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_IMPERSONAT E, // 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::ConnectServe r 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\\ro ot\\cimv2" ),
_bstr_t(L"User"), // User name
_bstr_t(L"Password"), // User password
NULL, // Locale
NULL, // Security flags
_bstr_t(L"NTLMDOMAIN:domai n"), // 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_IMPERSONAT E, // 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_S ervice.Nam e='Service Name'", 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(&varReturnValu e); varReturnValue;
HRESULT hr = pOutClass->Get(L"ReturnVal ue", 0, &varReturnValue, 0, 0);
cout << " Start Service : " << varReturnValue.uiVal << endl;
}
else cout <<"poutClass is null\n";
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
CoUninitialize();
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,
RPC_C_IMP_LEVEL_IMPERSONAT
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::ConnectServe
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\\ro
_bstr_t(L"User"), // User name
_bstr_t(L"Password"), // User password
NULL, // Locale
NULL, // Security flags
_bstr_t(L"NTLMDOMAIN:domai
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_IMPERSONAT
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_S
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(&varReturnValu
HRESULT hr = pOutClass->Get(L"ReturnVal
cout << " Start Service : " << varReturnValue.uiVal << endl;
}
else cout <<"poutClass is null\n";
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
CoUninitialize();
Do you have to use WMI? This task is way less tedious by using 'OpenSCManager()' for a remote machine.
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.
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>
BTW, have you thought of using 'PsService' (http://www.sysinternals.com/ntw2k/freeware/psservice.shtml)?
psservice [\\computer [-u username] [-p password]] <command> <options>
ASKER
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("WbemScriptin g.SWbemLoc ator")
Set objSWbemServices = objSWbemLocator.ConnectSer ver ("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.
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("WbemScriptin
Set objSWbemServices = objSWbemLocator.ConnectSer
Set colSwbemObjectSet = objSWbemServices.ExecQuery
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you all for your suggestions and comment, but the last comment really did the trick.. Thanks