Get hardware information of Windows Server - c#

Currently I'm using following methods to get hardware information (network adapter, processor, hdd)
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_processor");
ManagementObject dsk = new ManagementObject(#"win32_logicaldisk.deviceid=""c:""");
My app is desktop, client-server (app and db are installed on server).
This methods get information for client. Is there a way to get hardware information for some node on lan - I want to get hardware information for server?

This is a subroutine I use in order to query remote hosts (here I assume I already configured WMI on the remote computer):
public string getWMI(string[] parameters)
{
string ip = parameters[0];
string username = parameters[1];
string password = parameters[2];
string query = parameters[3];
string result = "";
ConnectionOptions options = new ConnectionOptions();
ManagementScope scope;
options.Username = username;
options.Password = password;
try
{
scope = new ManagementScope("\\\\" + ip + "\\root\\cimv2", options);
scope.Connect();
if (scope.IsConnected)
{
ObjectQuery q = new ObjectQuery(query);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, q);
ManagementObjectCollection objCol = searcher.Get();
foreach (ManagementObject mgtObject in objCol)
{
result = result + mgtObject.GetText(TextFormat.CimDtd20);
}
}
else
{
}
}
catch (Exception e)
{
writeLogFile("WMI Error: " + e.Message);
writeLog("WMI Error: " + e.Message);
}
return result;
}
In that subroutine I use a direct query such as "select * from Win32_ComputerSystem" but you can use ManagementClass as well.

I want to get hardware information for server?
WMI can poin to another server as long as:
The eserver exposes WMI
The fireawall does not block it.
Your user account has the rights on the other server.
Simple like that.

Related

How can I read the CPU Load of a remote PC with CIM session instead of WMI? I have to use the admin credentials of the remote PC

I am using the following code for reading CPU Load on remote PC with Win XP. I have to use the credentials on the remote PC. It is working fine. But how can I use CIM session instead of WMI?
public void Read_CPU_Load_WMI()
{
WMI_path = "\\\\" + TagService.IP_to_Connect + "\\root\\cimv2";
System.Management.ConnectionOptions options = new System.Management.ConnectionOptions();
options.Username = username;
options.Password = password;
ManagementScope scope = new ManagementScope(WMI_path, options);
scope.Connect();
SelectQuery query = new SelectQuery("select PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor where Name='_Total'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject queryObj in searcher.Get())
{
CPU_Load_WMI_int = Convert.ToInt16(queryObj["PercentProcessorTime"]);
CPU_Load_WMI_str = queryObj["PercentProcessorTime"].ToString();
}
}
I have started as following but cannot finish it
public void Read_CPU_Load_CIM
{
WMI_path = "\\\\" + TagService.IP_to_Connect + "\\root\\cimv2";
System.Management.ConnectionOptions options = new System.Management.ConnectionOptions();
options.Username = username;
options.Password = password;
string Namespace = #"root\cimv2";
string OSQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor where Name='_Total'";
CimSession mySession = CimSession.Create(WMI_path);
IEnumerable<CimInstance> queryInstance = mySession.QueryInstances(Namespace, "WQL", OSQuery);
//CPU_Load_WMI_int = ???
}

c# connect to remote using wmi needs /etc/hosts

I am using below code to connect remote computer however it needs that the remote computer must be exist at '#drivers/etc/hosts' file.
If i don't write the information about remote computer on /etc/hosts file it gives below error;
the rpc server is unavailable
How can i connect to rdp without modifying '#drivers/etc/hosts' file ?
public void GetSystemInformation()
{
ConnectionOptions options = new ConnectionOptions();
options.Username = "test";
options.Password = "test";
options.EnablePrivileges = true;
ManagementScope scope = new ManagementScope("\\\\someip\\root\\cimv2", options);
scope.Connect();
//Query system for Operating System information
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
// Display the remote computer information
Console.WriteLine("Computer Name : {0}",m["csname"]);
Console.WriteLine("Windows Directory : {0}", m["WindowsDirectory"]);
Console.WriteLine("Operating System: {0}", m["Caption"]);
Console.WriteLine("Version: {0}", m["Version"]);
Console.WriteLine("Manufacturer : {0}",m["Manufacturer"]);
}
}

Returning Values from ObjectReadyEventHandler

