stop process using WMI - c#

I'm trying to stop a process on a remote machine using WMI
try
{
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Username = IFS_username;
connectionOptions.Password = IFS_password;
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope("\\\\" + IFS_IP + "\\root\\CIMV2", connectionOptions);
scope.Connect();
ManagementPath path = new ManagementPath("Win32_Process");
ManagementClass services;
services = new ManagementClass(scope, path, null);
foreach (ManagementObject service in services.GetInstances())
{
if (service.GetPropertyValue("Name").ToString().ToLower()=="notepad.exe")
{
service.InvokeMethod("Terminate", null);
}
}
}
catch (Exception ex)
{ textBox1.Text = ex.ToString(); }
}
But I got the following exception
System.Runtime.InteropServices.COMException (0x800706BA):
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
at System.Management.ThreadDispatch.Start()
at System.Management.ManagementScope.Initialize()
at System.Management.ManagementScope.Connect()
After some messing around the exception changed to
enter code here
I have checked couple of pages and it seems my method is correct, but I'm not able to find a solution for the exception.

Related

Registry value returns null when key has spaces uwing WMI

When trying to retrieve the value of a registry key from a remote machine for a key that has spaces using WMI in C# (Reason for using WMI: Authentication and Impersonation needed), the GetStringValue returns null but when the key doesn't have spaces, it works perfectly. Using either the # notation or standard " notation for strings didn't help. I tried enclosing the key in double-quotes. Didn't help either.
Here's the code I have written:
public static string GetRemoteRegistryValue(string MachineName, string username, string password)
{
string regValue = string.Empty;
ConnectionOptions opt = new ConnectionOptions();
opt.Impersonation = ImpersonationLevel.Impersonate;
opt.EnablePrivileges = true;
opt.Username = username;
opt.Password = password;
opt.Impersonation = ImpersonationLevel.Impersonate;
opt.EnablePrivileges = true;
try
{
ManagementPath p = new ManagementPath("\\\\" + MachineName + "\\root\\cimv2");
ManagementScope msc = new ManagementScope(p, opt);
msc.Connect();
string softwareRegLoc = "\"SOFTWARE\\VMware, Inc.\\VMware Drivers\"";
//string softwareRegLoc = #"""SOFTWARE\SAP BusinessObjects\Suite XI 4.0\Config Manager""";
ManagementClass registry = new ManagementClass(msc, new ManagementPath("StdRegProv"), null);
ManagementBaseObject inParams = registry.GetMethodParameters("GetStringValue");
inParams["hDefKey"] = 0x80000002;//HKEY_LOCAL_MACHINE
inParams["sSubKeyName"] = softwareRegLoc;
inParams["sValueName"] = "VmciHostDevInst";
// Read Registry Key Names
ManagementBaseObject outParams = registry.InvokeMethod("GetStringValue", inParams, null);
if (outParams.Properties["sValue"].Value != null)
{
regValue = outParams.Properties["sValue"].Value.ToString();
}
}
catch (ManagementException Ex)
{
}
catch (System.UnauthorizedAccessException Ex)
{
}
catch (Exception Ex)
{
}
return regValue;
}
What is the solution for this issue?
Okay, two points here:
You shouldn't use quotation marks. So, replace "\"SOFTWARE\\VMware, Inc.\\VMware Drivers\"" with "SOFTWARE\\VMware, Inc.\\VMware Drivers".
The path that you're trying to access belongs to the 64-bit provider. In order to be able to access it (by default), your application needs to have its Platform Target set to x64. Otherwise, your application would be trying to access the HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\VMware, Inc.\VMware Drivers path, which probably doesn't exist.
Removing the quotation marks and targeting x64 worked just fine for me and I got the value of the exact path mentioned in the question.
If your Platform Target is set to x86 (or Any CPU with the Prefer 32-bit checkbox ticked) and you don't want to change it to x64, then you have to force WMI to access the 64-bit Registry Hive. Check the documentation for more info.
Here's a full example:
public static string GetRemoteRegistryValue(string MachineName, string username, string password)
{
string regValue = string.Empty;
ConnectionOptions opt = new ConnectionOptions();
opt.Impersonation = ImpersonationLevel.Impersonate;
opt.EnablePrivileges = true;
opt.Username = username;
opt.Password = password;
opt.Impersonation = ImpersonationLevel.Impersonate;
opt.EnablePrivileges = true;
try
{
ManagementPath p = new ManagementPath("\\\\" + MachineName + "\\root\\cimv2");
ManagementScope msc = new ManagementScope(p, opt);
msc.Connect();
string softwareRegLoc = "SOFTWARE\\VMware, Inc.\\VMware Drivers";
ManagementClass registry = new ManagementClass(msc, new ManagementPath("StdRegProv"), null);
ManagementBaseObject inParams = registry.GetMethodParameters("GetStringValue");
inParams["hDefKey"] = 0x80000002;//HKEY_LOCAL_MACHINE
inParams["sSubKeyName"] = softwareRegLoc;
inParams["sValueName"] = "VmciHostDevInst";
ManagementNamedValueCollection objCtx = new ManagementNamedValueCollection();
objCtx.Add("__ProviderArchitecture", 64);
objCtx.Add("__RequiredArchitecture", true);
InvokeMethodOptions options = new InvokeMethodOptions(objCtx, TimeSpan.MaxValue);
// Read Registry Key Names
ManagementBaseObject outParams = registry.InvokeMethod("GetStringValue", inParams, options);
if (outParams.Properties["sValue"].Value != null)
{
regValue = outParams.Properties["sValue"].Value.ToString();
}
}
catch (ManagementException Ex)
{
throw;
}
catch (System.UnauthorizedAccessException Ex)
{
throw;
}
catch (Exception Ex)
{
throw;
}
return regValue;
}
The code above returned the value of VmciHostDevInst while the app is targeting x86.

