powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как служба под системной учеткой может получить скриншот экрана активного пользователя
5 сообщений из 5, страница 1 из 1
Как служба под системной учеткой может получить скриншот экрана активного пользователя
    #39751240
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!

Делаю сервис, который будет снимать скриншот экрана текущего (активного) пользователя и записывать его в файл BMP.
Служба устанавливается и запускается под системной учетной записью.

Компилятор Bloodshed Dev C++ 5.6.3

Вот текст main.cpp:

Код: plaintext
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.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
#include <windows.h>
#include <fstream>

#define SERVICE_NAME TEXT("Screen control service")
#define COMMAND_INSTALL   "install"
#define COMMAND_UNINSTALL "uninstall"
 
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
 
HANDLE stopServiceEvent = 0;
 
using namespace std;
//#define  PREFIX    "scr"
 
void ScreenShotToFile(LPCSTR wzTemp)
{
	// copy screen to bitmap
	POINT a, b;
	
	a.x = 0;
	a.y = 0;
	b.x = GetSystemMetrics(SM_CXSCREEN);
	b.y = GetSystemMetrics(SM_CYSCREEN);
	
	//HDC     hScreen = GetDC(handle);	
	//HDC     hScreen = GetDCEx(NULL);
	//HDC     hScreen = CreateDC("DISPLAY/SAM06A4/5&E615B6C&0&UID1048832", NULL, NULL, NULL); 
	//HDC     hScreen = GetDC(NULL);
	//HDC     hScreen = GetDC(0);
	//HWND    handle = GetDesktopWindow();
	HDC     hScreen = GetDC(NULL);
	HDC     hDC     = CreateCompatibleDC(hScreen);
	HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x-a.x), abs(b.y-a.y));
	HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
	SelectObject(hDC, hBitmap);
	
	BOOL    bRet    = BitBlt(hDC, 0, 0, abs(b.x-a.x), abs(b.y-a.y), hScreen, a.x, a.y, SRCCOPY);
	
	// save bitmap to file
	DWORD* byteImage = new DWORD[b.x * b.y];
	
	BITMAPINFO* bmInfo = new BITMAPINFO();
	
	bmInfo->bmiHeader.biWidth = b.x;
	bmInfo->bmiHeader.biHeight = b.y;
	bmInfo->bmiHeader.biPlanes = 1;
	bmInfo->bmiHeader.biCompression = BI_RGB;
	bmInfo->bmiHeader.biBitCount = 16;
	bmInfo->bmiHeader.biSize = sizeof(bmInfo->bmiHeader);
	
	GetDIBits(hDC, hBitmap, 0, b.x, byteImage, bmInfo, DIB_RGB_COLORS);
	
	ofstream file;
	BITMAPFILEHEADER* bmfh = new BITMAPFILEHEADER();
	
	file.open(wzTemp, ios::binary|ios::trunc|ios::out);
	
	bmfh->bfType = 0x4d42;
	bmfh->bfReserved1 = 0;
	bmfh->bfReserved2 = 0;
	bmfh->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + (b.x * b.y);
	
	file.write((char*)bmfh, sizeof(BITMAPFILEHEADER));
	file.write((char*)bmInfo, sizeof(BITMAPINFO));
	file.write((char*)byteImage, b.x * b.y * 4);
	
	// clean up
	DeleteDC(hDC);
	ReleaseDC(NULL, hScreen);
	DeleteObject(hBitmap);
}

void WINAPI ServiceControlHandler(DWORD controlCode)
{
   switch (controlCode)
   {
      case SERVICE_CONTROL_INTERROGATE:
      break;
 
      case SERVICE_CONTROL_SHUTDOWN:
      case SERVICE_CONTROL_STOP:
         serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
         SetServiceStatus(serviceStatusHandle, &serviceStatus);
 
         SetEvent(stopServiceEvent);
      return;
 
      case SERVICE_CONTROL_PAUSE:
      break;
 
      case SERVICE_CONTROL_CONTINUE:
      break;
 
      default:
         if (controlCode >= 128 && controlCode <= 255)
         {
            break;
         }
         else
         {
            break;
         }
   }
 
   SetServiceStatus(serviceStatusHandle, &serviceStatus);
}

