亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

Windows服務編寫(Windows Service,system權限)程序顯示界面與用戶交互(xp,win7通用)

2020-01-24 01:11:46
字體:
來源:轉載
供稿:網友

1、VC2008中編寫“Windows服務”(Windows Service)程序

源碼資源下載:/201604/yuanma/TestService_jb51.rar

vc2008下新建一個 ATL 項目-》 選擇創建一個“服務”類型的ATL 項目TestService,將生成如下代碼,

class CTestServiceModule : public CAtlServiceModuleT< CTestServiceModule, IDS_SERVICENAME >{public :DECLARE_LIBID(LIBID_TestServiceLib )DECLARE_REGISTRY_APPID_RESOURCEID (IDR_TESTSERVICE, "{1FF78006-B225-4CC0-A7DE-E0C9D31C9937}" )HRESULT InitializeSecurity () throw(){// TODO : 調用CoInitializeSecurity 并為服務提供適當的// 安全設置// 建議- PKT 級別的身份驗證、// RPC_C_IMP_LEVEL_IDENTIFY 的模擬級別// 以及適當的非NULL 安全說明符。return S_OK ;}//重寫這個函數來啟動任務啦HRESULT Run (int nShowCmd = SW_HIDE ) throw(){HRESULT hr = S_OK;hr = __super ::PreMessageLoop( nShowCmd);if (hr == S_OK){if (m_bService ){//需要定義#define _ATL_NO_COM_SUPPORT才能啟動服務時走到這里//可以在這里啟動線程,或者什么其他東西來做自己的工作的啦//這里是什么都沒有做了,只輸出一條信息LogEvent(_T ("widebright 的服務啟動咯,呵呵 "));SetServiceStatus(SERVICE_RUNNING );}//進入消息循環,不停的處理消息,可能最后分發到 Handler去處理,調用了OnShutdown等函數的。__super::RunMessageLoop ();}if (SUCCEEDED (hr)){hr = __super ::PostMessageLoop();}//可以在適當的時候調用Uninstall函數來卸載掉服務//__super::Uninstall();return hr ;}//重寫,服務退出處理void OnShutdown () throw(){LogEvent(_T ("TestService 的服務退出咯,一點都不好玩呵呵 "));}};CTestServiceModule _AtlModule;//extern "C" int WINAPI _tWinMain (HINSTANCE , HINSTANCE ,LPTSTR , int nShowCmd){return _AtlModule .WinMain( nShowCmd);}

2、我只要根據需要重寫相應的函數來實現自己想要的功能就行了

比如你想創建的“服務”隨系統啟動,可以重寫CAtlServiceModuleT 的Install函數,把里面的CreateService函數的參數修改一下,例如添加與用戶交互可以使用 SERVICE_INTERACTIVE_PROCESS,具體可以去MSDN上查找CreateService這個API的說明。

如果想處理服務 停止和啟動的動作,可以參考CAtlServiceModuleT 的源代碼重寫OnStop ()等函數。我上面簡單到重寫了Run函數,輸出一條“事件”其實具體 工作是可以放到這里來完成的吧。

編譯,生成程序之后就可以測試了,

執行“TestService -/Service” 就可以把服務注冊到系統了,命令行參數其實是在CAtlServiceModuleT::ParseCommandLine 這個函數里面處理,可以去看一下,必要的話重寫也是可以的,加上調用 UnInstall來刪除服務的代碼也很不錯的吧。

注冊后,就看用“sc start” 或者“net start” 等命令來操縱服務了。在“服務”控制器里面控制與可以:如圖

3、這時候在Run函數中啟動一個Notepad.exe,此時沒有界面顯示,在xp下可以使用下面的方法實現notepad與用戶的交互:

//for xp systemDWORD _stdcall LaunchAppIntoSession0( LPTSTR lpCommand ){////////////////////////////////////////////system show dlg////////////////////HDESK hdeskCurrent ;HDESK hdesk ;HWINSTA hwinstaCurrent ;HWINSTA hwinsta ;hwinstaCurrent = GetProcessWindowStation ();if (hwinstaCurrent == NULL){return FALSE ;}hdeskCurrent = GetThreadDesktop (GetCurrentThreadId());if (hdeskCurrent == NULL){return FALSE ;}//打開winsta0//打開winsta0hwinsta = OpenWindowStation (L"Winsta0" , FALSE, WINSTA_ALL_ACCESS);// WINSTA_ACCESSCLIPBOARD|// WINSTA_ACCESSGLOBALATOMS |// WINSTA_ENUMDESKTOPS |// WINSTA_CREATEDESKTOP |// WINSTA_CREATEDESKTOP |// WINSTA_ENUMERATE |// WINSTA_EXITWINDOWS |// WINSTA_READATTRIBUTES |// WINSTA_READSCREEN |// WINSTA_WRITEATTRIBUTES);if (hwinsta == NULL){return FALSE ;}if (!SetProcessWindowStation (hwinsta)){return FALSE ;}//打開desktophdesk = OpenDesktop (L"default" , 0, FALSE,DESKTOP_CREATEMENU |DESKTOP_CREATEWINDOW |DESKTOP_ENUMERATE|DESKTOP_HOOKCONTROL|DESKTOP_JOURNALPLAYBACK |DESKTOP_JOURNALRECORD |DESKTOP_READOBJECTS |DESKTOP_SWITCHDESKTOP |DESKTOP_WRITEOBJECTS);if (hdesk == NULL){return FALSE ;}SetThreadDesktop(hdesk );////////////////////////////////////////////end of system show dlg////////////////////STARTUPINFO si = { sizeof( si) }; SECURITY_ATTRIBUTES saProcess , saThread; PROCESS_INFORMATION piProcessB , piProcessC; // Prepare to spawn Process B from Process A. // The handle identifying the new process // object should be inheritable. saProcess.nLength = sizeof( saProcess); saProcess.lpSecurityDescriptor = NULL; saProcess.bInheritHandle = TRUE; // The handle identifying the new thread // object should NOT be inheritable. saThread.nLength = sizeof( saThread);saThread.lpSecurityDescriptor = NULL;saThread.bInheritHandle = FALSE; CreateProcess(NULL , lpCommand, & saProcess, &saThread , FALSE, 0, NULL , NULL, & si, &piProcessB ); if (!SetProcessWindowStation (hwinstaCurrent))return FALSE ;if (!SetThreadDesktop (hdeskCurrent))return FALSE ;if (!CloseWindowStation (hwinsta))return FALSE ;if (!CloseDesktop (hdesk))return FALSE ;return TRUE ;}


這種方法的關鍵是OpenWindowStation、SetProcessWindowStation、OpenDesktop和SetThreadDesktop這四個函數。這種方法的思路是:當前進程所處于的Session必須有界面交互能力,這樣才能顯示出對話框。由于第一個交互式用戶會登錄到擁有WinSta0的Session 0,所以,強制性地把服務所在的進程與WinSta0關聯起來,并且打開當前的桌面,把工作線程掛到該桌面上,就可以顯示出對話框。

4、這種方法在WinXP和Windows2003下工作得不錯,很遺憾,在Vista和Windows2008下,一旦執行到OpenWindowStation,試圖代開WinSta0工作站時,程序就會出異常。


首先了解一下程序要具備怎樣的條件才能與界面交互。Windows提供了三類對象:用戶界面對象(User Interface)、GDI對象和內核對象。內核對象有安全性,而前兩者沒有。為了對前兩者提供安全性,通過工作站對象(Window station)和桌面對象(Desktop)來管理用戶界面對象,因為工作站對象和桌面對象有安全特性。簡單說來,工作站是一個帶有安全特性的對象,它與進程相關聯,包含了一個或多個桌面對象。當工作站對象被創建時,它被關聯到調用進程上,并且被賦給當前Session。交互式工作站WinSta0,是唯一一個可以顯示用戶界面,接受用戶輸入的工作站。它被賦給交互式用戶的登錄Session,包含了鍵盤、鼠標和顯示設備。所有其他工作站都是非交互式的,這就意味著它們不能顯示用戶界面,不能接受用戶的輸入。當用戶登錄到一臺啟用了終端服務的計算機上時,每個用戶都會啟動一個Session。每個Session都會與自己的交互式工作站相聯系。桌面是一個帶有安全特性的對象,被包含在一個窗口工作站對象中。一個桌面對象有一個邏輯的顯示區域,包含了諸如窗口、菜單、鉤子等等這樣的用戶界面對象。

在Vista之前,之所以可以通過打開Winsta0和缺省桌面顯示對話框,是因為不管是服務還是第一個登錄的交互式用戶,都是登錄到Session 0中。因此,服務程序可以通過強制打開WinSta0和桌面來獲得交互能力。

然而,在Vista和Windows2008中,Session 0專用于服務和其他不與用戶交互的應用程序。第一個登錄進來,可以進行交互式操作的用戶被連到Session 1上。第二個登錄進行的用戶被分配給Session 2,以此類推。Session 0完全不支持要與用戶交互的進程。如果采取在服務進程中啟動子進程來顯示對話框,子對話框將無法顯示;如果采取用OpenWindowStation系統API打開WinSta0的方法,函數調用會失敗。總之,Vista和Windows2008已經堵上了在Session 0中產生界面交互的路。這就是原因所在。

那么,是否真的沒法在服務中彈出對話框了呢?對于服務進程自身來說,確實如此,操作系統已經把這條路堵上了。但是,我們想要的并不是“在服務進程中彈出對話框”,我們想要的不過是“當服務出現某些狀況的時候,在桌面上彈出對話框”。既然在Session 0中無法彈出對話框,而我們看到的桌面是Session X,并非Session 0,很自然的一個想法是:能不能讓Session 0通知其他的Session,讓當前桌面正顯示著的Session彈一個對話框呢?

幸運的是,還真可以這樣做。

//for win7DWORD _stdcall LaunchAppIntoDifferentSession( LPTSTR lpCommand ){DWORD dwRet = 0;PROCESS_INFORMATION pi ;STARTUPINFO si ;DWORD dwSessionId ;HANDLE hUserToken = NULL;HANDLE hUserTokenDup = NULL;HANDLE hPToken = NULL;HANDLE hProcess = NULL;DWORD dwCreationFlags ;HMODULE hInstKernel32 = NULL;typedef DWORD (WINAPI * WTSGetActiveConsoleSessionIdPROC)();WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;hInstKernel32 = LoadLibrary (L"Kernel32.dll" );if (!hInstKernel32 ) {return FALSE ;}OutputDebugString(L "LaunchAppIntoDifferentSession 1/n" );WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC )GetProcAddress( hInstKernel32,"WTSGetActiveConsoleSessionId" );// Log the client on to the local computer.dwSessionId = WTSGetActiveConsoleSessionId ();do{WTSQueryUserToken( dwSessionId ,&hUserToken );dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;ZeroMemory( &si , sizeof( STARTUPINFO ) );si.cb = sizeof( STARTUPINFO );si.lpDesktop = L"winsta0//default" ;ZeroMemory( &pi , sizeof( pi) );TOKEN_PRIVILEGES tp ;LUID luid ;if( !::OpenProcessToken ( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY| TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID| TOKEN_READ | TOKEN_WRITE , &hPToken ) ){dwRet = GetLastError ();break;}else;if ( !LookupPrivilegeValue ( NULL, SE_DEBUG_NAME, &luid ) ){dwRet = GetLastError ();break;}else;tp.PrivilegeCount =1;tp.Privileges [0].Luid = luid;tp.Privileges [0].Attributes = SE_PRIVILEGE_ENABLED;if( !DuplicateTokenEx ( hPToken, MAXIMUM_ALLOWED, NULL , SecurityIdentification , TokenPrimary, & hUserTokenDup ) ){dwRet = GetLastError ();break;}else;//Adjust Token privilegeif( !SetTokenInformation ( hUserTokenDup,TokenSessionId ,(void*)& dwSessionId,sizeof (DWORD) ) ){dwRet = GetLastError ();break;}else;if( !AdjustTokenPrivileges ( hUserTokenDup, FALSE, &tp , sizeof(TOKEN_PRIVILEGES ), (PTOKEN_PRIVILEGES) NULL, NULL ) ){dwRet = GetLastError ();break;}else;LPVOID pEnv =NULL;if( CreateEnvironmentBlock ( &pEnv, hUserTokenDup, TRUE ) ){dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT ;}else pEnv =NULL;// Launch the process in the client's logon session.if( CreateProcessAsUser ( hUserTokenDup, // client's access tokenNULL, // file to executelpCommand, // command lineNULL, // pointer to process SECURITY_ATTRIBUTESNULL, // pointer to thread SECURITY_ATTRIBUTESFALSE, // handles are not inheritabledwCreationFlags,// creation flagspEnv, // pointer to new environment blockNULL, // name of current directory& si, // pointer to STARTUPINFO structure& pi // receives information about new process) ){}else{dwRet = GetLastError ();break;}}while( 0 );//Perform All the Close Handles taskif( NULL != hUserToken ){CloseHandle( hUserToken );}else;if( NULL != hUserTokenDup){CloseHandle( hUserTokenDup );}else;if( NULL != hPToken ){CloseHandle( hPToken );}else;return dwRet ;}

5、啟動服務后顯示了system權限的Notepad.exe,并且可以與用戶進行交互


當然,在本例子啟動進程的地方創建一個對話框也是可以顯示對話框的。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品日韩美女的视频高清| 欧美激情二区三区| 日韩国产高清视频在线| 欧美日韩中文在线| 一本色道久久88亚洲综合88| 色噜噜亚洲精品中文字幕| 久久国产精品免费视频| 欧美国产在线视频| 国产一区二区三区在线| 国产美女主播一区| 国产婷婷97碰碰久久人人蜜臀| 欧美精品在线第一页| 欧美精品videofree1080p| 国产精品丝袜久久久久久高清| 日韩在线播放一区| 98精品国产自产在线观看| 亚洲的天堂在线中文字幕| 国内精品久久久久久| 国产一区二区美女视频| 国产精品极品美女在线观看免费| 国产精品揄拍500视频| 亚洲激情视频在线| 亚洲在线观看视频| 国产精品午夜视频| 欧美午夜视频在线观看| 疯狂欧美牲乱大交777| 永久免费毛片在线播放不卡| 国产丝袜精品第一页| 超碰97人人做人人爱少妇| 日韩va亚洲va欧洲va国产| 91成人精品网站| 亚洲女性裸体视频| 亚洲欧美国产精品va在线观看| 日韩在线视频观看| 日韩精品久久久久久久玫瑰园| 欧美色视频日本版| 7777精品久久久久久| 亚洲国产精品999| 一区二区三区视频免费在线观看| 亚洲第一精品自拍| 91精品久久久久久久久久久久久久| 国产精品视频在线观看| 久久夜色精品亚洲噜噜国产mv| 亚洲国产一区二区三区在线观看| 日韩精品在线第一页| 国产精品一区二区3区| 国产精品电影久久久久电影网| 97超碰蝌蚪网人人做人人爽| 中国人与牲禽动交精品| 亚洲综合日韩中文字幕v在线| 亚洲精品综合精品自拍| 91精品在线一区| 欧美又大粗又爽又黄大片视频| 国产亚洲精品久久久| 一区二区三区国产在线观看| 欧美日韩中文字幕| 日韩国产在线看| 精品久久久久久中文字幕大豆网| 亚洲欧美国产制服动漫| 亚洲一区二区三区成人在线视频精品| 欧美日韩国产中文精品字幕自在自线| 日韩成人av网址| 国产精品视频999| 色av中文字幕一区| 精品久久香蕉国产线看观看亚洲| 8090成年在线看片午夜| 亚洲欧美制服第一页| 国产国产精品人在线视| 欧美日韩国产一区二区| 日韩精品在线视频美女| 亚洲人成在线一二| 亚洲美女激情视频| 亚洲精品二三区| 久久夜色精品国产亚洲aⅴ| 日本国产一区二区三区| 日韩美女视频免费在线观看| 亚洲精品一区中文| 这里只有视频精品| 国产成人精品最新| 国产精品久久电影观看| 一个色综合导航| 精品久久国产精品| 日韩在线视频免费观看高清中文| 亚洲欧美日韩国产精品| 国产美女扒开尿口久久久| 亚洲深夜福利在线| 911国产网站尤物在线观看| 97免费视频在线播放| 亚洲国语精品自产拍在线观看| 国产精品久久在线观看| 欧美精品日韩www.p站| 国产成人亚洲综合91精品| 色噜噜狠狠狠综合曰曰曰88av| 亚洲视频在线观看免费| 国产精品视频大全| 992tv在线成人免费观看| 久久久久久久久久婷婷| 日韩中文第一页| 97香蕉超级碰碰久久免费的优势| 亚洲欧美成人在线| 一区二区三区天堂av| 菠萝蜜影院一区二区免费| 亚洲国产精品成人一区二区| 亚洲成色www8888| 欧美成人精品激情在线观看| 欧美成人第一页| 成人a级免费视频| 亚洲丝袜在线视频| 按摩亚洲人久久| 亚洲国产成人精品女人久久久| 中文字幕欧美日韩在线| 亚洲va久久久噜噜噜| 久久成人免费视频| 亚洲人成在线观看网站高清| 中文字幕日韩av电影| 亚洲视频在线免费看| xvideos国产精品| 精品中文字幕在线2019| 久久青草精品视频免费观看| 亚洲国产精品悠悠久久琪琪| 欧美日韩国产91| 7777kkkk成人观看| 韩国美女主播一区| 欧美日韩一区免费| 国产91亚洲精品| 日韩在线www| 国产91精品黑色丝袜高跟鞋| 国产97人人超碰caoprom| 国产欧美一区二区| 国产91亚洲精品| 韩剧1988在线观看免费完整版| 精品自拍视频在线观看| 精品无人区乱码1区2区3区在线| 亚洲精品二三区| 神马久久桃色视频| 欧美日韩中国免费专区在线看| 国产精品视频区1| 国产精品自产拍在线观| 国产精品69av| 欧美最猛性xxxxx亚洲精品| 精品久久香蕉国产线看观看gif| 国产欧美日韩免费| 精品美女国产在线| 国产精品久久久久久婷婷天堂| 国产精品一区二区三区毛片淫片| 日韩免费精品视频| 亚洲一区二区三区四区在线播放| 亚洲精品国产成人| 欧美亚洲日本网站| 日韩在线视频观看正片免费网站| 中文字幕国产精品久久| 伊人久久免费视频| 亚洲精品99999| 欧美日韩在线观看视频| 深夜福利亚洲导航| 日韩亚洲精品视频| 亚洲色图综合久久| 超碰97人人做人人爱少妇| 国产精品久久久久7777婷婷| 国产精品 欧美在线| 日韩黄在线观看| 亚洲精品之草原avav久久| 久久精品影视伊人网| 国产精品国产自产拍高清av水多|