Как запустить приложение, когда отображается диалоговое окно UAC? - PullRequest
8 голосов
/ 12 мая 2010

У меня есть приложение, которое я написал в .NET. Он должен оставаться запущенным и иметь доступ к рабочему столу, на котором открываются диалоговые окна UAC, и взаимодействовать с ним с помощью событий клавиатуры и мыши.

Это что-то вроде программы VNC. Представьте, что вы запускаете программу VNC и появляется окно UAC, и вы хотите, чтобы ваша программа VNC все еще могла контролировать рабочий стол с окном UAC , чтобы пользователь мог перемещать мышь и щелкать Кнопка ОК в диалоговом окне UAC. Может кто-нибудь сказать мне, как я буду делать это?

Спасибо

Ответы [ 5 ]

6 голосов
/ 12 мая 2010

Я бы посоветовал вам начать с чтения документации . Я предполагаю, что, возможно, вы могли бы открыть оконную станцию ​​и прикрепить к ней свой процесс, но я не очень знаком с этой областью Windows.

Редактировать 1:

В Windows XP мне удалось получить доступ к безопасному рабочему столу («winlogon») через OpenDesktop при работе в качестве SYSTEM; ACL на защищенном рабочем столе разрешает доступ только к учетной записи SYSTEM. Открыв его, я смог перечислить на нем окна, хотя их было всего несколько. Возможно, вы могли бы установить оконную ловушку и слушать для создания конкретного диалога. Я не уверен, что Vista изменила эту модель, так что, возможно, она не будет работать; Передо мной нет машины Vista, с которой можно проверить.

Редактировать 2:

Хорошо, я получил кое-что, что в основном работает (проверено на Windows 7). Во-первых, вы должны иметь сервис, работающий как SYSTEM. Из этого сервиса вам нужно запустить отдельное приложение в сеансе пользователя. Для этого перечислите все процессы, ищущие winlogon.exe, откройте его токен и CreateProcessAsUser. Укажите «WinSta0 \ Winlogon» для параметра lpDesktop в STARTUPINFO. Теперь у вас есть процесс, выполняющийся как SYSTEM в сеансе пользователя на рабочем столе «Winlogon». В новом процессе вы можете делать все, что захотите; Я провел быстрый тест с EnumDesktopWindows и смог получить класс окна и текст для различных окон, связанных с UAC («$$$ Secure UAP Background Window», «$$$ Secure UAP Background Fake Client Window» и т. Д.). Я не уверен, как определить, когда отображается приглашение UAC; для быстрого взлома вы можете просто запускать цикл каждые 100 мс в поисках окон UAC или чего-то еще. Я мог бы вставить некоторый код, если бы это помогло.

Редактировать 3:

Ok. Я написал сервис Win32, который принимает следующие параметры:

/ install - устанавливает сервис
/ uninstall - удаляет службу
/ сервис - работает как сервис; вызывается через SCM
/ client - работает как клиент; вызывается через CreateProcessAsUser

Единственный интересный код в режимах / service и / client.

В режиме / service перечисляет запущенные процессы через EnumProcesses и GetModuleFileNameEx, ища «winlogon.exe». Когда он находит его, он открывает свой токен и запускает себя в режиме / client через CreateProcessAsUser:

