Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2002.11.07;
Скачать: [xml.tar.bz2];

Вниз

Сервис на Delphi и Форма   Найти похожие ветки 

 
Terrible   (2002-09-04 17:13) [0]

Есть приложение, написанное на делфях, и переделанное в сервис. Сделано это следующим образом. В ServiceMain выполняется:
Application.Initialize;
Application.CreateForm(TForm1, Form1);

В событии FormCreate в конце процедуры выполняется
Form1.Activate;

Таким образом форма нормально строится, всё что нужно создаётся и приложение в принципе работает в фоновом процессе (в том числе работают компоненты TTimer, TTCPClient и пр.). То есть сервис коннектится по сети к серваку, обменивается данными и пр.
Но вот надо бы это всё куда то отображать, а конкретно, была задумка, красиво всё это показывать на форме (всё что мы делаем и пр).
Мне конечно скажут: "сделай в сервисе всё без форм и напиши отдельное приложение, которое по DDE, COM или т.п. будет обмениваться данными с сервисом и всё отображать". Но это процесс простой, а мы лёгких путей не ищем :)
Проблема описанного выше метода: когда меняется пользователь (LogOff, LogOn) то обычное приложение (не сервис) выгружается, и повторно автоматом не выгружается, надо стартовать его вручную.

Теперь внимание, собственно вопрос.
А можно ли как то заставить нормально отображаться форме из сервиса и взаимодействовать с ней.
Буду благодарен за примеры с исходниками, хотя бы обравками.


 
Fiend   (2002-09-04 17:54) [1]

для этого вам нужно узнать, залогинился ли кто то в систему.
Если да то получить хэндл на его десктоп и работать.
И надо бы разрешить сервису взаимодействие с рабочим столом


 
Terrible   (2002-09-04 18:12) [2]

А как узнать залогинился кто то или нет ?
И как реализовать на практике: получение хендла и отображение формы по этому хэндлу, если ворму я создаю стандартными pplication.CreateForm(TForm1, Form1) ?
Как мне переадресовать эту форму в рабочий стол подключившегося пользователя ?


 
Ученик   (2002-09-04 19:17) [3]

>Terrible © (04.09.02 18:12)

>Проблема описанного выше метода: когда меняется пользователь (LogOff, LogOn) то обычное приложение (не сервис) выгружается, и повторно автоматом не выгружается, надо стартовать его вручную.

Приложение запускается при логине, если прописано в
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

>А как узнать залогинился кто то или нет ?

Приходит сообщение
RM_TaskBarCreated := RegisterWindowMessage("TaskbarCreated");


 
Fiend   (2002-09-05 13:26) [4]

То Ученик

По моему вопрошающий чётко сказал, что у него СЕРВИС, а не приложение, поэтому само не перезапуститься при логоф-логон.
И насчёт месаджа тоже не согласен.

А вот огрызочек из МСДН как сделать интерактивный сервис.

Interacting with the User in a Service
For a noninteractive service application to interact with the user, it must open the user"s window station ("WinSta0") and desktop ("Default"). By default, only the logged-on user and service applications running in the LocalSystem account are granted access to the user"s window station and desktop. This means that services running in other accounts must either impersonate the user when opening the interactive window station and desktop, or have access granted to those accounts by the user.

For compatibility with versions of Windows that support multiple users and/or multiple desktops per user, the user"s window station and desktop names should not be hard-coded. Client applications should pass the names of their window station and desktop to the service as part of the request to the service.

This code sample displays a message on the user"s desktop in response to an RPC request from one of the user"s applications. Note that a global variable dwGuiThreadId in this example is also used in the logoff handling example. If the thread that displays the message box terminates after it is done with the message box, it is not necessary to save and restore the thread"s desktop. It is necessary to restore the process"s window station.

DWORD dwGuiThreadId = 0;

int
UserMessageBox(
RPC_BINDING_HANDLE h,
LPSTR lpszWindowStation,
LPSTR lpszDesktop,
LPSTR lpszText,
LPSTR lpszTitle,
UINT fuStyle)
{
DWORD dwThreadId;
HWINSTA hwinstaSave;
HDESK hdeskSave;
HWINSTA hwinstaUser;
HDESK hdeskUser;
int result;

// Ensure connection to service window station and desktop, and
// save their handles.

GetDesktopWindow();
hwinstaSave = GetProcessWindowStation();
dwThreadId = GetCurrentThreadId();
hdeskSave = GetThreadDesktop(dwThreadId);

// Impersonate the client and connect to the User"s
// window station and desktop.

RpcImpersonateClient(h);
hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
if (hwinstaUser == NULL)
{
RpcRevertToSelf();
return 0;
}
SetProcessWindowStation(hwinstaUser);
hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
RpcRevertToSelf();
if (hdeskUser == NULL)
{
SetProcessWindowStation(hwinstaSave);
CloseWindowStation(hwinstaUser);
return 0;
}
SetThreadDesktop(hdeskUser);

// Display message box.

dwGuiThreadId = dwThreadId;
result = MessageBox(NULL, lpszText, lpszTitle, fuStyle);
dwGuiThreadId = 0;

// Restore window station and desktop.

SetThreadDesktop(hdeskSave);
SetProcessWindowStation(hwinstaSave);
CloseDesktop(hdeskUser);
CloseWindowStation(hwinstaUser);

return result;
}

А это вот - как отловить логофф юзера:

Handling Logoff Events
Service applications that interact with the user should be prepared to handle logoff events. When a logoff event occurs, the service application must close all handles to the user"s window station and desktop.

This sample demonstrates how the message box in the interaction example code should be dismissed at logoff. The ConsoleCtrlHandler function in this example is a HandlerRoutine that was specified by a call to the SetConsoleCtrlHandler function.

BOOL CALLBACK EnumProc(
HWND hwnd,
LPARAM lParam)
{
// Send a WM_CLOSE to destroy the window, because DestroyWindow
// does not work across threads.

SendMessage(hwnd, WM_CLOSE, 0, 0);
return TRUE;
}

BOOL ConsoleCtrlHandler(
DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_LOGOFF_EVENT && dwGuiThreadId != 0)
{
SetThreadDesktop(GetThreadDesktop(dwGuiThreadId));
EnumThreadWindows(dwGuiThreadId, EnumProc, 0);
}
return FALSE;
}


Думаю без проблем переведети на Пасквель.

Однако хочу заметить, что раз вы хотите выводить не просто там какие то одиночные сообщения юзеру, то правильнее всё таки сделать отдельную утилитку, которая будет коннектится к службе. Ну просто мне кажется, что это самый логичный вариант.

ЗЫ: Может вы прислушаетесь к моему мнению по поводу окон. Всё же имею серьёзный опыт разработки служб и приложений к ним.


С наилучшими!!!



Страницы: 1 вся ветка

Форум: "Система";
Текущий архив: 2002.11.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.008 c
14-21783
Igorenia
2002-10-18 00:25
2002.11.07
необходимо написать развитый help, на подобии тех, которые присут


3-21409
Beglec
2002-10-18 14:38
2002.11.07
простенький вопрос, но больно мучительный для меня


1-21658
Yonic
2002-10-26 09:17
2002.11.07
WebBrowser


3-21412
Vlad_K
2002-10-11 14:02
2002.11.07
RX library


3-21440
nN_
2002-10-18 10:14
2002.11.07
TreeView и DBGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский