WMI management scope connect to local instead of remote - c#

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)

Related

Detect if screensaver, configured by GPO, is running on remote PC

I am trying to detect if screen saver is running on a remote PC using WMI. The remote PC is Windows 7, but it should work for W8/W10 as well.
So far I was testing having screen saver set manually on the remote PC (via control panel) and relying on WMI Win32_Process containing SCREEN_SAVER_NAME.SCR:
ConnectionOptions options = new ConnectionOptions();
options.Username = "Username";
options.Password = "password";
ManagementScope scope =
new ManagementScope(
"\\\\10.1.1.1\\root\\cimv2", options);
scope.Connect();
while (true)
{
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (var item in queryCollection)
{
if ((string)item["Description"] == "PhotoScreensaver.scr")
{
Console.WriteLine("screensaver running");
}
}
}
This works fine when the screen saver is set via control panel on the remote PC.
However, when setting the screen saver via group policy, WMI Win32_Process no longer lists the .SCR file and my software obviously doesn't work as expected.
Any idea how to detect running screen savers, which was set using GPO?

What to specify for Local ManagementScope

I am trying to connect (locally) to get a list of virtual machines and their properties. I have hacked some code I found, but my code is failing to connect so I can only assume that the connection string is wrong.
Using Server 2012, Hyper-V
private void listVirtualMachines() {
ManagementScope manScope = new ManagementScope(#"\\LOCALHOST\root\cimv2");
if (manScope.IsConnected) {
ObjectQuery queryObj = new ObjectQuery("SELECT * FROM Msvm_ComputerSystem");
// connect and set up our search
ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(manScope, queryObj);
ManagementObjectCollection vmCollection = vmSearcher.Get();
// loop through the machines
foreach (ManagementObject vm in vmCollection) {
// display VM details
LogString(vm["ElementName"].ToString());
LogString(vm["EnabledState"].ToString());
LogString(vm["Description"].ToString());
}
} else {
//WE END UP HERE EVERY TIME!
LogString("Cannot Connect to ManagementScope!");
}
} //funct
In Server 2012, Msvm_ComputerSystem is in the WMI namespace root\virtualization\v2 so the code should be:
ManagementScope manScope = new ManagementScope(#"\\.\root\virtualization\v2");
manScope.Connect();

WMI: “File not found” when trying to retrieve “ServerNetworkProtocol” scope for SQL Server

I am trying to get Server Network Protocol (SQL Server) using WMI.
I had written small application:
---------------------------C# code--------------------------
ManagementScope scope = new ManagementScope(#"\\computerName\root\Microsoft\SqlServer\ComputerManagement");
scope.Options.Username = "Administrator";
scope.Options.Password = "Password";
scope.Connect();
var query = new ObjectQuery(#"SELECT * FROM ServerNetworkProtocol");
var searcher = new ManagementObjectSearcher(scope, query);
var managementObjectCollection = searcher.Get();
var result = managementObjectCollection.Cast<ManagementObject>().ToList(); //<---- FileNotFoundException
var s = result.First()["ProtocolName"].ToString();
MessageBox.Show(String.Format("Protocol name: {0}", s));
And when I run the application, I will receive System.IO.FileNotFoundException.
I tested the query using WBEMTest Utility and everything is okey (with Administrator credentials).
Later I had written test service and put the same code, and service works correctly without any exceptions.
I suppose the problem related with credentials.
Can anyone explain more detailed what's wrong. What permissions need to run this query (if problem with credentials) and how I can resolve the issue.
I will be appreciated for any help.
just check credential and change one line :
ManagementScope scope = new ManagementScope(#"\\computerName\root\Microsoft\SqlServer\ComputerManagement10");

Access Denied for WMI when impersonating user on remote machine

I'm trying to collect process information from remote machines using System.Management.
I'm impersonating an admin on the remote machine using something along these lines, but the following code throws an exception: "Access Denied".
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(#"\\" + machine + #"\root\cimv2", options);
scope.Connect();
ObjectQuery query = new ObjectQuery("Select * from Win32_Process where ProcessId = "
+ procID.ToString());
ManagementObjectSearcher mos = new ManagementObjectSearcher(scope, query);
string cmdLn = "";
foreach (ManagementObject mo in mos.Get())
{
cmdLn = (string)mo.GetPropertyValue("CommandLine");
}
However, if I supply the username and password to options, everything works fine.
I've verified that this code is executing as the impersonated context (which has sufficient permissions on the remote machine), so I'm not sure why it isn't working without the username/password passed.
Is it possible to authenticate successfully WITHOUT explicitly passing the user's credentials?
With WMI, when impersonating a specific user you must supply explicit credentials. The link you provided above states this with the variables lpszUsername and lpszPassword.

stop / start service or close the sql server process / service on a remote computer

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();

Categories

Resources