setup other computer network and configure the ip address programatically C#

I have some sample codes where I can change my own ip address.
Now i have a problem regarding changing the ip address of my networks.
When i mean networks (Computers that are connected to the lan)
I want to connect and configure their ip address as well.
Example
I have 2 computers and the ip addresses are 192.168.1.6 - Computer 1 and 192.168.1.7 - Computer 2. So now I am at computer 1 and I want to connect to 192.168.1.7 and change the ip address to 192.168.1.8
CODE
private void button1_Click_1(object sender, EventArgs e)
{
//example of ip 10.11.3.120
try
{
setIP();
setGateway();
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
setIP();
setGateway();
MessageBox.Show("Update Success");
}
}
private void setIP()
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
try
{
ManagementBaseObject setIP;
ManagementBaseObject newIP =
objMO.GetMethodParameters("EnableStatic");
//string ip_address = "10.11.3.120";
//string subnet_mask = "255.255.255.0";
newIP["IPAddress"] = new string[] { textBox1.Text };
newIP["SubnetMask"] = new string[] { textBox2.Text };
setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
public void setGateway()
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
try
{
ManagementBaseObject setGateway;
ManagementBaseObject newGateway =
objMO.GetMethodParameters("SetGateways");
newGateway["DefaultIPGateway"] = new string[] { textBox3.Text };
newGateway["GatewayCostMetric"] = new int[] { 1 };
setGateway = objMO.InvokeMethod("SetGateways", newGateway, null);
}
catch (Exception)
{
throw;
}
}
}
}
This is not a direct answer. However, you should have all the information you need here
Connecting to WMI Remotely with C#
In short you will need create a system ManagementScope
Note System.Management was the original .NET namespace used to access
WMI; however, the APIs in this namespace generally are slower and do
not scale as well relative to their more modern
Microsoft.Management.Infrastructure counterparts.
However
Create a ManagementScope object, using the name of the computer and the WMI path, and connect to your target with a call to ManagementScope.Connect().
If you connect to a remote computer in a different domain or using a different user name and password, then you must use a ConnectionOptions object in the call to the ManagementScope.
The ConnectionOptions contains properties for describing the
Authentication, Impersonation, username, password, and other
connection options.
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
// options takes more arguments, you need to read up on what you want
ManagementScope scope = new ManagementScope("\\\\FullComputerName\\root\\cimv2", options);
scope.Connect();
ManagementPath path = new ManagementPath("Win32_NetworkAdapterConfiguration");
ObjectGetOptions o = new ObjectGetOptions(null, System.TimeSpan.MaxValue, true);
ManagementClass objMC = new ManagementClass(scope, path, o);
...
Generally speaking, it is recommended that you set your Impersonation
level to Impersonate unless explicitly needed otherwise
Additional reading
Connecting to WMI Remotely with C#
ManagementScope Class
ConnectionOptions Class
ObjectGetOptions Class
ManagementPath Class
ManagementClass Class
Disclaimer : You will have to read about these topics and work out what you need in your situation.

