running a command on a remote windows using winrm in C#

4.3k views Asked by At

I have a simple way to connect to a remote windows machine from a local windows machine using winrm. Here is the powershell code that is working:

Set-Item WSMan:\localhost\Client\TrustedHosts -Value $ip -Force
$securePassword = ConvertTo-SecureString -AsPlainText -Force 'mypass'
$cred = New-Object System.Management.Automation.PSCredential 'Administrator', $securePassword
$cmd = {ls C:\temp}
Invoke-Command -ComputerName $ip -Credential $cred -ScriptBlock $cmd

I want to figure out how to do the exact thing in c#.

Also, it would be additionally helpful if someone tell me whether there is a method to send files in c# winrm.

Note: the is only a c# code needed on my local machine. The remote machine is already setup.

2

There are 2 answers

0
max On

well, I figured out one way as I shall post below, but while it works fine on windows 8, it encounters the error "Strong name validation failed" on windows 7 so I should keep looking into this. Still please feel free to post other ideas.

--> add System.Management.Automation.dll to your project.

    WSManConnectionInfo connectionInfo = new WSManConnectionInfo();
    connectionInfo.ComputerName = host;
    SecureString securePwd = new SecureString();
    pass.ToCharArray().ToList().ForEach(p => securePwd.AppendChar(p));
    connectionInfo.Credential = new PSCredential(username, securePwd);
    Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo);
    runspace.Open();
    Collection<PSObject> results = null;
    using (PowerShell ps = PowerShell.Create())
    {
        ps.Runspace = runspace;
        ps.AddScript(cmd);
        results = ps.Invoke();
        // Do something with result ... 
    }
    runspace.Close();

    foreach (var result in results)
    {
        txtOutput.AppendText(result.ToString() + "\r\n");
    }
0
wlscaudill On

I've got an article that describes an easy way to run Powershell through WinRM from .NET at http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.

The code is in a single file if you want to just copy it and it's also a NuGet package that includes the reference to System.Management.Automation.

It auto manages trusted hosts, can run script blocks, and also send files (which isn't really supported but I created a work around). The returns are always the raw objects from Powershell.

// this is the entrypoint to interact with the system (interfaced for testing).
var machineManager = new MachineManager(
    "10.0.0.1",
    "Administrator",
    MachineManager.ConvertStringToSecureString("xxx"),
    true);

// will perform a user initiated reboot.
machineManager.Reboot();

// can run random script blocks WITH parameters.
var fileObjects = machineManager.RunScript(
    "{ param($path) ls $path }",
    new[] { @"C:\PathToList" });

// can transfer files to the remote server (over WinRM's protocol!).
var localFilePath = @"D:\Temp\BigFileLocal.nupkg";
var fileBytes = File.ReadAllBytes(localFilePath);
var remoteFilePath = @"D:\Temp\BigFileRemote.nupkg";
machineManager.SendFile(remoteFilePath, fileBytes);

Please mark as answer if this helps. I've been using this for a while with my automated deployments. Please leave comments if you find issues.