I'm trying to run a bat file remotely (from XP to 2003) and running into a problem connecting to any WMI namespace other than cimv2. The code below hits a "Not Found" exception in the "GetMethodParameters" call. But if I replace "directory" with "cimv2", everything is gravy.
ConnectionOptions theConnection = new ConnectionOptions();
theConnection.Username = conDet.User;
theConnection.Password = conDet.Pwd;
theConnection.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope theScope = new ManagementScope(String.Format(#"\\{0}\root\directory", conDet.Server), theConnection);
theScope.Connect();
ManagementClass processClass = new ManagementClass(theScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
enter code here
ManagementBaseObject inParams = processClass.GetMethodParameters("Create");
inParams["CommandLine"] = filename;
ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null);
I've checked the security on my machine and the server and the two namespaces have identical security settings. Any ideas what's going on?
Thanks.
you are using a wrong namespace, the Win32_Process WMI class is defined in root\cimv2.
So you must rewrite your code to
ManagementScope theScope = new ManagementScope(String.Format(#"\\{0}\root\cimv2", conDet.Server), theConnection);
Related
I tried to connect to a remote PC and query for its processes but when I run the code, it got connected with my local PC and obtained its processes instead of the remote PC.
The code is
ManagementScope scope = new ManagementScope(#"\\remote-user\\root\\cimv2");
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
You appear to be passing a username ("remote-user") instead of a hostname of the remote machine to your management scope. Change your code to e.g.:
ConnectionOptions options = new ConnectionOptions();
options.Password = "remoteUserPassword"; // you may want to avoid plain text password and use SecurePassword property instead
options.Username = "remote-user";
ManagementScope scope = new ManagementScope(#"\\remoteMachineHostname\root\cimv2", options);
(I assume that remote-user is Full computer name) change:
ManagementScope scope = new ManagementScope(#"\\remote-user\\root\\cimv2");
to:
ManagementScope scope = new ManagementScope(#"\\<FullComputerName>\root\cimv2");
another option:
ManagementScope scope = new ManagementScope("\\\\<FullComputerName>\\root\\cimv2");
See this link (it's Microsoft example)
Edit
if you want to connect with deffrent user you need to pass ConnectionOptions (see above link)
The following code works when "SelectedMachine" is the localhost where the C# exe is being launched from. When "SelectedMachine" is a remote machine, the process simply doesn't launch. No exceptions, no errors, acts as if it's successful, however, the process never starts. Any ideas?
object[] processToRun = { "notepad.exe" };
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.Authentication = AuthenticationLevel.PacketPrivacy;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", SelectedMachine), connOptions);
manScope.Connect();
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ManagementPath managementPath = new ManagementPath("Win32_Process");
ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions);
processClass.InvokeMethod("Create", processToRun );
Edit: When I go through wbemtest, same behavior occurs. When the Namespace is root\cimv2 (local), the process executes, when it is \RemoteMachineName\root\cimv2, it claims success but never starts on the remote machine. Not sure what I'm missing here.
This behavior is described in the Win32_Process.Create method documentation.
For security reasons the Win32_Process.Create method cannot be used to
start an interactive process remotely.
I'm trying to install/add a networked printer on a remote computer using WMI. The below code works perfectly when i enter my local computer name but i get an error message "Not Supported" when i use any remote computer name. I looked up the WMI Error on MSDN and read "Feature or operation is not supported." But also noticed on MSDN they have a 'howto' add a new printer connection to a remote computer and there VBs example. I copied the VBs example and ran it and also recieved the same error "Not Supported". What am i missing? Any idea on what I'm doing wrong?
ConnectionOptions conOp = new ConnectionOptions();
conOp.Impersonation = ImpersonationLevel.Impersonate;
conOp.Authentication = AuthenticationLevel.Default;
conOp.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(#"\\pcname\ROOT\CIMV2", conOp);
manScope.Connect();
ManagementClass manClass = new ManagementClass(manScope, new ManagementPath("Win32_Printer"), null);
ManagementBaseObject inParams = manClass.GetMethodParameters("AddPrinterConnection");
inParams["Name"] = #"\\server\printer";
////////Error Occurs Here
ManagementBaseObject outParams = manClass.InvokeMethod("AddPrinterConnection", inParams, null);
The main task of this short part is get some computer name and install on this PC needed software (throught msiexec.exe)
I do this
{
Credential creds = new Credential();
UserAttr UserCredential = new UserAttr();
UserCredential = creds.DefaultFlagsTest();
ConnectionOptions connection = new ConnectionOptions();
connection.Username = UserCredential.UserName;
connection.Password = UserCredential.password;
connection.Authentication = AuthenticationLevel.PacketPrivacy;
connection.Authority = "ntlmdomain:tcc1";
ManagementScope scope = new ManagementScope(
"\\\\"+computerName+"\\root\\CIMV2", connection);
scope.Connect();
ManagementClass classInstance =
new ManagementClass(scope,
new ManagementPath("Win32_Process"), null);
ManagementBaseObject inParams = classInstance.GetMethodParameters("Create");
inParams["CommandLine"] = #"msiexec.exe /qb /m log.mif /i ""\\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exec\Kaspersky Network Agent.msi""";
ManagementBaseObject outParams = classInstance.InvokeMethod("Create", inParams, null);
int res = int.Parse(outParams["ReturnValue"].ToString());
if (res == 0)
{
MessageBox.Show(outParams["ReturnValue"].ToString(), "Result");
}
else throw new System.ComponentModel.Win32Exception(res);
Close();
}
the program returns 0, but its doesnt mean that msiexec is complete with the same success. Error is check path of package .. or smth. But what i see in a log file log.mif:
..............................
START ATTRIBUTE
NAME = "Product"
ID = 2
ACCESS = READ-ONLY
STORAGE = SPECIFIC
TYPE = STRING(64)
VALUE = "\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exe"
END ATTRIBUTE
..............................
he crops the name of package at 64 symb. The reason is that parametr CommandLine of Win32_Process.Create has this limit.
I don't know how to overcome this...
Win32_Process.Create also has property CurrentDirectory, thath seems can solve this propblem. But he can't process UNC paths.
and i can't do the install directory shorter. it is not right. (And i can say that i've done this. And its worked)
Please, maybe you know how to solve this propblem with a long installation path?
different properties as TARGETDIR or INSTALLDIR set only path TO install, no FROM...
I gave up
START ATTRIBUTE
NAME = "Product"
ID = 2
ACCESS = READ-ONLY
STORAGE = SPECIFIC
TYPE = STRING(64)
VALUE = "\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exe"
END ATTRIBUTE
The value is limited to 64symb including path. It will be working properly only on a local machine without using UNC paths
I am trying to shutdown and start the sql server on a remote computer (on the same network), i have used this code
ConnectionOptions options = new ConnectionOptions();
options.Username = userName;
options.Password = password;
ManagementScope scope =
new ManagementScope(
string.Format(#"\\{0}\root\cimv2", serverFullName),
options);
scope.Connect();
ObjectQuery query = new ObjectQuery(
string.Format(#"SELECT * FROM Win32_Process WHERE Name='{0}'",
processToTerminate));
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
m.InvokeMethod("Terminate", null);
}
is there another way of doing that ?
how can i start the process (if Terminate close it)?
Thank you
What about using the ServiceController class? (see MSDN)
// just replace the params with your values
ServiceController sc = new ServiceController("SERVICENAME", "MACHINENAME");
if (sc.Status.Equals(ServiceControllerStatus.Running))
sc.Stop();
This should do the trick.
hth
It would seem a lot easier to just use the ServiceController class, that you can give a service name and computer name to, and then call methods such as Start and Stop.
Killing a process and stoping a service are two different things. A service could spawn other processes that will remain lingering. Also, you are effectively pulling the plug on the process. It isn't being given any time to stop gracefully, write everything to disk, etc.
Instead you should use the Win32_Service WMI object to find your service. This has a StartService and StopService method, which will allow you to stop and start it as you need.
Mind you, this WMI object is about services, not processes, so you will have to tweak your code to stop it by the service name, not the process name. Something like this:
ConnectionOptions options = new ConnectionOptions();
options.Username = userName;
options.Password = password;
ManagementScope scope = new ManagementScope(string.Format(#"\\{0}\root\cimv2", serverFullName), options);
scope.Connect();
ObjectQuery query = new ObjectQuery(string.Format(#"SELECT * FROM Win32_Service WHERE Name='{0}'",serviceToStop));
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
m.InvokeMethod("StopService", null);
}
Then later on you can use InvokeMethod on StartService.
you can do some like this to start and stop your sql server
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "net start \"Sql Server (SQLEXPRESS)\"";
process.Start();