void WINAPI ServiceMain(DWORD argc, TCHAR* argv[])
{
	// initialise service status
	serviceStatus.dwServiceType = SERVICE_WIN32;
	serviceStatus.dwCurrentState = SERVICE_STOPPED;
	serviceStatus.dwControlsAccepted = 0;
	serviceStatus.dwWin32ExitCode = NO_ERROR;
	serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
	serviceStatus.dwCheckPoint = 0;
	serviceStatus.dwWaitHint = 0;
 
	serviceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceControlHandler);
	
	if (!serviceStatusHandle)
	{
		return;
	}
	serviceStatus.dwCurrentState = SERVICE_START_PENDING;
	SetServiceStatus(serviceStatusHandle, &serviceStatus);
	
	stopServiceEvent = CreateEvent(0, FALSE, FALSE, 0);
	
	serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
	serviceStatus.dwCurrentState = SERVICE_RUNNING;
	SetServiceStatus(serviceStatusHandle, &serviceStatus);
 
	//LPCSTR Prefix = PREFIX;
	//CHAR TempWinDir[255];
	//GetTempPath(255, TempWinDir); 
	//LPTSTR wzTemp = new TCHAR[MAX_PATH]; 
	//GetTempFileName(TempWinDir, Prefix, 0, wzTemp); 
 
	CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ScreenShotToFile, (LPVOID)"C:/image.bmp", 0, 0);
	WaitForSingleObject(stopServiceEvent, INFINITE);
	
	serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
	SetServiceStatus(serviceStatusHandle, &serviceStatus);
	
	CloseHandle(stopServiceEvent);
	stopServiceEvent = 0;
	
	serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
	serviceStatus.dwCurrentState = SERVICE_STOPPED;
	SetServiceStatus(serviceStatusHandle, &serviceStatus);
}

void RunService()
{
	SERVICE_TABLE_ENTRY serviceTable[] =
	{
		{(LPSTR) SERVICE_NAME, ServiceMain},
		{0, 0}
	};
	
	StartServiceCtrlDispatcher(serviceTable);
}

void InstallService()
{
	SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
	
	if (serviceControlManager)
	{
	  TCHAR path[_MAX_PATH + 1];
	  if (GetModuleFileName(0, path, sizeof(path) / sizeof(*path)) > 0)
	  {
	     SC_HANDLE service = CreateService(serviceControlManager,
	                                       SERVICE_NAME, SERVICE_NAME,
	                                       SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
	                                       SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
	                                       0, 0, 0, 0, 0);
	     if (service)
	     {
	        CloseServiceHandle(service);
	     }
	  }
	
	  CloseServiceHandle(serviceControlManager);
	}
}

void UninstallService()
{
	SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
	
	if (serviceControlManager)
	{
	  SC_HANDLE service = OpenService(serviceControlManager, SERVICE_NAME, SERVICE_QUERY_STATUS | DELETE);
	  if (service)
	  {
	     SERVICE_STATUS serviceStatus;
	     if (QueryServiceStatus(service, &serviceStatus))
	     {
	        if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
	        {
	           DeleteService(service);
	        }
	     }
	
	     CloseServiceHandle(service);
	  }
	
	  CloseServiceHandle(serviceControlManager);
	}
}

int main(int argc, char** argv)
{
	if (argc > 1 && strcmp(argv[1], COMMAND_INSTALL) == 0)
	{
	  InstallService();
	}
	else if (argc > 1 && strcmp(argv[1], COMMAND_UNINSTALL) == 0)
	{
	  UninstallService();
	}
	else
	{
	  RunService();
	}
	return 0;
}


Best regards, Ildar
...
Рейтинг: 0 / 0
Как служба под системной учеткой может получить скриншот экрана активного пользователя
    #39751242
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема в том, что файл создается, но он не содержит нули, т.е. черный экран.
В файле нет самого скриншота.
Как сделать так, чтобы там был скриншот?

Заранее Благодарю!
...
Рейтинг: 0 / 0
Как служба под системной учеткой может получить скриншот экрана активного пользователя
    #39751244
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Грубо говоря в файле картинки чернота и все.
А хотелось бы снимок экрана пользователя.
_Ildar_,
...
Рейтинг: 0 / 0
Как служба под системной учеткой может получить скриншот экрана активного пользователя
    #39751296
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выбрать правильную WinStation из всех, имеющихся в EnumWindowStations.
Выбрать правильный Desktop для этой WinStation из имеющихся в EnumDesktops.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как служба под системной учеткой может получить скриншот экрана активного пользователя
    #39751363
Фотография feature
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Ildar_Компилятор Bloodshed Dev C++ 5.6.3
Это текстовый редактор, а-ля IDE, но отнюдь не компилятор.
При использовании Dev C++ компилятором является GCC из MinGW или же TDM-GCC

Начиная с Windows Vista все сервисы/службы работают на WinSta0 (Windows Station), которая специально под них и выделена.
Пользователи при интерактивном логоне попадают в другую WinSta.

Внутри каждой WinSta может быть несколько десктопов (по факту используется только лишь один).

Поскольку сервисы/службы живут на WinSta0, то и взаимодействовать с пользователем через GUI примитивы могут лишь в рамках того десктопа, который есть на этой самой WinSta0.
Вот начиная с Vista на эту WinSta0 пользователи никогда не логинятся, а зайдя в систему всегда попадают в другую WinSta.

Потому сервису/службе надо спрашивать ОС есть ли интерактивно залогиненный пользователь и на какой именно из WinSta. После этого получать доступ к GUI-примитивам, типа окон приложений на десктопе в этом WinSta.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как служба под системной учеткой может получить скриншот экрана активного пользователя
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]