2010-04-08 61 views
2

我有一個基於ATL 7的CAtlServiceModuleT類的Windows服務。此服務提供系統上各種應用程序使用的COM對象,如果服務在運行時停止,則這些其他應用程序自然會出現錯誤。如何在ATL 7中拒絕Windows「服務停止」請求?

我知道,ATL的DLL由DllCanUnloadNow()如果CComModule類的GetLockCount()返回0。也就是說返回S_OK解決這個問題,它會檢查,以確保沒有人正在使用任何COM對象的DLL擔任了。我想要服務中的等效功能。

這裏是我在我的CAtlServiceModuleT::OnStop()覆蓋完成:

void CMyServiceModule::OnStop() 
{ 
    if(GetLockCount() != 0) { 
     return; 
    } 

    BaseClass::OnStop(); 
} 

現在,當用戶試圖停止從服務面板服務,它們都帶有一條錯誤消息:

Windows無法停止本地計算機上的XYZ服務。 服務沒有返回錯誤。這可能是內部Windows錯誤或內部服務錯誤。 如果問題仍然存在,請聯繫您的系統管理員。

停止請求確實被拒絕,但它似乎使服務處於不良狀態。第二個「停止」請求會導致此錯誤消息:

Windows無法停止本地計算機上的XYZ服務。

錯誤1061:此時服務無法接受控制消息。

有趣的是,服務確實停止了這一次(儘管我寧願不要這樣做,因爲仍然有未解決的COM引用)。

我有兩個問題:

  1. 是它認爲不好的做法爲服務拒絕停止的時候問?
  2. 有沒有禮貌的方式來表示停止請求被拒絕;一個不會將服務置於不良狀態?
+0

我肯定會認爲這是一個不好的做法,不要停止時,用戶要求。除非你完全相信你的服務沒有缺陷,否則你會迫使他們重新啓動,或者更糟糕的是,如果你的服務出現意外情況。 – jnoss 2010-04-08 16:42:40

回答

1

你不能這樣做。一旦SCM向您的服務發送SERVICE_CONTROL_STOP,您必須停止。

如果您的其他應用程序也是服務,您可以使它們在SCM內依賴。當然,如果使用此服務的應用程序只是不能使用的常規應用程序。

1

當ATL的鎖計數遞增到1,調用SetServiceStatus()SERVICE_ACCEPT_STOP國旗在SERVICE_STATUS::dwControlsAccepted場省略。那麼你根本就不會收到任何SERVICE_CONTROL_STOP的請求。任何停止服務的嘗試都將立即失敗。當ATL的鎖計數回落到0時,再次撥打SetServiceStatus()並指定SERVICE_ACCEPT_STOP標誌。

我只需要在2(較老的)基於ATL的服務中做到這一點,它運行良好。當然,我無法找出直接覆蓋Lock()和Unlock()的最佳方法,因此我只在服務中放入一個小循環,頻繁檢查GetLockCount(),並在需要時調用SetServiceStatus()

0

在您的構造函數中,更新m_status.dwControlsAccepted刪除SERVICE_ACCEPT_STOP。例如:

CMyServiceModule::CMyServiceModule() 
    : ATL::CAtlServiceModuleT<CMyServiceModule, IDS_SERVICENAME>() 
{ 
    m_status.dw &= ~SERVICE_ACCEPT_STOP 
}