Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как послать сообщение сервису? 
:(
    Опции темы
danilsl
Дата 30.8.2007, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 78
Регистрация: 15.3.2006

Репутация: нет
Всего: нет



Привет Всем.
Я пишу системный сервис, который будет размножать потоки. О завершении потоков я хочу уведомлять основной поток сервиса через системные сообщения. Если я правильно понял смысл системных сообщений, ловить их могут только окна, неважно видимые или нет. С помощью проги WinSigh я нашёл, что процесс сервиса создаёт два каких-то окна (Скриншот в прикреплённом файле, 33 кб). В оба этих окна я пытался слать сообщения (из внешней проги), однако эффекта ноль. Вот сам код сервиса:
Код
unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

const
  WM_TEST = WM_APP+1;

type
  TTestSrv = class(TService)
  private
    { Private declarations }
    procedure ProcessMsg(var Msg:TMessage); message WM_TEST;
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  TestSrv: TTestSrv;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  TestSrv.Controller(CtrlCode);
end;

function TTestSrv.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TTestSrv.ProcessMsg(var Msg: TMessage);
begin
  ShowMessage('Словил');
end;

end.

Сервис интерактивный, так что ShowMessage вылезет. Сообщения слал тремя способами: SendMessage, PostMessage, PostThreadMessage. Кроме того перебрал все хэндлы, которые нашёл в объектах Application и сервиса.
Возможно ли вообще заставить сервис ловить эти сообщения? Или всё равно придётся создавать скрытое окно?

Вот в этом варианте сообщения ловятся, но это дополнительное окно smile  smile 
Код

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

type
  TTestSrv = class(TService)
    procedure ServiceStart(Sender: TService; var Started: Boolean);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  TestSrv: TTestSrv;

implementation

{$R *.DFM}

uses
  MsgHookForm;

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  TestSrv.Controller(CtrlCode);
end;

function TTestSrv.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TTestSrv.ServiceStart(Sender: TService; var Started: Boolean);
begin
  PostMessage(Form1.Handle, WM_APP+1, 0, 0);
end;

end.

Код

unit MsgHookForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const
  WM_TEST = WM_APP+1;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
    procedure ProcessMsg(var Msg:TMessage); message WM_TEST;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ProcessMsg(var Msg: TMessage);
begin
  ShowMessage('Словил');
end;

end.



Это сообщение отредактировал(а) danilsl - 30.8.2007, 23:55

Присоединённый файл ( Кол-во скачиваний: 30 )
Присоединённый файл  WinSight.JPG 32,31 Kb
PM MAIL   Вверх
NiJazz
Дата 31.8.2007, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 1
Всего: 23



danilsl, лучше избегать создания интерактивных сервисов. Если нужен диалог с пользователем, то лучше для этого создать отдельное GUI-приложение, которое будет общаться с сервисом посредством каких-либо стандартных механизмов (pipes, sockets). При такой архитектуре и проблем взаимодействия с сервисом не будет и у самого сервиса будет меньше проблем (особенно в поздних версиях винды).
PM MAIL   Вверх
NiJazz
Дата 31.8.2007, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 1
Всего: 23



Services running in an elevated security context, such as the LocalSystem account, should not create a window on the interactive desktop, because any other application that is running on the interactive desktop can interact with this window. This exposes the service to any application that a logged-on user executes. Also, services that are running as LocalSystem should not access the interactive desktop by calling the OpenWindowStation or GetThreadDesktop function.


The following list identifies the two ways that a service can interact with a user without creating an interactive service:

Display a message box by calling the MessageBox function with MB_SERVICE_NOTIFICATION. This is recommended for displaying simple status messages. Do not call MessageBox during service initialization or from the HandlerEx routine, unless you call it from a separate thread, so that you return to the SCM in a timely manner. 
Create a separate hidden GUI application and use the CreateProcessAsUser function to run the application within the context of the interactive user. Design the GUI application to communicate with the service through some method of interprocess communication (IPC), for example, named pipes. The service communicates with the GUI application to tell it when to display the GUI. The client communicates the results of the user interaction back to the service so that the service can take the appropriate action. Note that IPC can expose your service interfaces over the network unless you use an appropriate access control list (ACL). 

Future versions of Windows may not support interactive services. Therefore, it is better to use another approach to support interaction between a user and a service.


PM MAIL   Вверх
danilsl
Дата 31.8.2007, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 78
Регистрация: 15.3.2006

Репутация: нет
Всего: нет



Ну собственно интерактивный сервис мне и не нужен. Ну а пример из первого поста интерактивный потому что имхо ShowMessage самый простой способ проконтролировать что сервисЧтотоДелает. В данной теме мне более интересно, как заставить сервис принимать системные сообщения без создания скрытого окна.
PM MAIL   Вверх
NiJazz
Дата 31.8.2007, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 1
Всего: 23



danilsl, лучше всего так: отправил запрос, получил ответ, но по каналу, без помощи окон.
PM MAIL   Вверх
danilsl
Дата 31.8.2007, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 78
Регистрация: 15.3.2006

Репутация: нет
Всего: нет



Если можно, по-подробнее, по какому каналу?
Мне нужно всего лишь, что бы потоки тупо информировали основной поток моего сервиса о своём завершении. Что бы информация о количестве и состоянии порождённых потоков обрабатывалась в контексте одного основного потока, а остальные потоки ничего об этом не знали и в эти данные не лезли. А это в свою очередь мне нужно, что бы не изобретать велосипед с синхронизацией, так как потоков планируется много, и как минимум трёх типов. Так что в этом свете мне кажется проще создать таки отдельное окошко, обработчики которого будут выполняться в контексте основного потока и можно будет спокойно лесть к структурам, содержащим инфу о потоках. К тому же, используя этот способ я смогу спокойно вытаскивать из потоков обработаную инфу, опять же не заморачиваясь с синхронизацией.
С окошком я уже поигрался, с отключенным заголовком, границами кнопочками и остальными прибамбасами сервис отъел от памяти всего лишь 200кб, да и экзэшник вырос не на много. Так что в принципе довольно неплохой вариант. Во всяком случае заготовки потоков рождаются и мрут именно так, как я хочу.
Кстати. Говоря о каналах, уж не pipe ли имеются в виду? У меня книжечка есть "Программирование в сетях Windows" 2002 года (Microsoft Press кстати), так там каналы описываются в части "Устаревшие сетевые API". Что ж делать со следующими версиями Windows? Ведь как и всё устаревшее они рано или поздно перестанут поддерживаться виндой...
PM MAIL   Вверх
MetalFan
Дата 1.9.2007, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Цитата(danilsl @  31.8.2007,  16:12 Найти цитируемый пост)
Устаревшие сетевые API

ну тут не сетевое, а между процессами взаимодействие...  вполне подойдет имхо)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Alix
Дата 21.9.2007, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


