欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
編寫(xiě)有圖形界面的 Windows 服務(wù)程序 - VC知識庫文章

編寫(xiě)有圖形界面的 Windows 服務(wù)程序

作者:feitian2007

下載源代碼

環(huán)境:Windows 2003,VC 6.0

摘要:從建立一個(gè)COM服務(wù)程序入手,然后將一個(gè)MFC項目改造成服務(wù)程序,最后讓這一程序在啟動(dòng)時(shí)可以顯示圖形界面。

關(guān)鍵字:windows服務(wù)程序 COM服務(wù)程序 開(kāi)機前啟動(dòng) NT服務(wù) 與桌面交互

一、什么是windows的服務(wù)程序?

可以使用下面的幾種方法看到它。

  1. 打開(kāi)控制面板,然后是管理工具,里面有一個(gè)“服務(wù)”,雙擊后打開(kāi);
  2. 或者是通過(guò)輸入命令的方式,打開(kāi)開(kāi)始菜單,點(diǎn)擊運行,輸入mmc services.msc(mmc可省略),也可打開(kāi);

  我們會(huì )在打開(kāi)的頁(yè)面中看到一個(gè)大的列表,標題欄上包含有名稱(chēng)、描述、狀態(tài)、啟動(dòng)類(lèi)型、登錄身份等項。其中在狀態(tài)一欄中顯示為“已啟動(dòng)”的是系統中已經(jīng)啟動(dòng)了的服務(wù)。我們先看一下服務(wù)的屬性。舉個(gè)例子,找到Print Spooler這一名稱(chēng),然后用右鍵在上面點(diǎn)擊,選擇“屬性”,可以看到它所執行的命令行是C:\WINDOWS\system32\spoolsv.exe,按下停止后,任務(wù)管理器中spoolsv.exe進(jìn)程退出。我們所見(jiàn)到的這個(gè)列表就是服務(wù)程序的集中地,每一項就是一個(gè)服務(wù)程序。

上面這些標為自啟動(dòng)的服務(wù)程序隨系統一起啟動(dòng)。它與一些修改注冊表:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 

項,及類(lèi)似注冊表項的程序不同的是,即使用戶(hù)沒(méi)有登錄到系統中,它們也是會(huì )運行的,或者說(shuō)它們在系統登錄前運行。

二、怎么建立自己的服務(wù)程序?

  每一個(gè)服務(wù)程序對應注冊表項HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下的一個(gè)子項。因此我們可以通過(guò)增加注冊表項的方式增加服務(wù)程序。比如,我現在要增加一個(gè)test1服務(wù)程序,對應的可執行文件是c:\test1.exe。那么我要增加如下注冊表項:

  1. [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\]下增加子項test1;
  2. test1下增加:
    字符串型:"Description"="測試服務(wù)1"
    字符串型:"DisplayName"="test1-displayname"
    DWORD型:"ErrorControl"=dword:00000001
    可擴充字符串值(即文件所在路徑):
    "ImagePath"=hex(2):43,00,3a,00,5c,00,74,00,65,00,73,00,74,00,31,00,2e,00,65,00,\
    78,00,65,00,00,00
    字符串型:"ObjectName"="LocalSystem"
    DWORD型,值為3表示是手動(dòng):"Start"=dword:00000003
    DWORD型:"Type"=dword:00000020
  3. test1下增加子項:
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\test1\Security]
    里面的鍵值從其他的服務(wù)程序注冊表值中復制。

  如果test1這一程序只是一個(gè)普通的win32程序,那么這樣做了之后還是不行,服務(wù)程序有它自己的一些結構特點(diǎn)。那么怎么編寫(xiě)這些服務(wù)程序?
  建立一個(gè)服務(wù)程序的最簡(jiǎn)單的方法是用VC中的ATL COM向導。主菜單中選擇新建,然后選Projects中的ATL COM AppWizard,輸入一個(gè)項目名,選擇了所在目錄后,點(diǎn)OK按鈕,在出現的對話(huà)框中選擇Service(EXE),點(diǎn)Finish即可。然后編譯生成test1.exe。
  運行test1.exe /regserver可以注冊程序為服務(wù),test1.exe /unregserver是取消注冊。test1.exe運行時(shí)的參數是在:
Project->Settings->Debug->Program arguments中設置。

