服務程序(Service)一般是不能和用戶進行交互的,所以他一般是不能顯示窗口的。要和用戶進行交互(如顯示窗口),我們必須打開用戶WinSta0和desktop,下面的這段代碼就是打開上述兩個,並顯示一個dialog:
BOOL CServiceModule::ShowMsgDlg(void)
{
HDESK hdeskCurrent;
HDESK hdesk;
HWINSTA hwinstaCurrent;
HWINSTA hwinsta;
hwinstaCurrent = GetProcessWindowStation();
if (hwinstaCurrent == NULL){
LogEvent(_T("get window station err"));
return FALSE;
}
hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
if (hdeskCurrent == NULL){
LogEvent(_T("get window desktop err"));
return FALSE;
}
//打開winsta0
hwinsta = OpenWindowStation("winsta0", FALSE,
WINSTA_ACCESSCLIPBOARD |
WINSTA_ACCESSGLOBALATOMS |
WINSTA_CREATEDESKTOP |
WINSTA_ENUMDESKTOPS |
WINSTA_ENUMERATE |
WINSTA_EXITWINDOWS |
WINSTA_READATTRIBUTES |
WINSTA_READSCREEN |
WINSTA_WRITEATTRIBUTES);
if (hwinsta == NULL){
LogEvent(_T("open window station err"));
return FALSE;
}
if (!SetProcessWindowStation(hwinsta)){
LogEvent(_T("Set window station err"));
return FALSE;
}
//打開desktop
hdesk = OpenDesktop("default", 0, FALSE,
DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE |
DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS);
if (hdesk == NULL){
LogEvent(_T("Open desktop err"));
return FALSE;
}
SetThreadDesktop(hdesk);
//到這一步,我們獲取了和用戶交互(如顯示窗口)的權利
CMsgDlg dlgMsg;
//顯示一個dialog
dlgMsg.DoModal();
if (!SetProcessWindowStation(hwinstaCurrent))
return FALSE;
if (!SetThreadDesktop(hdeskCurrent))
return FALSE;
if (!CloseWindowStation(hwinsta))
return FALSE;
if (!CloseDesktop(hdesk))
return FALSE;
return TRUE;
}
運行:編譯生成guiser.exe, 運行guiser /service, 然後在控制面板的服務中啟動該服務,將會出現一個對話框!
上述程序在win2000 professional + VC6.0 + Sp5.0 + Platform SDK 2001.8編譯運行通過
如有編譯不通過,請下載最新的Platform SDK
本文配套源碼