Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
al-tom

Службы и GDI

29.11.2013, 15:47. Показов 961. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех.
Есть Windows служба:

C++
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
  SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
  if(!hSCManager) {
    return false;
  }
  
  GetModuleFileName(NULL, servicePath, MAX_PATH);
  DWORD wver = LOWORD(GetVersion());
  wver = (LOBYTE(wver) << 8) + HIBYTE(wver);
  DWORD stype = SERVICE_WIN32_OWN_PROCESS;
  if (wver < 0x0600) {
    stype |= SERVICE_INTERACTIVE_PROCESS;
  }
  SC_HANDLE hService = CreateService(
     hSCManager,
     serviceName,
     serviceName,
     SERVICE_ALL_ACCESS,
     stype,
     SERVICE_AUTO_START,
     SERVICE_ERROR_NORMAL,
     servicePath,
     NULL, NULL, NULL, NULL, NULL
  );
 
  CloseServiceHandle(hService);
  CloseServiceHandle(hSCManager);

Служба запускает другой процесс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  memset(&si, 0, sizeof(si));
  si.cb = sizeof(si);
  memset(&pi, 0, sizeof(pi));
  
  HANDLE proc = GetCurrentProcess();
  HANDLE cur_token, new_token;
  DWORD session = WTSGetActiveConsoleSessionId();
  
  if (!OpenProcessToken(proc, TOKEN_DUPLICATE, &cur_token)) {
    return false;
  }
  if (!DuplicateTokenEx(cur_token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &new_token)) {
    return false;
  }
  if (!SetTokenInformation(new_token, (TOKEN_INFORMATION_CLASS) TokenSessionId, &session, sizeof(session))) {
    return false;
  }
 
  CreateProcessAsUser(new_token, NULL, "program.exe scr", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
 
  CloseHandle(token);
  CloseHandle(userToken);

Этот процесс занимается снятием скриншотов:

C++
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
  HDC winDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  HDC bmpDC = CreateCompatibleDC(winDC);
 
  int width = GetDeviceCaps(winDC, HORZRES);
  int height = GetDeviceCaps(winDC, VERTRES);
 
  BITMAPINFOHEADER bmpInfoHeader;
  BITMAPFILEHEADER bmpFileHeader;
 
  bmpFileHeader.bfType = 0x4d42;
  bmpFileHeader.bfSize = 0;
  bmpFileHeader.bfReserved1 = 0;
  bmpFileHeader.bfReserved2 = 0;
  bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
  bmpInfoHeader.biSize = sizeof(bmpInfoHeader);
  bmpInfoHeader.biWidth = width;
  bmpInfoHeader.biHeight = height;
  bmpInfoHeader.biPlanes = 1;
  bmpInfoHeader.biBitCount = 24;
  bmpInfoHeader.biCompression = BI_RGB;
  bmpInfoHeader.biSizeImage = width * height * 3;
  bmpInfoHeader.biXPelsPerMeter = 0;
  bmpInfoHeader.biYPelsPerMeter = 0;
  bmpInfoHeader.biClrUsed = 0;
  bmpInfoHeader.biClrImportant = 0;
  
  BITMAPINFO info;
  info.bmiHeader = bmpInfoHeader;
 
  void* memory;
  HBITMAP bitmap;
  bitmap = CreateDIBSection(winDC, &info, DIB_RGB_COLORS, &memory, NULL, 0);
  SelectObject(bmpDC, bitmap);
  if (!BitBlt(bmpDC, 0, 0, width, height, winDC, 0, 0, SRCCOPY | CAPTUREBLT)) {
    return false;
  }
 
  FILE *f = fopen("scrsht.bmp", "wb");
  fwrite(&bmpFileHeader, 1, sizeof(BITMAPFILEHEADER), f);
  fwrite(&bmpInfoHeader, 1, sizeof(BITMAPINFOHEADER), f);
  fwrite(memory, 1, bmpInfoHeader.biSizeImage, f);
  fclose(f);

Проблема заключается в том, что при работе под Windows XP приходится делать службу интерактивной
(иначе на скриншоте получаем черный прямоугольник), а интерактивные службы могут быть запрещены на машине клиента.
Но, коль скоро скриншоты делает не служба, а запущенный процесс, напрашивается вывод о том, что процесс
наследует какие-то права службы, которые мешают ему получить доступ к консоли.
При этом, даже в случае интерактивной службы, при отображении экрана приветствия получается черный прямоугольник.
По некоторым причинам служба и дочерний процесс представлены одним exe файлом, но непосредственно функционал
(запуск дочернего процесса и снятие скриншотов) расположен в dll (общей). Было сомнение по поводу того, что
проблема может быть связана с загрузкой этой dll из сервиса и последующим использованием ее же в дочернем
процессе, но разнесение функционала по разным dll не помогло.
Возможно, я не стал бы биться над решением этой задачи, списал бы это на ограничения винды, если бы не TightVNC,
которая производит аналогичные манипуляции, при этом не регистрируя сервис как интерактивный.
Собственно, отсюда 2 вопроса:
1. Какие права нужно добавить/отобрать у процесса, чтобы его работа не зависела от настроек службы (если проблема в правах)?
2. Что может мешать получению скриншота с экрана приветствия?
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.11.2013, 15:47
Ответы с готовыми решениями:

Есть ли в WPF полноценная замена GDI+? Чтобы можно было всё, что можно в GDI+? Просто думаю углубляться в работу с изображениями в WPF или GDI.
Ну собственно весь вопрос в заголовке темы.

Не удаётся запустить службы криптографии и некоторые другие важные службы
Итак, расскажу всю историю по порядку. Где-то с полгода назад появилась проблема, что звук, примерно, после часа работы, пропадал,...

Остановка и запуск службы(сервиса) из другой службы или из приложения не используя консоль
Добрый день! Компилятор Embarcadero XE8 Скажите, как можно остановить и запустить некую службу(сервис) зная его имя (например...

2
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
29.11.2013, 18:00
Цитата Сообщение от al-tom Посмотреть сообщение
Что может мешать получению скриншота с экрана приветствия?
если имеется в виду заставка при запуске windows то надо запустить вашу службу до запуска winlogon.exe
Цитата Сообщение от al-tom Посмотреть сообщение
Какие права нужно добавить/отобрать у процесса, чтобы его работа не зависела от настроек службы (если проблема в правах)?
о сервисах и прочее... MSDN - About Window Stations and Desktops
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.11.2013, 18:20
Во-первых, уберите флаг SERVICE_INTERACTIVE_PROCESS.
Он работает только до Vista и только для первого залогиненного пользователя.
И вреда от него, судя по расползшимся по интернету слепо копируемым примерам,
намного больше, чем пользы.

Во-вторых, Вы для создания нового процесса берете access token службы, соответственно,
процесс здесь будет запускаться от имени SYSTEM, а не пользователя. Если нужно запускать в
контексте пользователя, лучше WTSQueryUserToken и затем CreateProcessAsUser. Только еще
нужно создать блок переменных окружения - CreateEnvironmentBlock. Кстати, в этом случае
устанавливать ID сессии для нового токена не нужно, т.к. его access token уже содержит
ID сессии пользователя.

В-третьих, в STARTUPINFO нужно вписать имя оконной станции и десктопа, на котором будет
создан новый процесс (если этого не сделать, он унаследует эти параметры от службы).
Т.е. STARTUPINFO::lpDesktop = L"WinSta0\\Default". Ну или другой десктоп, например "WinSta0\\Winlogon".

В-четвертых, пользоваться WTSGetActiveConsoleSessionId ненадежно. При некоторых условиях
она может вернуть ID совсем не той сессии, в которой залогинен пользователь. Корректный
вариант - подписаться в службе на событие SERVICE_CONTROL_SESSIONCHANGE и получать
ID соответствующего пользователя там.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.11.2013, 18:20
Помогаю со студенческими работами здесь

Связь приложения и службы (передача сообщений службы в форму)
Здравствуйте, при написании службы столкнулся с такой проблемкой, служба получает некие данные, и необходимо их выводить в форму, как можно...

D7, запуск службы из под службы, возможно ли такое?
Hello All. Необходимо написать службу которая будет через определенное время (каждые 5 минут) проверять существует (зарегистрирована) ли...

В чём отличие приложения службы WCF от библиотеки службы WCF
Вот читаю книгу по WCF. Создал проект, и думаю, а в чём же основное отличие? Библиотека как-то проще, как я понял. Уже почти всё...

GDI
Ребята, привет. Не знаю, с чего начать. Нужен примерчик использования интерфейса графического устройства. Что-нибудь нарисовать,...

COM GDI+
Добрый день. Было запланировано создание type library под интерфейсы gdi+, которые описаны в msdn. При поиске идентификаторов CLSID...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru