Link to home
Start Free TrialLog in
Avatar of Soerenlp
Soerenlp

asked on

Start and Stop Services on Remote computer

Hi,

Im trying to start a service remotely using WMI in c++. I have this working in VB Script, but I get Access Denied error when I try it in C++.
Are there additional security settings that have to be set? I made changes recommeded on microsoft site to dcom. The Username and Password I use have admin rights on remote pc.

I would really appreciate any help anyone can provide.
Thanks

My code is:

 HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x"
            << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------

    hres =  CoInitializeSecurity(
        NULL,
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities
        NULL                         // Reserved
        );

                     
    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;                    // Program has failed.
    }
   
    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,            
        0,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;

    // Connect to the remote root\cimv2 namespace
    // and obtain pointer pSvc to make IWbemServices calls.
    //---------------------------------------------------------
    // change the computerName and domain
    // strings below to the full computer name and domain
    // of the remote computer
   
    hres = pLoc->ConnectServer(
        _bstr_t(L"\\\\RemotePC\\root\\cimv2"),
        _bstr_t(L"User"),                 // User name
        _bstr_t(L"Password"),                  // User password
        NULL,               // Locale            
        NULL,                             // Security flags
        _bstr_t(L"NTLMDOMAIN:domain"),    // Authority        
        0,                                // Context object
        &pSvc                             // IWbemServices proxy
        );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x"
             << hex << hres << endl;
        pLoc->Release();    
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels on a WMI connection ------------------

    hres = CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL ,                                    // client identity
       EOAC_NONE                    // proxy capabilities
    );

    if (FAILED(hres))
    {
            if(hres == E_INVALIDARG) cout << "Invalid args setting proxy blanket.\n";
        cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();    
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----

    // For example, get the name of the operating system
    IWbemClassObject *pOutClass = NULL;
      hres = pSvc->ExecMethod(L"Win32_Service.Name='ServiceName'", L"StartService", 0, NULL, NULL, &pOutClass, NULL);

       if (FAILED(hres))
        {
            cout << "Could not Start Service. Error code = 0x"  << hex << hres << endl;
            pSvc->Release();
           pLoc->Release();
           CoUninitialize();
           return 1;               // Program has failed.
       }
      
      if(pOutClass != NULL)
      {
                        VARIANT varReturnValue;
                        VariantInit(&varReturnValue); varReturnValue;
              HRESULT hr = pOutClass->Get(L"ReturnValue", 0, &varReturnValue, 0, 0);
            
              cout << " Start Service : " << varReturnValue.uiVal << endl;
      }
      else cout <<"poutClass is null\n";
      
    // Cleanup
    // ========
   
    pSvc->Release();
    pLoc->Release();
    CoUninitialize();
Avatar of jkr
jkr
Flag of Germany image

Do you have to use WMI? This task is way less tedious by using 'OpenSCManager()' for a remote machine.
Avatar of Soerenlp
Soerenlp

ASKER

Thanks for replying.
No it doesnt have to be WMI, anything that works would be great.

I did try with OpenSCManager before but for that to work you have to be logged in to the Admin Account. I want to get it so anyone can run my application (anyone on domain) and they can start and stop services on another computer. My application will hold the Admin account details which it can pass to WMI. The OpenSCManager does not (not that I know of) allow you to pass in the username and pwd.
You will not be able to control services on a remote machine without an account that has the appropriate permissions to do so anyway, also not with WMI.

BTW, have you thought of using 'PsService' (http://www.sysinternals.com/ntw2k/freeware/psservice.shtml)?

psservice [\\computer [-u username] [-p password]] <command> <options>
I do have account information. I dont want to be logged into that account, I want to just pass the account details on.

I have this working in VB Script - see code below.
However rather than running an external process from my C++ app Id rather have a function in C++ that did the same.

Dim objProcess
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer ("CompName", "root\cimv2", "DOMAIN\User", "Password")          
Set colSwbemObjectSet = objSWbemServices.ExecQuery ("Select * From Win32_Service WHERE Name = 'ServiceName'")
For Each objProcess in colSWbemObjectSet
    returnVal =    objProcess.StartService()
Next

Thanks for link to psService. It does work but again Id have to call it from my c++ app which Id prefer not to do.
ASKER CERTIFIED SOLUTION
Avatar of Amritpal Singh
Amritpal Singh
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you all for your suggestions and comment, but the last comment really did the trick.. Thanks