L45
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 4.5.2005
Где: Pskov/Spb

Репутация: 3
Всего: 23



Мне интересно, а это ограничение на создание окон распространяется на все окна или окна с HWND_MESSAGE в качестве родителя в CreateWindow прокатывают? Вот у меня не получилось, но, быть может, я что-то не то делаю...
Вообще хотелось бы чтобы сервер получал именно сообщения на окно, его разве никак нельзя создать чтобы оно не было on the interactive desktop


--------------------
Знание только тогда знание, когда оно приобретено усилиями своей мысли, а не памятью (с) Л. Толстой
High tech. Low live. (с) Gardner Dozois
PM MAIL ICQ Skype   Вверх
Virtuals
Дата 24.9.2007, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



какое ограничение?. 
выше написано что не стоит создавать окна сервисов в контексте 
рабочего стола - оконной станции пользователя 
(иначе любой пользователь может взаимодействовать с вашим окном, в том числе и прибить его)
что похоже не знали создатели многих файрволов и антивирусов smile //postmessage(FindWindow('имя класса антивируса',nil),WM_QUIT,0,0);

если данное окно нужно только для взаимодействия между потоками и вашим приложением, то создавайте в свое удовольствие, при условии что сервис не интерактивный (винда создаст для вашего процесса, оконную станцию с произвольным именем, что изолирует вашы окна от пользователя). все ваши потоки будут на одном и том же станции/столе что обеспечит нормальное взаимодействие

окошко рекомендую создать на чистом апи а не тянуть с собой forms.

вот вам пример заготовка
Код


uses
    Messages, Windows, SysUtils;

procedure WNxl; stdcall;
  const
  TITLE = 'MyClassWxl';
  SCREEN_WIDTH = 2;
  SCREEN_HEIGHT = 2;
const id_Hot = 0;

var
  Handle: hWnd;
function WindowProcedure(Window: hWnd; Message, wParam: Word; lParam: LongInt): LongInt; stdcall;
begin
    Result:=0;
 case Message of
  WM_CREATE:
   begin
   end;
  WM_SIZE:
   begin
   end;
  WM_CLOSE:
   begin
    PostQuitMessage(0);
    Result:=0;
    Exit;
   end;
  WM_KEYDOWN:
   begin
   end;
  WM_KEYUP:
   begin
   end;
 else Result := DefWindowProc(Window, Message, wParam, lParam);
 end;
end;

// Create the window
function CreateTheWindow(Width, Height: Integer): hWnd;
var WindowClass: TWndClass;
    hInstance: HINST;
    Style: Cardinal;
begin
 hInstance := GetModuleHandle(nil);
 ZeroMemory(@WindowClass, SizeOf(WindowClass));
 with WindowClass do
  begin
   Style := CS_SAVEBITS;;
   lpfnWndProc := @WindowProcedure;
   cbClsExtra := 0;
   cbWndExtra := 0;
   hInstance := hInstance;
   hIcon := 0;
   hCursor := 0;
   hbrBackground := 0;
   lpszMenuName := '';
   lpszClassName := TITLE;
  end;
 RegisterClass(WindowClass);
 Style := WS_OVERLAPPEDWINDOW;
 Result := CreateWindowEx(0, TITLE, TITLE, Style, 0, 0, Width, Height, 0, 0, hInstance, nil);
