2009-10-20 5 views
5

से सेवा करने के लिए कमांड भेजें कि कैसे मैं सी ++ से Windows सेवा करने के लिए आदेश भेज सकते हैं? समतुल्य नेट कोड है:सी ++

ServiceController sc = new ServiceController("MyService"); 
sc.ExecuteCommand(255); 

उत्तर

3

देशी C++, आप की आवश्यकता होगी करने के लिए:

  1. ओपन सेवा नियंत्रण प्रबंधक को एक संभाल,
  2. सेवा आप नियंत्रित करना चाहते के लिए एक सेवा संभाल प्राप्त करने के लिए सेवा नियंत्रण प्रबंधक का उपयोग करें,
  3. सेवा करने के लिए एक नियंत्रण कोड या कोड भेजें, और
  4. बंद हैंडल चरण 1 में खोला गया और 2.

उदाहरण के लिए, यह कोड समय सिंक्रनाइज़ेशन सेवा को पुनरारंभ करता है। सबसे पहले, मैं ब्लॉक को छोड़ते समय उन्हें स्वचालित रूप से बंद करने के लिए, सेवा हैंडल के लिए एक रैपर क्लास बना देता हूं।

class CSC_HANDLE 
{ 
public: 
CSC_HANDLE(SC_HANDLE h) : m_h(h) { } 
~CSC_HANDLE() { ::CloseServiceHandle(m_h); } 
operator SC_HANDLE() { return m_h; } 
private: 
SC_HANDLE m_h; 
}; 

फिर, मैं सेवा नियंत्रण प्रबंधक (OpenSCManager() प्रयोग करके) और सेवा मैं नियंत्रित करने के लिए खोलें। ध्यान दें कि OpenService() में dwDesiredAccess पैरामीटर में प्रत्येक नियंत्रण के लिए अनुमतियां शामिल होनी चाहिए, या प्रासंगिक नियंत्रण फ़ंक्शन विफल हो जाएंगे।

BOOL RestartTimeService() 
{ 
    CSC_HANDLE hSCM(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, GENERIC_READ)); 
    if (NULL == hSCM) return FALSE; 

    CSC_HANDLE hW32Time(::OpenService(hSCM, L"W32Time", SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS)); 
    if (NULL == hW32Time) return FALSE; 

सेवा रोकने के लिए, मैं ControlService() का उपयोग SERVICE_CONTROL_STOP कोड भेजने के लिए, और फिर सुनिश्चित आदेश सफल बनाने के लिए वापसी मान की जाँच करें। यदि ERROR_SERVICE_NOT_ACTIVE के अलावा कोई त्रुटि रिपोर्ट की गई है, तो मुझे लगता है कि सेवा शुरू करने के लिए सफल नहीं होगा।

SERVICE_STATUS ss = { 0 }; 
    ::SetLastError(0); 
    BOOL success = ::ControlService(hW32Time, SERVICE_CONTROL_STOP, &ss); 
    if (!success) 
    { 
     DWORD le = ::GetLastError(); 
     switch (le) 
     { 
     case ERROR_ACCESS_DENIED: 
     case ERROR_DEPENDENT_SERVICES_RUNNING: 
     case ERROR_INVALID_HANDLE: 
     case ERROR_INVALID_PARAMETER: 
     case ERROR_INVALID_SERVICE_CONTROL: 
     case ERROR_SERVICE_CANNOT_ACCEPT_CTRL: 
     case ERROR_SERVICE_REQUEST_TIMEOUT: 
     case ERROR_SHUTDOWN_IN_PROGRESS: 
      return FALSE; 

     case ERROR_SERVICE_NOT_ACTIVE: 
     default: 
      break; 
     } 
    } 

सेवा रोकने के निर्देश देने के बाद, मैं सेवा प्रबंधक को यह रिपोर्ट करने का इंतजार करता हूं कि सेवा वास्तव में बंद हो गई है।

  1. नींद (1000), इस धागे पर संदेश पाश को निलंबित ताकि आप किसी अन्य विधि का उपयोग करना चाहिए निष्पादन में देरी करने के अगर यह समारोह चलेगा होगा: इस कोड दो संभावित कीड़े, जो आप उत्पादन कोड के लिए सही करने के लिए इच्छा हो सकती है है एक यूआई थ्रेड पर। आप MsgWaitForMultipleObjectsEx() का उपयोग कर उपयुक्त नींद-संदेश-लूप का निर्माण कर सकते हैं।
  2. GetTickCount() से लौटा दिया गया DWORD अंत में शून्य पर लपेट जाएगा; अगर यह काम इंतजार कर रहा है, तो यह चारों ओर लपेटता है, इंतजार मेरे इरादे से जल्द ही छोड़ सकता है।

    DWORD waitstart(::GetTickCount()); 
    while (true) 
    { 
        ZeroMemory(&ss, sizeof(ss)); 
        ::QueryServiceStatus(hW32Time, &ss); 
        if (SERVICE_STOPPED == ss.dwCurrentState) break; 
        ::Sleep(1000); 
        DWORD tick(::GetTickCount()); 
        if ((tick < waitstart) || (tick > (waitstart + 30000))) return FALSE; 
    } 
    

अंत में, जानते हुए भी कि सेवा एक बंद कर दिया अवस्था में है, मैं इसे फिर से StartService() रन कहते हैं।

success = ::StartService(hW32Time, 0, NULL); 
    if (!success) return FALSE; 

    return TRUE; 
}