HANDLE hProcess = ...;
// winlogon.exe runs as SYSTEM in user's session; we need to run the same way
HANDLE hToken = NULL;
if(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &hToken))
{
    TCHAR szCommandLine[MAX_PATH];
    GetModuleFileName(NULL, szCommandLine, MAX_PATH);
    PathQuoteSpaces(szCommandLine);
    // run in /client mode
    _tcscat_s(szCommandLine, MAX_PATH, _T(" /client"));
    STARTUPINFO StartupInfo;
    ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
    StartupInfo.cb = sizeof(STARTUPINFO);
    // run on the Winlogon desktop
    StartupInfo.lpDesktop = _T("WinSta0\\Winlogon");
    PROCESS_INFORMATION ProcessInformation;
    ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    if(CreateProcessAsUser(hToken, NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
    {
        CloseHandle(ProcessInformation.hThread);
        ProcessInformation.hThread = NULL;
        CloseHandle(ProcessInformation.hProcess);
        ProcessInformation.hProcess = NULL;
    }
    CloseHandle(hToken);
    hToken = NULL;
}

В режиме / client он нажимает кнопку «Да» в приглашении UAC через несколько вызовов FindWindow и FindWindowEx. Вы можете использовать Spy ++, чтобы выяснить иерархию окон.

HWND hWnd = ...;
HWND hWndButton = FindWindowEx(hWnd, NULL, _T("Button"), NULL);
if(hWndButton != NULL)
{
    // see if this is the "Yes" button
    TCHAR szText[32];
    if(GetWindowText(hWndButton, szText, 32) && _tcsicmp(szText, _T("&Yes")) == 0)
    {
        // click it
        SendMessage(hWndButton, BM_CLICK, 0, 0);
    }
}

Способ, которым я проверяю это - придерживаться Сна (5000); в / клиентском коде. Затем я запускаю службу и сразу делаю что-то, что вызывает приглашение UAC (т.е. запускаю regedit). Через 5 секунд код / ​​client проснется и найдет и нажмет кнопку «Да». Вы можете запускать другие процессы на рабочем столе Winlogon; cmd.exe и spyxx.exe (Spy ++) являются наиболее полезными. К сожалению, файл explorer.exe вызывает много проблем при работе на рабочем столе Winlogon и не очень полезен. Чтобы попасть на рабочий стол Winlogon, вы можете запустить regedit, а затем Alt + Tab, чтобы переключиться на другое приложение. Если вы хотите стать модным, вы можете написать свою собственную утилиту переключения рабочего стола (используя функцию SwitchDesktop), чтобы вам не приходилось вызывать запрос UAC, чтобы попасть на рабочий стол Winlogon. Если вы хотите стать действительно модным, вы можете установить глобальный хук окна для мониторинга создания окна; когда должно появиться диалоговое окно UAC, вы можете нажать кнопку «Да». Впрочем, я не зашел так далеко.

4 голосов
/ 12 мая 2010

Проблема в том, что приглашение UAC не открывается на текущем рабочем столе, а на совершенно новом Безопасном рабочем столе , который приостанавливает все открытые в настоящее время рабочие столы.

Это сделано намеренно, поскольку программы не имеют права взаимодействовать с этим диалоговым окном.

Существует одно исключение: «доверенные процессы SYSTEM могут запускаться на защищенном рабочем столе», согласно этой записи в блоге .

0 голосов
/ 12 мая 2010

Вы не можете сделать это. По умолчанию, когда появляется приглашение UAC, оно фактически выполняется в изолированной WinStation, которая отличается от той, которая запускает «обычные» приложения. Эта WinStation изолирована специально для предотвращения взаимодействия пользовательских приложений с приглашением UAC. Он выглядит как ваш рабочий стол, потому что фон этого WinStation на самом деле является статическим растровым изображением вашего рабочего стола, каким оно было непосредственно перед отображением приглашения UAC.

Я подозреваю, что это может быть проблемой в версии VNC, которую вы используете, так как я уверен, что удаленный рабочий стол обеспечивает правильное поведение и позволяет пользователю по-прежнему взаимодействовать с приглашением UAC через клиент удаленного рабочего стола. Помните, что при работе с любым видом удаленного клиента (удаленный рабочий стол, VNC и т. Д.) Идея заключается в том, чтобы клиент позволял вам делать все, что вы обычно могли бы делать, если бы вы физически сидели за клавиатурой.

0 голосов
/ 12 мая 2010

Я считаю, что все, что вы видите на экране во время подсказки UAC, - это скриншот (кроме самого диалога)

0 голосов
/ 12 мая 2010

Я полагаю, что вам, вероятно, нужно работать как служба Windows, чтобы иметь возможность запускаться при активном UAC.

...