| 
我是用Visual Studio 2008 中的 VC++ 2008 寫系統(tǒng)服務的詳細步驟: 
 
1. 新建項目。 
1-1. 啟動 Visual Studio 2008。選擇 File -> New -> Project...。 
1-2. 在 New Project 對話框中,選擇 Visual C++ 中的 ATL Project 模板,寫入項目名稱:ShowjiSvc,點 OK。 
1-3. 在打開的 ATL Project Wizard - ShowjiSvc 中,點 Application Settings,選擇 Server type 為 Service(EXE),點 Finish。 
2. 安裝、卸載服務。 
2-1. 編譯項目。 
2-2. 打開命令提示符,切換到編譯后的目錄,執(zhí)行以下命令安裝服務:ShowjiSvc /Service
 
2-3. 打開服務管理,能找到一個名為 ShowjiSvc 的服務,啟動類型是 Manual??梢詥臃?、停止服務。 
2-4. 停止服務,然后用以下命令卸載服務:ShowjiSvc /UnRegServer
 
 
3. 修改服務的配置。 
3-1. 修改服務名稱:在 Resource View 中打開 String Table,修改 IDS_SERVICENAME 的 Caption 為服務的名稱:Showji Mobile Service。
 
3-2. 修改服務的描述:打開 ShowjiSvc.cpp 文件,在 CShowjiSvcModule 的聲明中增加以下函數(shù)聲明:
 
  HRESULT RegisterAppId(bool bService); 
再增加此函數(shù)的定義: 
 HRESULT CShowjiSvcModule::RegisterAppId(bool bService = false) throw()
{
  HRESULT hr = S_OK;
  BOOL res = __super::RegisterAppId(bService); 
  if (bService)
  {
    if (IsInstalled())
    {
      SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);
      SC_HANDLE hService = NULL;
      if (hSCM == NULL)
        hr = AtlHresultFromLastError();
      else
      {
        hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);
        if (hService != NULL)
        {
          ::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, 
                  SERVICE_AUTO_START,  // 修改服務為自動啟動
                  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                  m_szServiceName); // 通過修改資源IDS_SERVICENAME 修改服務的顯示名字
          SERVICE_DESCRIPTION Description;
          TCHAR  szDescription[1024];
          ZeroMemory(szDescription, 1024);
          ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION));
          lstrcpy(szDescription, _T("www.showji.com示例服務,by yangwei@ligsoft.com"));
          Description.lpDescription = szDescription;
          ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);
          ::CloseServiceHandle(hService);
        }
        else
          hr = AtlHresultFromLastError();
        ::CloseServiceHandle(hSCM);
      }
    }
  }
  return hr;
}
 
 
3-3. 測試修改后的服務。重新注冊服務,在服務管理器中可以看到服務的新名稱和描述,并且啟動狀態(tài)已經修改為 Automatic。
 測試成功后,注銷服務。
 
4. 修改服務的進程安全設置。 
打開 ShowjiSvc.cpp,在 CShowjiSvcModule 的聲明中,找到 InitializeSecurity 函數(shù),修改如下: 
  HRESULT InitializeSecurity() throw(){
 return CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
 RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL );
 }
 
要根據(jù)自己的情況,做相關的安全性設置。如果沒有什么特殊的安全性要求,就按照上面的格式寫就行了。 
如果沒有設置進程安全性的代碼,那么 VC 客戶端創(chuàng)建對象的時候,會返回 E_ACCESSDENIED 的錯誤。VB 客戶端的錯誤提示如下:
 實時錯誤 '70': 拒絕的權限(Run-time error '70': Permission denied)。
 
5. 增加服務的初始化和釋放操作。 
打開 ShowjiSvc.cpp,在 CShowjiSvcModule 的聲明中,增加以下聲明: 
  HRESULT PreMessageLoop(int nShowCmd);HRESULT PostMessageLoop();
 
