Скриншот из сервиса Windows 7

Программа-сервис Windows XP, делающая снимки экрана, после переноса на Windows 7 начала сохранять вместо снимков просто белый фон.
Чтобы использовать основанную на коде ниже программу rooshot, распакуйте архив в отдельную папку, установите ее как сервис (командой rooshot.exe /install), задайте параметры в конфигурационном файле rcshot.conf и запускайте через диспетчер служб. Удаление – командой rooshot.exe /uninstall. Программа будет автоматически делать снимки экрана согласно указанным в конфиге параметрам.
![]() |
Скачать программу rooshot версия 0.1 (07.08.12) | 0.3 Мб | stable |
Дело в том, что начиная с Windows Vista, служба, запущенная от имени SYSTEM, более не может взаимодействовать с рабочим столом – службы теперь запускаются в изолированном сеансе (сессии) и загрузка своего процесса приведет к попытке запуска в неверном (вошедшего в систему пользователя) сеансе. Решить проблему можно, получив сессию залогинившегося пользователя. Вкратце, этот код делает следующее:
- Получает токен вошедшего в систему в данный момент пользователя, используя функцию WtsGetActiveConsoleSessionID
- Далее получает пользовательский токен, назначенный процессу (токен для службы от имени SYSTEM)
- Затем этот токен дублируется
- У скопированного токена изменяется сеанс (на вошедшего пользователя)
- Используя CreateProcessAsUser запускается процесс с измененным пользовательским токеном
Процесс с системными правами, но будучи запущенным от имени вошедшего в систему пользователя в Windows 7, также позволит корректно работать GUI-программе как и любой другой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
... function WTSGetActiveConsoleSessionId: THandle; external 'Kernel32.dll' name 'WTSGetActiveConsoleSessionId'; function CreateEnvironmentBlock(var lpEnvironment: Pointer; hToken: THandle; bInherit: BOOL): BOOL; stdcall; external 'userenv.dll'; function ProcessIdToSessionId(dwProcessID : DWORD; pSessionID : PDWORD) : BOOL; stdcall; external 'Kernel32.dll'; function WTSQueryUserToken(SessionId: DWORD; phToken : pHandle) : bool; stdcall; external 'wtsapi32.dll'; ... const TOKEN_ADJUST_SESSIONID = $0100; SE_DEBUG_NAME = 'SeDebugPrivilege'; TokenSessionId = 12; ... function LaunchApplication(FileName: string): Boolean; var pi: PROCESS_INFORMATION; si: STARTUPINFO; dwSessionId, winlogonPid: DWORD; hUserToken, hUserTokenDup, hPToken, hProcess, hsnap: THandle; dwCreationFlags: DWORD; procEntry: TProcessEntry32; winlogonSessId: DWORD; tp, tpko: Windows.TTokenPrivileges; Buffer: DWORD; lpenv: pointer; begin Result := False; dwSessionId := WTSGetActiveConsoleSessionId; hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap = INVALID_HANDLE_VALUE) then begin Result := False; Exit; end; procEntry.dwSize := sizeof(TPROCESSENTRY32); if (not Process32First(hSnap, procEntry)) then begin Result := False; Exit; end; winlogonPid := 0; repeat begin winlogonSessId := 0; if (ProcessIdToSessionId(procEntry.th32ProcessID, @winlogonSessId) and (winlogonSessId = dwSessionId)) then begin winlogonPid := procEntry.th32ProcessID; break; end; end; until (not Process32Next(hSnap, procEntry)); WTSQueryUserToken(dwSessionId, @hUserToken); dwCreationFlags := NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE; ZeroMemory(@si, sizeof(STARTUPINFO)); si.cb := sizeof(STARTUPINFO); si.lpDesktop := PChar('Winsta0\Default'); ZeroMemory(@pi, sizeof(pi)); hProcess := OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid); if (not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE, hPToken)) then begin LogPrint('OpenProcessToken : ' + SysErrorMessage(GetLastError)); Result := False; end; if (not LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid)) then begin LogPrint('LookupPrivilegeValue : ' + SysErrorMessage(GetLastError)); Result := False; end; tp.PrivilegeCount := 1; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; if not DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, nil, SecurityIdentification, TokenPrimary, hUserTokenDup) then begin LogPrint('DuplicateTokenEx: ' + SysErrorMessage(GetLastError)); Result := False; end; if not SetTokenInformation(hUserTokenDup, TTokenInformationClass(ord(TokenSessionId)), @dwSessionId, sizeof(dwSessionId)) then begin LogPrint('SetTokenInformation : ' + SysErrorMessage(GetLastError)); Result := False; end; if (not AdjustTokenPrivileges(hUserTokenDup, FALSE, tp, sizeof(tp), tpko, Buffer)) then begin LogPrint('AdjustTokenPrivileges: ' + SysErrorMessage(GetLastError)); end; lpEnv := nil; if (CreateEnvironmentBlock(lpEnv, hUserTokenDup, TRUE)) then begin dwCreationFlags := dwCreationFlags or CREATE_UNICODE_ENVIRONMENT or PROFILE_USER; end else lpEnv := nil; CreateProcessAsUser(hUserTokenDup, PChar(FileName), nil, nil, nil, FALSE, dwCreationFlags, lpEnv, nil, si, pi); CloseHandle(hProcess); CloseHandle(hUserToken); CloseHandle(hUserTokenDup); CloseHandle(hPToken); end; |
Артур
14.05.2010 @ 12:20
другие программы не работает, белый файл
эта работает
Ренат
30.07.2010 @ 06:01
Здравствуйте,а почему имена файлов только вида shotdesk_ххх.jpg?
где задается имя скриншота?
Nat3el
04.10.2010 @ 17:50
Как у вас реализуется скриншот? Есть аська?
Uchla
05.10.2010 @ 20:31
Не совсем понял вопроса – в каком смысле „как реализуется“?
Листинг функции скриншота? Напишите мне на E-mail там и в аське спишемся
Vener P
13.12.2010 @ 22:55
Здравствуйте, uhla
Не понял как запустить программу? – при запуске ничего не происходит.
Uchla
14.12.2010 @ 07:07
Распакуйте программу куда-нибудь, например, в C:\Program files\rooshot
Затем меню „Пуск“ > „Выполнить“, введите здесь
„C:\Program files\rooshot\rooshot.exe“ /install и нажмите enter, кавычки не забудьте.
При запуске и не будет ничего происходить, просто будет появляться скриншот рабочего стола в папке указанной в rooshot.conf
Serge
27.04.2011 @ 14:44
hello!
В описании не написано программа может сохранять на общую папку или не может?
fgdgdfgdfgdf
11.07.2011 @ 16:40
очень бедная програма, настроек нет
только 1 файл
другие программы умеют в 100 раз больше этой
Uchla
18.07.2011 @ 16:41
Да, умеют больше в 100 раз.
Только скриншот не делают на Win7.
Гость
19.09.2011 @ 20:42
Спасбо большое
Поставил всем сотрудникам, доступ к папке со скринами закрыл через „безопасность“ и открыл ее на чтение по сети
Гость
10.02.2012 @ 15:15
До входа в windows 7 где контрол альт делете тоже делает белые снимки.
начинает делать снимки когда сотрудник войдет.
Uchla
12.02.2012 @ 00:43
Версия beta же пока – главное работает, допилю и это
Yura80
24.03.2012 @ 19:22
Эта софтина умеет сохранять скрины на сетевую шару?
Uchla
26.03.2012 @ 08:10
Да, с UNC-путями проблем нет, можете писать в конфиг строчки вида directory=\\10.20.11.240\scrs
Влад
04.02.2013 @ 17:26
Любобытная программа)
Uchla, а есть ли способ обнаружить факт срабатывания этой программы на ПК с windows 7? Например с помощью оснастки perfmon (системный монитор). Хотелось бы увидеть каким то образом не мониторит ли меня самого кто-нибудь аналогичной программой.
Может есть параметр в permon который покажет срабатывание функции windows 7, отвечающей за создание скриншота?
Alexander
07.05.2014 @ 16:47
Спасибо за код, хотя бы один рабочий вариант запуска GUI-шного приложения под седьмыми виндами
Uchla
28.08.2014 @ 20:47
Нынче уже под восьмыми виндами сидят :-)
Nick
14.02.2015 @ 18:42
А весь исходник программы нельзя ли выложить? Ну или на мыло отправить. Обязуюсь не афишировать его, если что…
Uchla
20.02.2015 @ 12:36
Nick
rooshot01Code.cab
Nick
20.02.2015 @ 17:25
Огромное спасибо, подправил немножко под свои нужды, все прекрасно работает!
Sharki
15.02.2016 @ 18:21
А полный исходник самого сервиса можно посмотреть