----此例中原程序使用Delphi編制,老妖將之改成CB版。:D
----WindowsNTServer提供多種功能強大的服務(Service),例如FTP,WWW或遠程登錄服務,另外常用的數據庫服務器也是以Service的形式存在於NTServer上的,如Sybase SQLServer For NT。Service一般在NT啟動時自動啟動,在NT關機時停止。但是有時用戶可能想手工啟動、暫停、停止某項Service,這就需要在控制面板中進行配置,對於不太熟悉NT的用戶來說比較困難;對於軟件開發人員,有時需要在軟件中訪問和操作某項Service,甚至可能需要開發新Service的提供給用戶使用。上面兩種情況都可以通過對Service的編程來解決。對Service的編程涉及到NT的內核,比較復雜且相關資料較少,給軟件開發人員帶來很多困難,筆者通過對WindowsNT的API的分析找到了相應的編程方法,再此介紹給大家。
----在WindowsNT下,各種Service都存在service control manager database中,因此我們可以通過對service control manager database進行操作來實現對Service的編程。下面介紹常用的函數:
1:SC_HANDLE OpenSCManager(LPCTSTR lpszMachineName,LPCTSTR lpszDatabaseName,DWORD fdwDesiredAccess);
----Open SCManager 函數打開指定計算機上的service control manager database。其中參數lpszMachineName指定計算機名,若為空則指定為本機。參數lpszDatabaseName指定要打開的service control manager database,默認為空。
----參數fdwDesiredAccess指定操作的權限,可以為下面取值之一
SC_MANAGER_ALL_ACCESS //所有權限
SC_MANAGER_CONNECT //允許連接service control manager
SC_MANAGER_CREATE_SERVICE //允許創建服務對象並把它加入service control manager database
SC_MANAGER_ENUMERATE_SERVICE //允許枚舉service control manager database中的服務
SC_MANAGER_LOCK //允許鎖住service control manager database
SC_MANAGER_QUERY_LOCK_STATUS //允許獲取servicecontrolmanagerdatabase的封鎖信息
----函數返回值:函數執行成功則返回一個指向service control manager database的句柄,失敗則返回NULL。
2:SC_HANDLE OpenService(SC_HANDLE schSCManager,LPCTSTR lpszServiceName,DWORD fdwDesiredAccess);
----OpenService函數打開指定的Service。
----其中參數schSCManager是指向service control manager database的句柄,由OpenSCManager函數返回。
----參數lpszServiceName要打開的服務的名字,注意大小寫。
----參數fdwDesiredAccess指定操作的權限,可以為下面取值之一
SERVICE_ALL_ACCESS //所有權限
SERVICE_CHANGE_CONFIG //允許更改服務的配置
SERVICE_ENUMERATE_DEPENDENTS //允許獲取依賴於該服務的其他服務
SERVICE_INTERROGATE //允許立即獲取服務狀態
SERVICE_PAUSE_CONTINUE //允許暫停和喚醒服務
SERVICE_QUERY_CONFIG //允許獲取服務配置
SERVICE_QUERY_STATU //允許通過訪問service control manager獲取服務狀態
SERVICE_START //允許啟動服務
SERVICE_STOP //允許停止服務
SERVICE_USER_DEFINE_CONTROL //允許用戶指定特殊的服務控制碼
----函數返回值:函數執行成功則返回指向某項服務的句柄,失敗則返回NULL。
3:BOOL QueryServiceStatus(SC_HANDLE schService,LPSERVICE_STATUS lpssServiceStatus);
----QueryServiceStatus函數返回指定服務的當前狀態。
----其中參數schService是指向某項服務的句柄,由OpenService函數返回,且必須SERVICE_QUERY_STATUS的權限。
----參數lpssServiceStatus中存放返回的服務狀態信息,結構如下
typedefstruct_SERVICE_STATUS
{
DWORD dwServiceType; //服務類型
DWORD dwCurrentState; //當前狀態
DWORD dwControlsAccepted; //服務可接受的控制碼
DWORD dwWin32ExitCode; //Win32出錯代碼
DWORD dwServiceSpecificExitCode;//服務出錯代碼
DWORD dwCheckPoint; //用於跟蹤服務長時間操作
DWORD dwWaitHint; //服務某一操作的最大允許時間,以毫秒為單位
}SERVICE_STATUS,*LPSERVICE_STATUS;
----函數返回值:函數執行成功則返回True,失敗則返回False。
4:BOOLStartService(SC_HANDLE schService,DWORD dwNumServiceArgs,LPCTSTR * lpszServiceArgs);
----StartService函數啟動指定的服務。
----其中參數schService是指向某項服務的句柄,由OpenService函數返回,且必須有SERVICE_START的權限。
----dwNumServiceArgs為啟動服務所需的參數的個數。
----lpszServiceArgs為啟動服務所需的參數。函數返回值:函數執行成功則返回True,失敗則返回False。
5:BOOL ControlService(SC_HANDLE hService,DWORD dwControl,LPSERVICE_STATUS lpServiceStatus);
----ControlService函數向Win32service發送控制碼。
----其中參數hService是指向某項服務的句柄,由OpenService函數返回。
----參數dwControl為控制碼,常用的有
SERVICE_CONTROL_STOP //停止服務
SERVICE_CONTROL_PAUSE //暫停服務
SERVICE_CONTROL_CONTINUE //喚醒暫停的服務
SERVICE_CONTROL_INTERROGATE//刷新某服務的狀態
----參數lpServiceStatus指向SERVICE_STATUS結構,用於存放該服務最新的狀態信息。
----函數返回值:函數執行成功則返回True,失敗則返回False。
6:BOOL EnumServicesStatus(SC_HANDLE hSCManager,DWORD dwServiceType,DWORD dwServiceState,LPENUM_SERVICE_STATUS lpServices,DWORD cbBufSize,LPDWORD pcbBytesNeeded,LPDWORD lpServicesReturned,LPDWORD lpResumeHandle);
----EnumServicesStatus函數用於枚舉NT下存在的Service。
----其中參數hSCManager是指向service control manager database的句柄,由OpenSCManager函數返回,且必須有SC_MANAGER_ENUMERATE_SERVICE的權限。
----參數dwServiceType指定按服務的類型枚舉。
----參數dwServiceState指定按服務的狀態枚舉。
----參數lpServices指向ENUM_SERVICE_STATUS結構,用於存放返回的服務的名字和狀態信息。
----參數cbBufSize返回參數lpServices的長度,以字節為單位。
----參數pcbBytesNeeded返回獲取剩余的Service所需字節的個數。
----參數lpServicesReturned返回服務的個數。
----參數lpResumeHandle,當第一次調用時該參數為0,當該函數再次被調用以獲取另外的信息時,該參數表示下一個被讀的Service。
----函數返回值:函數執行成功則返回True,失敗則返回False。
----值得注意的是通常情況下該函數返回的結果為FALSE,我們可以調用GetLastError()來獲取進一步信息。因為一台機器上有多種服務存在,所以GetLastError()應為ERROR_MORE_DATA,此時應再次調用EnumServicesStatus函數以獲取正確的Service列表。
----下面有一個用Delphi編的一個程序例子,用其他開發工具如VC,VB也可實現。程序運行時,單擊按鈕Button1枚舉NT中的Service並顯示在列表框ListBox1中。在ListBox1選中某個Service,單擊按鈕Button2則啟動該Service,單擊按鈕Button3則停止該Service。
首先在Unit1.hpp中添加
#include <winsvc.hpp>
然後在Class Form1的Private中添加
SC_HANDLE hscmanager,hService;
TServiceStatus returnstatus;
以下是Unit1.cpp的內容:
/**************************************************************************
* 枚舉NT系統當服務並啟動或終止之。
* Edited by 黑山老妖
* 2002.8.9
****************************************************************************/
void __fastcall TForm1::Button1Click(TObject *Sender)
{
DWORD BytesNeeded,serviceReturned,resumeHandle;
bool returnflag;
TEnumServiceStatus lpservice[100];
TEnumServiceStatus service;
DWORD i,bytes;
ListBox1->Items->Clear();
returnflag=false;
resumeHandle=0;
hscmanager=OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);//打開service control manager database
if (hscmanager<0)
{
ShowMessage("無法打開service control manager database");
return;
}
returnflag=EnumServicesStatus(hscmanager,SERVICE_DRIVER,SERVICE_ACTIVE,&service,sizeof(service),&BytesNeeded,&serviceReturned,&resumeHandle);//枚舉Service
if(!returnflag&&GetLastError()==ERROR_MORE_DATA)
{
bytes=BytesNeeded+sizeof(TEnumServiceStatus);
EnumServicesStatus(hscmanager,SERVICE_DRIVER,SERVICE_ACTIVE,&lpservice[0],bytes,&BytesNeeded,&serviceReturned,&resumeHandle);
for(i=0;i<serviceReturned-1;i++)
{
ListBox1->Items->Add(lpservice[i].lpServiceName);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
int i;
for(i=0;i<ListBox1->Items->Count;i++)
{
if(ListBox1->Selected[i])
{
hService=OpenService(hscmanager,PChar(ListBox1->Items->Strings[i].c_str()),SERVICE_ALL_ACCESS);//打開該Service
if(hService<0)
{
ShowMessage("無法打開該服務!");
return;
}
QueryServiceStatus(hService,&returnstatus);//查看該Service的狀態
if(returnstatus.dwCurrentState==SERVICE_STOPPED)//如果該Service已停止則啟動它
//SERVICE_STOPPED==1,SERVICE_RUNNING==4 老妖注。
{
if(StartService(hService,0,NULL))
ShowMessage("啟動成功!");
else
ShowMessage("無法啟動該服務!");
}
CloseServiceHandle(hService);//關閉該Service
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
int i;
for(i=0;i<ListBox1->Items->Count;i++)
{
if(ListBox1->Selected[i])
{
hService=OpenService(hscmanager,PChar(ListBox1->Items->Strings[i].c_str()),SERVICE_ALL_ACCESS);//打開該Service
if(hService<0)
{
ShowMessage("無法打開該Service");
return;
}
QueryServiceStatus(hService,&returnstatus);//查看該Service的狀態
if(returnstatus.dwCurrentState==SERVICE_RUNNING) //如果該Service正在運行則停止它
{
if(ControlService(hService,SERVICE_CONTROL_STOP,&returnstatus))
ShowMessage("成功停止!");
else
ShowMessage("無法停止該服務!");
}
CloseServiceHandle(hService);//關閉該Service
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseServiceHandle(hscmanager);//關閉service control manager database
}
//---------------------------------------------------------------------------