end;

procedure DestroyTheWindow(Wnd: hWnd);
begin
 DestroyWindow(Wnd);
 UnRegisterClass(TITLE, hInstance);
end;

function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow: Integer): Integer; stdcall;
var Msg : TMsg;
    Finished : Boolean;
begin
 Finished := False;
 while not Finished do
  begin
   if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
    begin
     if Msg.Message = WM_QUIT then Finished := True
                              else
       begin
        TranslateMessage(msg);
        DispatchMessage(msg);
       end;
    end
   else
    begin
    WaitMessage;
    end;
  end;
 Result := Msg.wParam;
end;

begin
Handle:= CreateTheWindow(SCREEN_WIDTH, SCREEN_HEIGHT);
if Handle=0 then halt(0);
 WinMain(hInstance, 0, nil, 0);
 DestroyTheWindow(Handle);
end;

end.
......
//это вызвать при старте сервиса (хотя можно и не в отдельном потоке)
hThread2:=CreateThread(nil,0,@WNxl,nil,0,ThID2);


Это сообщение отредактировал(а) Virtuals - 24.9.2007, 08:34
PM MAIL ICQ   Вверх
Alix
Дата 24.9.2007, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


L45
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 4.5.2005
Где: Pskov/Spb

Репутация: 3
Всего: 23



Да нее... Создавать окна и сервисы я умею, можно было без кода. Проблема как раз в том, что сервис должен был общаться с внешним приложением, а не со своими потоками. И по ряду причин всякие pipes и mailslots не подходят.


--------------------
Знание только тогда знание, когда оно приобретено усилиями своей мысли, а не памятью (с) Л. Толстой
High tech. Low live. (с) Gardner Dozois
PM MAIL ICQ Skype   Вверх
Virtuals
Дата 24.9.2007, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



с внешним приложением не значит с пользователем!
речь идет о том что для взаимодействия между окнами они должны находится на одном станции/столе 
тоесть если приложение запустиш из сервиса (с параметрами по умолчанию) то оно окажется на одном станции/столе с сервисом и все будет работать

ЗЫ
пользовательский: Winsta0\Default
winlogon: Winsta0\Winlogon
сервис: blablabla\Default

ЗЫЗЫ кстати винда сама активно работает с сервисами именно через pipes  smile 

Код

BOOL
WINAPI
CreateProcessWithLogonW(
      LPCWSTR lpUsername,
      LPCWSTR lpDomain,
      LPCWSTR lpPassword,
      DWORD dwLogonFlags,
      LPCWSTR lpApplicationName,
      LPWSTR lpCommandLine,
      DWORD dwCreationFlags,
      LPVOID lpEnvironment,
      LPCWSTR lpCurrentDirectory,
      LPSTARTUPINFOW lpStartupInfo,
      LPPROCESS_INFORMATION lpProcessInformation)

//.
//.
//.
            hpipe = CreateFileW(L"\\\\.\\pipe\\SecondaryLogon",
                  GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 
                  FILE_FLAG_OVERLAPPED, NULL);
            if(hpipe == INVALID_HANDLE_VALUE) 
            {
                LastError = GetLastError();
                __leave;
            }

         }
         else
            __leave;
      }

      DWORD cbBytesTransferred;
      OVERLAPPED    Overlapped;
      SECURITY_ATTRIBUTES   SecurityAttr;

      Overlapped.Offset = 0;
      Overlapped.OffsetHigh = 0;

      SecurityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
      SecurityAttr.lpSecurityDescriptor = NULL;
      SecurityAttr.bInheritHandle = FALSE;

      Overlapped.hEvent = CreateEvent( &SecurityAttr, FALSE, FALSE, NULL );
      if(Overlapped.hEvent == NULL) __leave;

      if (!WriteFile(hpipe, &cbBytesToSend, sizeof(cbBytesToSend),
                     &cbBytesTransferred, &Overlapped))
      {
//.
//.
//.

(С) М$ да простят меня великие и богатые

Это сообщение отредактировал(а) Virtuals - 24.9.2007, 10:30
PM MAIL ICQ   Вверх
Alix
Дата 24.9.2007, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


L45
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 4.5.2005
Где: Pskov/Spb

Репутация: 3
Всего: 23



Цитата
тоесть если приложение запустиш из сервиса (с параметрами по умолчанию) то оно окажется на одном станции/столе с сервисом и все будет работать

имхо, это плохой способ, т.к. тогда это приложение получит права учетной записи под которой запущен сервис, а это чаще всего System


--------------------
Знание только тогда знание, когда оно приобретено усилиями своей мысли, а не памятью (с) Л. Толстой
High tech. Low live. (с) Gardner Dozois
PM MAIL ICQ Skype   Вверх
Virtuals
Дата 24.9.2007, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



Код

LogonUser (лох ушастый)
CreateProcessAsUser(прога от имени лоха ушастого)
 smile  smile 
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0897 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.