I want to run a command in command prompt on a remote computer using C#. Per this link How to execute a command in a remote computer?, I am trying to do this using the following code:
public static void RunRemoteCommand(string command, string RemoteMachineName)
{
ManagementScope WMIscope = new ManagementScope(
String.Format("\\\\{0}\\root\\cimv2", RemoteMachineName));
WMIscope.Connect();
ManagementClass WMIprocess = new ManagementClass(
WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
object[] process = { command };
object result = WMIprocess.InvokeMethod("Create", process);
Log.Comment("Creation of process returned: " + result);
}
This returns an exit code of 0 and no errors are thrown, yet nothing is executed. Please help.
Hope this will help
http://www.petri.co.il/command-line-wmi-part-2.htm
Have a look into "Alternate Credentials" section. i believe you are able to do the little modification yourself.
If you are willing to try it out, psexec is great for this sort of thing.
I know the post is old but for others who come across this page and also completeness:
RRUZ's comment is correct , but there is also one more thing you might need in order to run on the remote machine, credentials.
To do that you need to add connection options:
public static void RunRemoteCommand(string command, string RemoteMachineName,
string username,string password)
{
var connection = new ConnectionOptions();
connection.Username = username;
connection.Password = password;
ManagementScope WMIscope = new ManagementScope(
String.Format("\\\\{0}\\root\\cimv2", RemoteMachineName), connection);
WMIscope.Connect();
ManagementClass WMIprocess = new ManagementClass(
WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
object[] process = { command };
object result = WMIprocess.InvokeMethod("Create", process);
Log.Comment("Creation of process returned: " + result);
}
Related
I am using the below code to change the service start in a remote server up type to manual/automatic using C#.
public static void ChangeServiceStartupType()
{
string query1 = "select * from Win32_Service where name = 'myservice' ";
string server = "servername";
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = #"username";
connectoptions.Password = "password";
ManagementScope scope = new ManagementScope(#"\\" + server + #"\root\cimv2");
scope.Options = connectoptions;
scope.Connect();
ObjectQuery query = new ObjectQuery(query1);
ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get();
foreach (ManagementObject mo in managementObjectSearcher.Get())
{
string name = mo.Properties["Name"].Value.ToString().Trim().ToLower();
string state = mo.Properties["State"].Value.ToString().Trim();
string startmode = mo.Properties["StartMode"].Value.ToString().Trim();
changemode(mo, "Automatic");
}
}
Here is the changemode method
private static void changemode(ManagementObject mo, string startmode)
{
ManagementBaseObject inParams = mo.GetMethodParameters("ChangeStartMode");
inParams["startmode"] = startmode;
ManagementBaseObject outParams = mo.InvokeMethod("ChangeStartMode", inParams, null);
startmode = mo.Properties["StartMode"].Value.ToString().Trim();
}
When I pass the parameters Manual or Automatic in the changemode(object,startmode parameter) the service start up type changes from automatic to manual and vice-versa. However, I am unable to change it to Automatic(Delayed Start).
I tried Auto-Delayed , Delayed-Auto, Automatic (Delayed Start) How do I achieve this?
If there's a way through ManagementObject than I haven't found it, but it IS possible through the registry:
public void SetDalayedAutoStart(string machineName, string serviceName)
{
using (var regKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machineName))
{
using (RegistryKey serviceKey = regKey.OpenSubKey(#"System\CurrentControlSet\Services\" + serviceName, true))
{
serviceKey.SetValue("DelayedAutostart", 1, RegistryValueKind.DWord);
}
}
}
Note 1: This is only relevant for services with the Automatic start type
Note 2: The new state will be visible in the Services control (services.msc) only after a restart (don't ask me why)
Looking at the documentation, it doesn't seem to be possible to make the service start with a delay using the ChangeStartMode Win32 method. Doing what you want is fairly straightforward if you use ServiceInstaller, like so:
myServiceInstaller.StartType = ServiceStartMode.Automatic;
myServiceInstaller.DelayedAutoStart = true;
However I'm guessing that isn't an option, so we will have to dig deeper.
The Service class does have a DelayedAutoStart property, but it is read only. If you want to set it to delayed, you're going to have to mess around with P/Invokes. All information I could find points to ChangeServiceConfig2 and this struct.
Alternatively, you can just execute this command it it will have the same effect. However, it isn't really an answer to your question, just a workaround.
sc.exe config myService start= delayed-auto
Finally, check out this (very) long answer by user Kramii, and this by Peter Kelly. Both of them wrote helper classes to make doing this sort of thing a lot easier. I haven't tested them but they look promising.
Sty's answer lets you set a service to automatic delayed at the time of creation; not post deployment.
There is a command line that can do that
sc \\computername config *servicename* start= delayed-auto
I ran this command line in the remote server using WMI Management Class and it works fine.
More documentation on how to remote start a process here
I am using C# with SSH.NET.
I want to issue a PWD command but could not find any documentation or help. I do not know how to use 'SshClient' class.
Update:
I also tried experimenting with SshClient class using the below code but it does nothing, neither any error nor any exception.
ConnectionInfo ConnNfo = new ConnectionInfo("FTPHost", 22, "FTPUser",
new AuthenticationMethod[]{
// Pasword based Authentication
new PasswordAuthenticationMethod("FTPUser","FTPPass")
}
);
using (var ssh = new SshClient(ConnNfo))
{
ssh.Connect();
if (ssh.IsConnected)
{
string comm = "pwd";
using (var cmd = ssh.CreateCommand(comm))
{
var returned = cmd.Execute();
var output = cmd.Result;
var err = cmd.Error;
var stat = cmd.ExitStatus;
}
}
ssh.Disconnect();
}
Nothing happens. Neither an error nor an exception. On Visual Studio console, i get the below output.
*SshNet.Logging Verbose: 1 : SendMessage to server 'ChannelRequestMessage': 'SSH_MSG_CHANNEL_REQUEST : #152199'.
SshNet.Logging Verbose: 1 : ReceiveMessage from server:
'ChannelFailureMessage': 'SSH_MSG_CHANNEL_FAILURE : #0'.*
At ssh.RunCommand method call the program goes in some sleep state (or waits for around 1 minute). sshCommand.Result and sshCommand.Error variables are empty.
Here's a quick example - one way to do it.
string host = "myhost";
string user = "root";
string pwd = "#secret#!"; // Don't use hardcoded plain-text passwords if possible - for demonstration only.
using (PasswordAuthenticationMethod auth = new PasswordAuthenticationMethod(user, pwd))
{
ConnectionInfo connection = new ConnectionInfo(host, user, auth);
using (var ssh = new SshClient(connection))
{
ssh.Connect();
SshCommand sshCommand = ssh.RunCommand("pwd");
Console.WriteLine("Command execution result: {0}", sshCommand.Result);
}
}
Note that if you specify an invalid command (e.g. "pwdxxxx"), you won't get an exception, but an error that will be stored in the SshCommand.Error string.
Note also that this uses SSH PasswordAuthentication, which may not be enabled in your SSH config.
Try looking into the documentation of SSH.NET:
SSH.NET at CodePlex
Code sample for executing a command (recommended)
Help file.CHM
I'm trying to launch a process using impersonation with WMI and C#.
Here's what I have so far:
var coptions = new ConnectionOptions();
coptions.Username = String.Format(#"{0}\{1}", machine.Domain, machine.Username);
coptions.Password = machine.Password;
coptions.Impersonation = ImpersonationLevel.Impersonate;
coptions.EnablePrivileges = true;
var mScope = new ManagementScope(String.Format(#"\\{0}\root\cimv2", machine.Address), coptions);
var mClass = new ManagementClass(mScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
object[] generatorProcess = { #"C:\test\test1.exe" };
mClass.InvokeMethod("Create", generatorProcess);
Exception:
E_ACCESSDENIED at mClass.InvokeMethod
How can I do it?
PS: The user I'm launching the process with does not have admin privileges, is it required?
EDIT: It works with an admin, looks like it's the user..
I've followed this guide here to try and give permissions without sucess.
https://support.infosim.net/demo/wmi/wmi.html
Help please
Basically, you can't do it with an account that has limited permissions. You can tweak the permissions on the WMI object to read but not to write it does not work at all.
I have to create an executable which checks if a certain process is running for a certain user (a service account) on a remote machine, the input parameters are 3 strings, machine name, user name and process name.
I have the idea to do this using either System.Diagnostics or WMI, just wanted to double check if anybody has another idea like powershell or even a window functionality which could make the task even easier.
since we want to make sure that process is always running on a dedicated server we will configure a scheduled task to execute a small console application which does this check. Not sure if coding it in C# is the best option or am I ignoring a builtin feature of windows server? Thanks!
I'm pretty sure you can accomplish this with tasklist cmd: tasklist /S \\<server> /V > tasklist.txt. this will give you a file you can grep through.
namespace not referenced
using System.Management;
I have ended up by implementing following solution in C#
this retrieves the username without domain name of the user running processName on machineName
public static string GetProcessOwner()
{
try
{
var resultUserName = string.Empty;
ConnectionOptions opt = new ConnectionOptions();
string path = string.Format(#"\\{0}\root\cimv2", machineName);
ManagementScope scope = new ManagementScope(path, opt);
scope.Connect();
var query = new ObjectQuery(string.Format("Select * From Win32_Process Where Name = '{0}'", processName));
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
var processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
//return argList[1] + "\\" + argList[0];
resultUserName = argList[0];
}
}
return resultUserName;
}
catch (Exception exc)
{
Debug.WriteLine(exc.Message);
return string.Empty;
}
}
GetOwner can return empty array for remote comp, so it may not work
i want to create a wrapper class for specific WMI functions that affect Bitlocker functionality. The first step is to get all the Bitlocker volumes of a machine so I created a Console Application and did this:
private static ManagementClass management;
private static ManagementObjectCollection Volumes = null;
static void Main(string[] args)
{
ManagementPath path = new ManagementPath();
path.Server = "";
path.NamespacePath = "\\ROOT\\CIMV2\\Security\\MicrosoftVolumeEncryption";
path.ClassName = "Win32_EncryptableVolume";
ConnectionOptions options = new ConnectionOptions();
options.Authentication = AuthenticationLevel.PacketPrivacy;
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(path, options);
ObjectGetOptions getOptions = new ObjectGetOptions();
management = new ManagementClass(scope, path, getOptions);
management.Get();
Volumes = management.GetInstances();
}
When I run this on a non-Bitlocker machine the Volumes Collection gets initialized OK, only that it has a Count of 0 of course. Now I copied the code over to a WinForms App and when I click a button to run this code it steps through OK but when I try to expand the collection during debugging the App hangs and I get a "Function evaluation timed out". It's the same code just in another Application. What could be the reason for this?
Hm. I got a null reference exception if I didn't run it as administrator, but when I ran it as administrator (Win 7 x64, btw), I got four Volumes back.
I just had a similar issue, I will post my code for you hopefully it helps.
ManagementObjectSearcher Encryption = new ManagementObjectSearcher(#"root\cimv2\Security\MicrosoftVolumeEncryption", "SELECT * FROM Win32_EncryptableVolume");
foreach (ManagementObject QueryObj in Encryption.Get())
{
string EncryptionStatus = QueryObj.GetPropertyValue("ProtectionStatus").ToString();
if (EncryptionStatus == "0")
{
EncryptionDialog.Text = "Unencrypted";
}
else if (EncryptionStatus == "1")
{
EncryptionDialog.Text = "Encrypted - SysPrep will not complete";
}
else if (EncryptionStatus == "2")
{
EncryptionDialog.Text = "Cannot Determine Encryption";
}
}
I'm using this to display the status for a sysprep tool i'm creating so the "EncryptionDialog.Text = ..." can be replaced with any other calls you may need. you also need to remember "which caused me issues at least" if you are using visual studio you will need to add a file to your project labeled "Application Manifest File" in the "Add New File" Dialog. The reason for this is that the application will need to be opened in Administrator mode(Just an FYI in case you haven't made it that far)