WMI connection error C#

using System;
using System.Management;
public class Class1
{
public static void Main()
{
string strComputer = string.Format(#"machineName.domainname\root\cimv2");
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
options.Impersonation = ImpersonationLevel.Impersonate;
options.Authentication = AuthenticationLevel.Packet;
options.Authority = "ntlmdomain:InsTIL.com:InsTIL.com";
options.Username = "usr";
options.Password = "pwd";
ManagementScope oMs = new ManagementScope(strComputer, options);
SelectQuery query =new SelectQuery("Select * From Win32_Directory Where Name ='"+string.Format(#"C:\Scripts")+"'");
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs,query);
ManagementObjectCollection oReturnCollection = oSearcher.Get();
if (oReturnCollection.Count < 1)
{
Console.WriteLine("Folder does not exist");
}
else
{
Console.WriteLine("Folder does exist");
}
}
}
I'm trying to connect to remote machine and checking existence of folder.But I'm getting below mentioned error.
I tried and incorporated changes discussed in remote wmi connection c# - invalid parameter error
Program abruptly stops working and throws below error:
Unhandled Exception: System.Management.ManagementException: Invalid parameter
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStat
us errorCode)
at System.Management.ManagementPath.CreateWbemPath(String path)
at System.Management.ManagementPath..ctor(String path)
at Class1.Main()
You need backslashes before your machine name. Change this:
string strComputer = string.Format(#"machineName.domainname\root\cimv2");
to this:
string strComputer = string.Format(#"\\machineName.domainname\root\cimv2");

NTAccount.Translate Method fails with error Some or all identity references could not be translated

PipeAccessRule par = new PipeAccessRule("Everyone", PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
This code fails with error:
Some or all identity references could not be translated.
I guess this is because I'm using "Everyone" while launch my app on non-English local. On English system everything is OK.
How to avoid this? Is there some enum describes general user groups?
Stack trace:
at System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess)
at System.Security.Principal.NTAccount.Translate(Type targetType)
at System.Security.AccessControl.CommonObjectSecurity.ModifyAccess(AccessControlModification modification, AccessRule rule, Boolean& modified)
at System.Security.AccessControl.CommonObjectSecurity.AddAccessRule(AccessRule rule)
at System.IO.Pipes.PipeSecurity.AddAccessRule(PipeAccessRule rule)
Solved by using second constructor of PipeAccessRule and SecurityIdentifier instead of string:
System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.BuiltinUsersSid, null);
PipeAccessRule par = new PipeAccessRule(sid, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
For some reasons, BuiltinUsersSid doesn't seem to work properly in my case (remote servers can access to the pipe but local accesses to the pipe fail !)
Here is the code I used to give access to almost everything and now pipe can be accessed locally or remotely :
Please note that DomainSid parameter is in some cases populated with current user domain
using System.IO.Pipes;
using System.Security.Principal;
using System.Security.AccessControl;
[...]
PipeSecurity lPipeSecurity = new PipeSecurity();
try
{
PipeAccessRule lPar1 = new PipeAccessRule(#"NT AUTHORITY\NETWORK", PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar1);
}
catch (Exception E1)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give pipe rights to AUTORITY NT NETWORK"+E1.Message);
}
try
{
System.Security.Principal.SecurityIdentifier lSid = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.BuiltinUsersSid, null);
PipeAccessRule lPar2 = new PipeAccessRule(lSid, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar2);
}
catch (Exception E2)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give pipe rights to BuiltInSid "+E2.Message);
}
try
{
PipeAccessRule lPar3 = new PipeAccessRule(string.Format(#"{0}\{1}", Environment.UserDomainName, Environment.UserName), PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar3);
}
catch (Exception E3)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give pipe rights to current user "+E3.Message);
}
try
{
System.Security.Principal.SecurityIdentifier lSidWorld = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.WorldSid, null);
PipeAccessRule lPar4 = new PipeAccessRule(lSidWorld, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar4);
}
catch (Exception E4)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give rights to World "+E4.Message);
}
try
{
System.Security.Principal.SecurityIdentifier lSidLocal = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.LocalSid, null);
PipeAccessRule lPar5 = new PipeAccessRule(lSidLocal, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar5);
}
catch (Exception E5)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give rights to Local "+E5.Message);
}
try
{
PipeAccessRule lPar6 = new PipeAccessRule(#"geneos", PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar6);
}
catch (Exception E6)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give pipe rights to geneos" + E6.Message);
}
try
{
WindowsIdentity lCurrentId = WindowsIdentity.GetCurrent();
System.Security.Principal.SecurityIdentifier lSidLocal = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.AccountAdministratorSid, lCurrentId.User.AccountDomainSid);
PipeAccessRule lPar5 = new PipeAccessRule(lSidLocal, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar5);
}
catch (Exception E7)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give rights to administrators " + E7.Message);
}
try
{
System.Security.Principal.SecurityIdentifier lSidLocal = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.AuthenticatedUserSid, null);
PipeAccessRule lPar8 = new PipeAccessRule(lSidLocal, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar8);
}
catch (Exception E8)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give rights to authenticated users " + E8.Message);
}
try
{
WindowsIdentity lCurrentId = WindowsIdentity.GetCurrent();
System.Security.Principal.SecurityIdentifier lSidLocal = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.AuthenticatedUserSid, lCurrentId.User.AccountDomainSid);
PipeAccessRule lPar9 = new PipeAccessRule(lSidLocal, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
lPipeSecurity.AddAccessRule(lPar9);
}
catch (Exception E9)
{
Console.WriteLine(PrinterBase.DumpTimestamp(DateTime.UtcNow, true) + ": Exception when trying to give rights to authenticated users on current user domain " + E9.Message);
}
lPipeServer = new NamedPipeServerStream(
lNamedPipe,
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous,
0,
0,
lPipeSecurity);

