
Программа-сервис 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
30.07.2010
04.10.2010
05.10.2010
13.12.2010
14.12.2010
27.04.2011
11.07.2011
18.07.2011
19.09.2011
10.02.2012
11.02.2012
24.03.2012
26.03.2012
04.02.2013
07.05.2014
28.08.2014
14.02.2015
20.02.2015
20.02.2015
15.02.2016