I'm writing a program that returns a list of users currently logged in a server.
Here's the code that does this:
private List<string> GetUsers(string server)
{
ConnectionOptions options = new ConnectionOptions();
ManagementScope moScope = new ManagementScope(#"\\" + server + #"\root\cimv2");
moScope.Connect();
ObjectQuery query = new ObjectQuery("select * from Win32_Process where name='explorer.exe'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(moScope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
ManagementOperationObserver mo = new ManagementOperationObserver();
mo.ObjectReady += new ObjectReadyEventHandler(mo_ObjectReady);
m.InvokeMethod(mo, "GetOwner", null);
}
}
private void mo_ObjectReady(object sender, ObjectReadyEventArgs e)
{
string user = e.NewObject.Properties["user"].Value.ToString();
//I would like to return the username back to the GetUsers function. How can I do this?
}
The mo_ObjectReady can get one username that is currently logged in the server. How could I return the value to the GetUsers function so I can put them altogether in a List?
Thanks in advance.

Is a process running on a remote machine?

I have three remote PC's to which I remotely connect. I am trying to write a simple Windows application that would display in a single window whether a particular process is running on either of the machines, e.g.
Server1: Chrome not running
Server2: Chrome IS running
Server3: Chrome IS running
I used WMI and C#. So far I've got this much:
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = #"domain\username";
connectoptions.Password = "password";
//IP Address of the remote machine
string ipAddress = "192.168.0.217";
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2");
scope.Options = connectoptions;
//Define the WMI query to be executed on the remote machine
SelectQuery query = new SelectQuery("select * from Win32_Process");
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query))
{
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject process in collection)
{
// dwarfs stole the code!! :'(
}
}
I think it is all set up correctly, but if I MessageBox.Show(process.ToString()) inside the foreach loop, I get a whole bunch of message boxes with the following text:
\\username\root\cimv2:W32_Process.Handle="XXX"
I am kind of stuck. Is there any way I can "translate" that XXX to a process name? Or else, how can actually get the names of the processes so I can use an if statement to check whether it is a "chrome" process?
Or...is my implementation an overkill? Is there an easier way to accomplish this?
Thanks a lot!
In your foreach, try this:
Console.WriteLine(process["Name"]);
You can filter the name of the process to watch in the WQL sentence, so you can write something like this
SelectQuery query = new SelectQuery("select * from Win32_Process Where Name='Chrome.exe'");
Try this sample app
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
ConnectionOptions Conn = new ConnectionOptions();
Conn.Username = "";
Conn.Password = "";
Conn.Authority = "ntlmdomain:DOMAIN";
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn);
}
else
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_Process Where Name='Chrome.exe'");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
//for each instance found, do something
Console.WriteLine("{0,-35} {1,-40}","Name",WmiObject["Name"]);
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
Try Process.GetProcesses("chrome", "computerName");
Defined in System.Diagnostics.Process as
public static Process[] GetProcessesByName(
string processName,
string machineName)

Kill a process on a remote machine in C#

This only helps kills processes on the local machine. How do I kill processes on remote machines?
You can use wmi. Or, if you don't mind using external executable, use pskill
I like this (similar to answer from Mubashar):
ManagementScope managementScope = new ManagementScope("\\\\servername\\root\\cimv2");
managementScope.Connect();
ObjectQuery objectQuery = new ObjectQuery("SELECT * FROM Win32_Process Where Name = 'processname'");
ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(managementScope, objectQuery);
ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get();
foreach (ManagementObject managementObject in managementObjectCollection)
{
managementObject.InvokeMethod("Terminate", null);
}
I use the following code. psKill is also a good way to go but sometimes you need to check the some other stuff, for example in my case remote machine was running multiple instances of same process but with different command line arguments, so following code worked for me.
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = string.Format(#"carpark\{0}", "domainOrWorkspace\RemoteUsername");
connectoptions.Password = "remoteComputersPasssword";
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2");
scope.Options = connectoptions;
SelectQuery query = new SelectQuery("select * from Win32_Process where name = 'MYPROCESS.EXE'");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
ManagementObjectCollection collection = searcher.Get();
if (collection.Count > 0)
{
foreach (ManagementObject mo in collection)
{
uint processId = (uint)mo["ProcessId"];
string commandLine = (string) mo["CommandLine"];
string expectedCommandLine = string.Format("MYPROCESS.EXE {0} {1}", deviceId, deviceType);
if (commandLine != null && commandLine.ToUpper() == expectedCommandLine.ToUpper())
{
mo.InvokeMethod("Terminate", null);
break;
}
}
}
}

Categories