C# WMI privileges

I have searched through numerous questions about how to convert VBS to C# and all that good stuff.
The issue that I'm having is that with the VBS code (see below) when the process is executed on the remote machine it's run with the SYSTEM account.
When I execute with C# it's run with my credentials (or whomever runs the C# program).
The VBS seems to be more reliable in getting remote installs to go through which is what i need it for.
I wanted to switch to C# so I could make a more user friendly GUI for the program.
Anyone know how to get C# to run WMI with the SYSTEM account?
VBS Code:
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objScheduledJob = objWMIService.Get("Win32_ScheduledJob")
Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")
'add the scheduled job to be run
objSWbemDateTime.SetVarDate(DateAdd(INTERVAL, MINUTES, Now()))
errReturn = objScheduledJob.Create(strCommand, objSWbemDateTime.Value, False, 0, 0, True, intJobID)
C# code:
static public int RemoteAdmin(string remoteMachine, string runFile)
{
try
{
ManagementPath run = new ManagementPath(#"\\" + remoteMachine + #"\root\cimv2:Win32_process");
ManagementClass man = new ManagementClass(run);
man.InvokeMethod("Create", new Object[] { runFile });
return 0;
}
catch
{
MessageBox.Show("Error in remote execution");
return 1;
}
}
You need to setup the ConnectionOptions
ConnectionOptions wmiConnOpts = new ConnectionOptions();
wmiConnOpts.Impersonation = ImpersonationLevel.Impersonate;
wmiConnOpts.Authentication = System.Management.AuthenticationLevel.Default;
wmiConnOpts.EnablePrivileges = true;
ManagementScope wmiLoc =
new ManagementScope(String.Format(#"\\{0}\root\cimv2", remoteMachine ),
wmiConnOpts);
ManagementPath wmiProcPath = new ManagementPath("Win32_ScheduledJob");
ManagementClass wmiProc = new ManagementClass(wmiLoc, wmiProcPath, null);
wmiProc.InvokeMethod("Create", new Object[] { runFile });
This is probably idiot error on my part but the error I was getting was because I didn't specify a time (UTC format) for it to start the scheduled job
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.Authentication = AuthenticationLevel.PacketPrivacy;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\" + remoteMachine + #"\ROOT\CIMV2"), connOptions);
manScope.Connect();
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ManagementPath managementPath = new ManagementPath("Win32_ScheduledJob");
ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions);
ManagementBaseObject inParams = processClass.GetMethodParameters("Create");
inParams["Command"] = runFile;
string StartTime = DateTimetoUTC(DateTime.Now.AddMinutes(1));
inParams["StartTime"] = StartTime;
ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null);

Categories