三、怎么在建立的服務(wù)程序中加入自己的代碼?

我們看一下剛才生成的test1項目的結構。

  我們看到test1有一個(gè)類(lèi)CServiceModule和一些Globals的內容。Globals包括一個(gè)_tWinMain函數,也就是程序的入口,其中使用了FindOneOf這一與分析命令行有關(guān)的函數,還剩下一個(gè)全局變量_Module。
  _tWinMain函數中,_Module初始化并設置m_bService為T(mén)RUE,在一些分析命令行和判斷是否為服務(wù)的代碼之后,使用_Module.Start()進(jìn)入主要的執行部分。CServiceModule::Start()中,結構體SERVICE_TABLE_ENTRY建立了服務(wù)名與相應處理函數的映射。在這里,如果m_bService為T(mén)RUE,則調用StartServiceCtrlDispatcher進(jìn)入一種類(lèi)似win32程序的消息處理的過(guò)程,用SERVICE_TABLE_ENTRY中的處理函數讓程序執行下去。如果m_bService不為T(mén)RUE,則直接執行Run()函數。
  在SERVICE_TABLE_ENTRY中,我們看到服務(wù)處理函數為_(kāi)ServiceMain,繼續跟蹤下去,發(fā)現是ServiceMain函數。在ServiceMain中又調用RegisterServiceCtrlHandler為服務(wù)增加了一個(gè)_Handler函數。對服務(wù)程序來(lái)說(shuō),我們可以在前面打開(kāi)的服務(wù)列表中對它們進(jìn)行“啟動(dòng)”,“停止”,“暫停”,“恢復”等操作。這實(shí)際上是由_Handler來(lái)處理不同的信號。_Handler內部調用Handler,在Handler中,對傳入的dwOpcode參數作出處理。比如如果是SERVICE_CONTROL_STOP,也就是我們“停止”服務(wù)時(shí),將使用PostThreadMessage對主線(xiàn)程發(fā)出一個(gè)退出的信號?;氐絊erviceMain函數,在里面同樣是在調用Run()函數。也就是說(shuō)程序以服務(wù)身份和非服務(wù)身份運行時(shí),區別在于以服務(wù)身份運行時(shí)多了一個(gè)Handler函數,處理用戶(hù)對服務(wù)程序發(fā)出的一些信號。
  需要注意的是,這個(gè)程序注冊為服務(wù)時(shí)并不是直接寫(xiě)注冊表,而是在Install中使用了OpenSCManager,CreateService等函數來(lái)完成的任務(wù)。顯然,這比直接寫(xiě)注冊表要好一些,因為有時(shí)候我們并不太清楚要怎么去修改注冊表項的值來(lái)適應不同的服務(wù)程序配置,而這些函數有參數可以做到。

說(shuō)到這里,就涉及到我們自己編寫(xiě)的代碼了。
比如現在我們已經(jīng)建立了一個(gè)MFC的程序,想讓它成為一個(gè)服務(wù)程序,那要怎么做呢?
我現在建立一個(gè)MFC EXE的項目mfc1,基于對話(huà)框。那么把它變?yōu)橐粋€(gè)服務(wù)程序的最簡(jiǎn)單的方法就是把CServiceModule給拿過(guò)來(lái)使用。因為我們已經(jīng)看到CServiceModule類(lèi)已經(jīng)把安裝服務(wù),卸載服務(wù),運行服務(wù)這些操作封裝得很好。
打開(kāi)test1的stdafx.h文件,復制CServiceModule的聲明及相關(guān)頭文件和變量到mfc1的stdafx.h中。
然后是把test1的test1.cpp中對CServiceModule類(lèi)的實(shí)現,復制到mfc1中的mfc1.cpp中。
在stdafx.h中CServiceModule類(lèi)聲明前加上#include <winsvc.h>,它里面是對結構體SERVICE_STATUS_HANDLE的聲明。
編譯后出現以下類(lèi)似錯誤:

D:\vc6_test\mfc1\mfc1.cpp(52) : error C2065: ''IDR_Test1'' : undeclared identifierD:\vc6_test\mfc1\mfc1.cpp(336) : error C2065: ''CoInitializeSecurity'' : undeclared identifierD:\vc6_test\mfc1\mfc1.cpp(337) : error C2065: ''EOAC_NONE'' : undeclared identifierD:\vc6_test\mfc1\mfc1.cpp(362) : error C2065: ''IDS_SERVICENAME'' : undeclared identifierD:\vc6_test\mfc1\mfc1.cpp(362) : error C2065: ''LIBID_TEST1Lib'' : undeclared identifier

  我們可以在test1中找到IDR_Test1的聲明,放到mfc1中,解決第一條錯誤。但我們也可以去掉CServiceModule中與COM有關(guān)的一些代碼。這里我們刪除RegisterServer,UnregisterServer兩個(gè)函數,并讓Run函數成為

void CServiceModule::Run(){_Module.dwThreadID = GetCurrentThreadId();LogEvent(_T("Service started"));if (m_bService)SetServiceStatus(SERVICE_RUNNING);MSG msg;while (GetMessage(&msg, 0, 0, 0))DispatchMessage(&msg);}		
增加資源IDS_SERVICENAME為“mfc1”。
注釋掉CServiceModule::Init中“CComModule::Init(p, h, plibid);”一行。
注釋_tWinMain函數(技巧:用#if 0和#endif注釋)。

現在編譯程序,應該沒(méi)有錯誤了,但加入的CServiceModule還沒(méi)有起到作用。

在mfc1中的IDD_MFC1_DIALOG上加入兩個(gè)按鈕,分別是“安裝服務(wù)”,“卸載服務(wù)”。增加的單擊事件代碼為:
“安裝服務(wù)”按鈕:void CMfc1Dlg::OnButton1() { _Module.Install(); }
“卸載服務(wù)”按鈕:void CMfc1Dlg::OnButton2() { _Module.Uninstall(); }

下面在CMfc1App::InitInstance()中加入一些代碼:

_Module.Init(ObjectMap, this->m_hInstance, IDS_SERVICENAME, NULL);_Module.m_bService = TRUE;_Module.Start();

  地點(diǎn)是在原來(lái)產(chǎn)生對話(huà)框的代碼的地方。而原有的生成對話(huà)框的代碼轉移到Run()中,位置是在使用了SetServiceStatus函數設置服務(wù)狀態(tài)之后,并注釋掉其后的消息處理代碼,因對話(huà)框自身有消息處理機制。

編譯時(shí)若出現如下錯誤,將Install()和Uninstall()前的inline參數去掉即可:

mfc1Dlg.obj : error LNK2001: unresolved external symbol "public: int __thiscall CServiceModule::Install(void)" (?Install@CServiceModule@@QAEHXZ)

mfc1Dlg.obj : error LNK2001: unresolved external symbol "public: int __thiscall CServiceModule::Uninstall(void)" (?Uninstall@CServiceModule@@QAEHXZ)

現在可以編譯運行了。然后點(diǎn)擊“安裝服務(wù)”,就可以在服務(wù)列表中看到mfc1了。

四、這一服務(wù)程序運行時(shí)沒(méi)有圖形界面?

  不錯,剛才直接運行mfc1.exe時(shí)我們看到了圖形界面,但在服務(wù)列表中用右鍵菜單中的“啟動(dòng)”時(shí)卻看不到任何界面。這該怎么辦?
我們還需要在使用CreateService函數時(shí)(Install()中),加上一個(gè)參數,這樣才能允許程序與桌面交互,也就是可以顯示界面。這個(gè)參數是SERVICE_INTERACTIVE_PROCESS。
填加后的CreateService:

    SC_HANDLE hService = ::CreateService(hSCM, m_szServiceName, m_szServiceName,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);		
再次編譯mfc1,卸載服務(wù)后,安裝服務(wù)。我們可以看到,通過(guò)服務(wù)列表啟動(dòng)mfc1,原有的對話(huà)框出現了。

如需將服務(wù)設為自動(dòng)啟動(dòng),則將 SERVICE_DEMAND_START 改為 SERVICE_AUTO_START。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
用ATL編寫(xiě)Windows服務(wù)
vc6.0程序界面實(shí)現XP風(fēng)格方法
VC中加載LIB文件
vc調試適合入門(mén)
多線(xiàn)程技術(shù)在VC++串口通信程序中的應用研究
C、C++、API、SDK、IDE、VC++、MSDN、MFC、OWL、VCL、ATL 、BCB
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久