Задать вопрос
  • Можно ли упихать контролируемый invoke в smart pointer?

    opium
    @opium
    Просто люблю качественно работать
    через operator-> перехватить произвольный вызов не выйдет, прокси всё равно придётся описывать метод за методом. А если хватит своей реакции на FAILED(hr), то у #import (без raw_interfaces_only) обёртки уже зовут _com_raise_error, и его можно подменить через _set_com_error_handler(&MyHandler). Только обработчик не должен возвращать управление, подменить результат и продолжить так не получится. Для этого остаётся шаблон вида invoke(ptr, &IFoo::Bar, args...) на std::invoke с проверкой hr внутри.
    Ответ написан
    Комментировать
  • Архитектура для приложения, повышающего привилегии?

    VoidVolker
    @VoidVolker Куратор тега Windows
    Dark side eye. А у нас печеньки! А у вас?
    Просто запускать приложение сразу от имени администратора и не заниматься бесполезным усложнением. Не, если скучно и хочется приключений — то вперёд, никаких проблем. Передать состояние между потоками можно через обычный сокет, файл, да даже просто напрямик блок данных передать через чтение/запись в память процесса.
    Ответ написан
    8 комментариев
  • Архитектура для приложения, повышающего привилегии?

    opium
    @opium
    Просто люблю качественно работать
    а зачем городить с нуля? то что ты описал в пп 1-6 — это буквально COM Elevation Moniker, готовый Windows-примитив ровно под твой сценарий: CoGetObject с монитором вида Elevation:Administrator!new:{CLSID} сам поднимает elevated-инстанс через UAC, без клонирования процесса и без ручного маршалинга. Не хочешь COM — тот же движок без обвязки: MIDL + ncalrpc, proxy/stub генерятся сами, транспорт локальный. И не мельчи интерфейс, батчи вызовы на список путей — на каталоге с кучей файлов голый RPC на файл сожрёт всю экономию.
    Ответ написан
    5 комментариев
  • Как заблокировать входящие по подстроке идентификатора?

    @Int64_x86
    Я сделал через AccessibilityService - смотрит на экран когда звонок, читает текст и сверяет с черным списком. Пока проверяю на моем samsung s24 ultra. если все будет четко то выложу на 4pda
    Ответ написан
    2 комментария
  • Кто-нибудь писал на cpp2? Годится для работы?

    @res2001
    Developer, ex-admin
    Прочтите этот пост автора.
    Там найдете ответ на ваш вопрос.

    Если коротко - автор не позиционирует cppfront для конечного использования. Он предназначен для экспериментов и обкатки идей, после чего возможно внесение их на рассмотрение в стандарт С++. И автор не обещает никакой поддержки cppfront.

    Если вы готовы взять поддержку cppfront на себя, то можно использовать, если считает нужным.
    Ответ написан
    1 комментарий
  • Как сделать автокоммит текстового файла в git при сохранении в Notepad++?

    opium
    @opium
    Просто люблю качественно работать
    Раз самому сервис писать неохота — не пиши его руками, заверни готовый PowerShell-скрипт с FileSystemWatcher через nssm:
    nssm install AutoCommit powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\watcher.ps1"
    (путь к скрипту — обязательно полный, служба стартует не из твоей папки). Утилита сама регистрирует его как обычный Windows-сервис с автозапуском и рестартом при падении, никакого своего кода для демонизации писать не надо. Плюс работает для любого редактора, не только для Notepad++, в отличие от варианта через PythonScript.
    Ответ написан
    Комментировать
  • Как сделать автокоммит текстового файла в git при сохранении в Notepad++?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Можно сделать прямо внутри Notepad++ через плагин PythonScript.

    У PythonScript есть событие NOTIFICATION.FILESAVED, на которое можно повесить git add и git commit. Отдельный watcher или NppExec для этого не нужен.

    Проверил у себя — работает.

    Установка и настройка

    1. Открыть Plugins → Plugins Admin....
    2. Найти PythonScript, отметить его и нажать Install. Notepad++ после установки перезапустится.
    3. Открыть Plugins → PythonScript → Configuration....
    4. Для Initialisation выбрать ATSTARTUP. Заодно полезно включить Automatically open console on error, чтобы ошибки скрипта сразу были видны.
    5. Открыть Plugins → PythonScript → Scripts и startup (User). Если пользовательского startup.py ещё нет — создать через Plugins → PythonScript → New Script файл с именем startup.py.
    6. Вставить в него следующий код и сохранить:


    from Npp import notepad, NOTIFICATION
    import os
    import subprocess
    import datetime
    
    
    def on_save(args):
        filename = notepad.getBufferFilename(args["bufferID"])
        file_dir = os.path.dirname(filename)
    
        try:
            repo = subprocess.check_output([
                "git", "-C", file_dir,
                "rev-parse", "--show-toplevel"
            ]).strip()
        except subprocess.CalledProcessError:
            return
    
        rel_file = os.path.relpath(filename, repo)
    
        subprocess.call([
            "git", "-C", repo,
            "add", "--", rel_file
        ])
    
        changed = subprocess.call([
            "git", "-C", repo,
            "diff", "--cached", "--quiet",
            "--", rel_file
        ])
    
        if changed != 0:
            message = "autosave " + datetime.datetime.now().strftime(
                "%Y-%m-%d %H:%M:%S"
            )
    
            subprocess.call([
                "git", "-C", repo,
                "commit",
                "-m", message,
                "--", rel_file
            ])
    
    
    notepad.callback(on_save, [NOTIFICATION.FILESAVED])


    После перезапуска Notepad++ обработчик будет регистрироваться автоматически.

    При каждом сохранении файла скрипт:

    1. получает путь сохранённого файла;
    2. через git rev-parse --show-toplevel определяет его Git-репозиторий;
    3. добавляет в индекс только этот файл;
    4. создаёт commit, только если содержимое действительно изменилось.


    Если открытый файл находится не в Git-репозитории, ничего не происходит.

    Разумеется, git должен быть установлен и доступен через PATH, а файл должен находиться внутри уже созданного Git-репозитория.

    Есть только один нюанс: стабильная версия PythonScript, устанавливаемая через Plugins Admin, всё ещё использует встроенный Python 2.7. Поэтому скрипт написан без конструкций современных версий Python.

    Если Git нужен только ради истории изменений одного текстового файла, то есть ещё более простой вариант — встроенный в Notepad++:

    Settings → Preferences → Backup → Backup on save → Verbose backup


    Он сохраняет отдельную предыдущую версию файла при каждом сохранении.

    И ещё: локальный Git без push — это история версий, но не полноценный backup. При потере диска вместе с рабочей папкой пропадёт и каталог .git. Если нужна именно резервная копия, репозиторий надо периодически отправлять во внешнее хранилище.
    Ответ написан
    3 комментария
  • Как сделать простую рефлексию (стрингизацию имён типов) на C++23?

    opium
    @opium
    Просто люблю качественно работать
    в C++23 нормальной рефлексии нет вообще, P2996 (static reflection) это C++26, и то экспериментально: GCC 16 за флагом -freflection, у Clang свой форк от Bloomberg. Без макросов ближе всего трюк из nameof-cpp/magic_enum: указатель на статический член как NTTP, внутри шаблона парсишь __PRETTY_FUNCTION__ (или std::source_location::current().function_name()), там будет полное квалифицированное имя вроде Settings::Category1::Value1, откуда constexpr-парсером режешь и категорию, и имя настройки одним заходом.

    p.s. формат этой строки implementation-defined, для сериализации это риск на будущее, так что кодогенерация тут надёжнее чем экономия на макросах
    Ответ написан
    Комментировать
  • Используете ли вы static не inline, и для чего?

    @ReggieMan
    А чем inline переменные в хедере с C++17 хуже? Я просто пишу static int x = 5; прямо в классе, и все работает без отдельных cpp-файлов. Зачем усложнять
    Ответ написан
    Комментировать
  • Как заблокировать входящие по подстроке идентификатора?

    opium
    @opium
    Просто люблю качественно работать
    CallScreeningService работает не так просто как кажется: в onScreenCall() приходит урезанный Call.Details, только номер (handle) и служебные поля, getCallerDisplayName() там пустой.

    Название организации, которое рисует гугловский dialer, это его собственный Business Caller ID, не CNAM, и публичного API к нему нет — так что фильтровать офлайн по подстроке названия не выйдет.

    Рабочий вариант: свой CallScreeningService, номер из callDetails.getHandle(), сверка со своей локальной базой номер→категория, по совпадению "bank" в имени зовёшь respondToCall с setDisallowCall(true).
    Ответ написан
    2 комментария
  • Используете ли вы static не inline, и для чего?

    opium
    @opium
    Просто люблю качественно работать
    Похожий трюк масштабируется шире ресурсов: объявил static-поле в хедере без определения — если нужный .cpp не подключён к сборке, линковщик даст undefined reference. Так можно enforce'ить обязательную линковку конкретной единицы трансляции: регистрация плагина, feature-флаг, конфиг под сборку — забыл модуль, поймаешь на линковке, а не в рантайме.

    Плюс: меняется только инициализатор — правишь .cpp, а не хедер, остальные TU не пересобираются каскадом. До C++17, пока не было инлайн-переменных, это вообще был единственный вариант.
    Ответ написан
    Комментировать
  • Что означают буквы в скобках в разных частях браузера?

    VoidVolker
    @VoidVolker Куратор тега Windows
    Dark side eye. А у нас печеньки! А у вас?
    Хоткеи же. Это так-то всегда было нормой в ОС и в десктопных приложениях сразу в названии пункта меню или кнопки указывать хоткей для использовании данного элемента интерфейса.
    На уровне ОС настраивается тут:
    • Панель управления -> Специальные возможности -> Клавиатура -> Изменить действия для сочетания клавиш -> Подчёркивать клавиши доступа, когда они доступны

    Но это работает только с системными элементами. А многие современные приложения не используют системные элементы интерфейса и в таких приложения это всё зависит только от них самих.
    Ответ написан
    Комментировать
  • Доступен ли сейчас built-in VPN в Firefox for Android?

    opium
    @opium
    Просто люблю качественно работать
    На Android его тоже раскатывают, но не через about:config: смотри Настройки → VPN (в самом низу списка), там же логин в Mozilla Account. Флаги browser.ipProtection.* только включают видимость кнопки, в сам rollout по стране и когорте они не пускают. Россия пока не в списке (там США, UK, Германия, Франция, Канада и ещё почти три десятка стран) — так что пункта может просто не быть, хоть на Nightly 155, хоть на любой другой сборке.
    Ответ написан
    2 комментария
  • Схема в Telegram: "медсестра", звонок на номер и "авторизация пройдена", затем просят СНИЛС. Как это работает?

    CityCat4
    @CityCat4 Куратор тега Информационная безопасность
    Жил да был черный кот за углом...
    Работает довольно просто, весь расчет на психологию.

    1. "Медсестра" - начальный заход, нужен только для того, чтобы был звонок на указанный номер. Вместо "медсестры" может быть "электрик", "сантехник", "оператор домофонов" - кто угодно, тут неважно, главное, чтобы человек повелся и позвонил.
    2. Звонок по указанному номеру. Никакой авторизации там конечно нет, там стоит тупой бот, который запрограммирован произнести эту фразу. Почему именно так - чтобы человек напугался, подумал что взломали и начал дергаться.
    3. Обратный звонок (может не быть). Говорят, что плохо слышно, спрашивают СНИЛС - по СНИЛС можно на ГУ зайти - если сказать СНИЛС наверняка последует дальнейший развод про взлом ГУ, ааааа, спасайте деньги на безопасный счет!
    4. Так как фаза "обратный звонок" не прошла - с "якобы ГУ" позвонили самостоятельно и начали пугать - опять же в расчете, что чел испугается и начнет дергаться и тут опять конечно же ааааа, спасайте деньги!

    Ничего нового, кроме начального захода.
    Ответ написан
  • Как удалить элемент из LocalStorage?

    @7rows
    Frontend Разработчик / Vue / JS / TS / CSS
    Привет, смотри, есть несколько причин
    1- внутри renderTable() ты каждый раз добавляешь новый обработчик события на tbody, что приводит к дублированию. Лучше добавить его один раз вне этой функции.
    2-
    const isWatched = document.querySelector('#isWatched').cahecked;
    -
    тут у тебя кажется тоже ошибка
    3- чтобы удалить нужный фильм, нужно знать, какой именно элемент массива удалять. Удобно добавить каждому фильму уникальный id - если есть, если нет, то добавь randomUUId / Date
    Ну и далее, у тебя при удалении будет
    films = films.filter(film => film.id !== filmId);
            localStorage.setItem('films', JSON.stringify(films));

    4-
    edit: 'Редактировать',
            delete: 'Удалить'

    не имеет смысла хранить, это элементы интерфейса, но никак не данных

    Примерно такой код, он не идеален, но должен работать

    const form = document.querySelector('#film-form');
    const tbody = document.querySelector('#film-tbody');
    
    function getFilms() {
        return JSON.parse(localStorage.getItem('films')) || [];
    }
    
    function setFilms(films) {
        localStorage.setItem('films', JSON.stringify(films));
    }
    
    function renderTable() {
        const films = getFilms();
        tbody.innerHTML = '';
        films.forEach(film => {
            const row = document.createElement('tr');
            row.dataset.id = film.id;
            row.innerHTML = `
                <td>${film.title}</td>
                <td>${film.genre}</td>
                <td>${film.releaseYear}</td>
                <td>${film.isWatched ? "Да" : "Нет"}</td>
                <td>
                    <button class="edit">Редактировать</button>
                    <button class="delete">Удалить</button>
                </td>
            `;
            tbody.appendChild(row);
        });
    }
    
    function addFilmToLocalStorage(film) {
        const films = getFilms();
        film.id = Date.now();
        films.push(film);
        setFilms(films);
        renderTable();
    }
    
    function handleFormSubmit(e) {
        e.preventDefault();
        const title = document.querySelector('#title').value;
        const genre = document.querySelector('#genre').value;
        const releaseYear = document.querySelector('#releaseYear').value;
        const isWatched = document.querySelector('#isWatched').checked;
        addFilmToLocalStorage({ title, genre, releaseYear, isWatched });
        form.reset();
    }
    
    tbody.addEventListener('click', e => {
        const target = e.target;
        if (target.classList.contains('delete')) {
            const row = target.closest('tr');
            const id = Number(row.dataset.id);
            let films = getFilms();
            films = films.filter(f => f.id !== id);
            setFilms(films);
            renderTable();
        }
    });
    
    form.addEventListener('submit', handleFormSubmit);
    renderTable();


    Ну и лучше, в таких случаях кидать ссылку на пример
    Ответ написан
    1 комментарий
  • Концепт проверки совместимости с шаблонным конструктором?

    opium
    @opium
    Просто люблю качественно работать
    Вывод шаблонного параметра квалификационных преобразований не делает, а is_same_v требует точного тождества. Глянь, что реально выводится: в Output(const Args&...) для L"Test" получается Args = wchar_t[5], без const — его съедает const в самом параметре. Дальше convertible_to берёт declval<Args>(), массив распадается в wchar_t*, тоже без const, и конструктор выводит T = wchar_t*. is_same_v<wchar_t*, const wchar_t*> даёт false, конструктора нет, концепт не прошёл; gcc так и пишет: [with Args = {wchar_t [5]}]. С нешаблонным Argument(const wchar_t*) работало потому, что там это доводит перегрузка. Вторая ветка вдобавок мёртвая: у параметра по значению вывод срезает ссылку и верхний const. Нужен перечень типов — сравнивай decay_t<T>, а не remove_cvref_t: тот массив не распадает.
    Ответ написан
    Комментировать
  • Большая пауза перед скачиванием из браузера - это смерть SSD?

    opium
    @opium
    Просто люблю качественно работать
    SSD вряд ли виноват — с других осей тот же диск летает сразу. About:blank сам по себе не доказывает SmartScreen, так иногда просто открывает вкладку сайт-источник. Тест простой: качни тот же файл другим браузером на винде, потом на минуту выруби Defender SmartScreen (Edge → Конфиденциальность и безопасность → защита от вредоносных сайтов и загрузок) и попробуй снова, не забудь включить обратно. Если пауза пропадёт, дело в проверке репутации файла, не в SSD. А 28% на Intel 660 всё равно повод сделать бэкап.
    Ответ написан
    Комментировать
  • Стоит ли оставлять Windows 7 на i5-12400F и RTX 3050, если система завелась через модифицированный .inf (драйвер 474.11)?

    VoidVolker
    @VoidVolker Куратор тега Железо
    Dark side eye. А у нас печеньки! А у вас?
    Главная проблема семёрки сегодня — это отказ поддержки семёрки со стороны производителей ПО/игр и невозможности использовать это ПО/игры в семёрке.
    Ответ написан
    4 комментария
  • Какой метод биометрической аутентификации лучше для СКУД в офисе с высокой проходимостью: лицо, отпечаток или карта?

    @Drno
    физика всегда надёжнее всего.
    руки могут быть мокрыми \ грядными
    лицо может быть небритым итд..(пока я норм сработку толька на айфонах видел)

    мой личный выбор - физ носитель, там где это возможно
    Ответ написан
    1 комментарий
  • Возможно ли сделать скрин действующего окна через Alt + PrtSc на С++?

    opium
    @opium
    Просто люблю качественно работать
    PrintWindow() с флагом PW_RENDERFULLCONTENT, доступен с Win8.1. Ровно то что Alt+PrtSc делает под капотом — DWM рисует DirectX-слой без хуков в видеопамять:
    PrintWindow(hWnd, hdc, PW_RENDERFULLCONTENT);
    p.s. и rect.right+8 в CreateCompatibleBitmap у тебя не ширина, а координата, размер будет кривой.
    Ответ написан
    1 комментарий