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();
SoerenlpAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Do you have to use WMI? This task is way less tedious by using 'OpenSCManager()' for a remote machine.
0
SoerenlpAuthor Commented:
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.
0
jkrCommented:
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>
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

SoerenlpAuthor Commented:
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.
0
Amritpal SinghCommented:
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SoerenlpAuthor Commented:
Thank you all for your suggestions and comment, but the last comment really did the trick.. Thanks
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.