增加以上聲明的相關定義: 
 HRESULT CShowjiSvcModule::PreMessageLoop(int nShowCmd) throw()
{
  HRESULT hr = __super::PreMessageLoop(nShowCmd);
  if (SUCCEEDED(hr))
  {
    // Add any custom code to initialize your service
  }
   return hr;
}
HRESULT CShowjiSvcModule::PostMessageLoop() throw()
{
   HRESULT hr = __super::PostMessageLoop();
   if (SUCCEEDED(hr))
   {
     // Add any custom code to uninitialize your service
   }
   return hr;
}
 
 
在相關的描述位置增加自己的代碼即可。 
6. 為服務增加一個叫做 MyMath 的示例組件。 
6-1. 選中 ShowjiSvc 項目,點菜單 Project -> Add Class...,選擇 ATL 中的 ATL Simple Object,點 Add。 
6-2. 在打開的 ATL Simple Object Wizard - ShowjiSvc 對話框的 Short name 中寫入組件名稱:MyMath。其它名稱會自動填好(當然您也可以修改)。 
6-3. 在 Option 中可以看到許多選項。如果您搞不懂這些,就保留默認值吧(建議看一下 COM 的相關書籍)。 
6-4. 打開 MyMath.rgs,為組件增加服務程序的 ID(代碼中的紅色粗體部分): 
 HKCR
{
   ShowjiSvc.MyMath.1 = s 'MyMath Class'
   {
     CLSID = s '{37F47E87-7D33-43CD-B591-DA01023F90BC}'
   }
   ShowjiSvc.MyMath = s 'MyMath Class'
   {
     CLSID = s '{37F47E87-7D33-43CD-B591-DA01023F90BC}'
     CurVer = s 'ShowjiSvc.MyMath.1'
   }
   NoRemove CLSID
   {
     ForceRemove {37F47E87-7D33-43CD-B591-DA01023F90BC} = s 'MyMath Class'
     {
       ProgID = s 'ShowjiSvc.MyMath.1'
       VersionIndependentProgID = s 'ShowjiSvc.MyMath'
       ForceRemove 'Programmable'
       LocalServer32 = s '%MODULE%'
       val AppID = s '%APPID%'
       'TypeLib' = s '{55E58774-E86F-4482-A521-38AE8C85FD1D}'
     }
   }
}
 
 
AppID 必須設置,否則客戶端創(chuàng)建對象的時候會超時并報錯誤:80080005 server execution failed。并且,系統(tǒng)日志中會出現(xiàn)一個錯誤:The server {uuid} did not register with DCOM within the required timeout.
 VB 客戶端的錯誤提示如下:
 實時錯誤 '429': ActiveX 部件不能創(chuàng)建對象(Run-time error '429': ActiveX component can't create object)。
 
7. 為 MyMath 組件增加一個方法。 
7-1. 在 Class View 中,右擊 IMyMath,選擇 Add -> Add Method...。 
7-2. 在打開的 Add Method Wizard - ShowjiSvc 對話框中,輸入 Method name: Sum;Parameter type 選擇 LONG,Parameter name 寫 a,Parameter attributes 選擇 in,點一下 Add;
 Parameter type 選擇 LONG,Parameter name 寫 b,Parameter attributes 選擇 in,點一下 Add;
 Parameter type 選擇 LONG*,Parameter name 寫 s,Parameter attributes 選擇 retval,點一下 Add;
 點 Finish 添加這個方法。
 
7-3. 打開 MyMath.cpp 文件,找到 Sum 方法,修改如下: 
STDMETHODIMP CMyMath::Sum(LONG a, LONG b, LONG* s){
 *s = a + b;
 return S_OK;
 }
 
8. 編譯、注冊、啟動服務。 
8-1. 編譯代碼。 
8-2. 注冊服務,執(zhí)行以下命令行代碼:ShowjiSvc /Service
 
8-3. 啟動服務,執(zhí)行以下命令行代碼:net start "Showji Mobile Service"
 當然,也可以在服務管理器中啟動服務。
 相對應的停止服務的命令是:
 net stop "Showji Mobile Service"
 
9. 客戶端訪問測試(用 VB6 舉例)。 
9-1. 打開 Visual Basic 6.0。 
9-2. 新建“標準 EXE”工程。 
9-3. 點菜單:工程 -> 引用...,找到 ShowjiSvc 1.0 Type Library 并勾選,點確定。 
9-4. 雙擊 Form1 窗體,進入代碼模式,輸入以下代碼: 
Private Sub Form_Load()Dim math As ShowjiSvcLib.MyMath
 Set math = New ShowjiSvcLib.MyMath
 MsgBox math.Sum(10, 19)
 Set math = Nothing
 End Sub
 
執(zhí)行后可以看到,VB 正常初始化了系統(tǒng)服務中的 COM 對象,并調用了其中的方法。 
10. 部署。 
要將項目部署到其它電腦,需要安裝 Microsoft Visual C++ 2008 Redistributable Package,否則會提示錯誤:系統(tǒng)無法執(zhí)行指定的程序(The system cannot execute the specified program.)。 
 
 |