19 November, 2012
3 Comments
1 category
You van execute a process on an other machine from C#, by using the code below:
Example for calling the function
var rc = new RemotingComponent(null); rc.RunRemoteProcess ( @"MyMachine1", "MyMachine1\Administrator", "MyPassword1", @"C:\Windows\System32\notepad.exe", string.Empty );
C# class
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Security; using System.Text; namespace Research { public interface IRemotingComponent { void RunRemoteProcess(string machineName, string userName, string password, string processPath, string processArguments); } public class RemotingComponent : IRemotingComponent { public void RunRemoteProcess(string machineName, string userName, string password, string processPath, string processArguments) { var connectTo = new Uri(String.Format("http://{0}:5985/wsman", machineName)); _logger.Info("Building powershell command."); var command = new StringBuilder(); command.AppendLine("$pinfo = New-Object System.Diagnostics.ProcessStartInfo"); command.AppendLine(string.Format(@"$pinfo.FileName = ""{0}""", processPath)); command.AppendLine("$pinfo.UseShellExecute = $false"); command.AppendLine("$pinfo.RedirectStandardError = $true"); command.AppendLine("$pinfo.RedirectStandardOutput = $true"); command.AppendLine("$pinfo.CreateNoWindow = $true"); command.AppendLine(string.Format(@"$pinfo.WorkingDirectory = ""{0}""", new FileInfo(processPath).Directory.FullName)); command.AppendLine(string.Format(@"$pinfo.Arguments = ""{0}""", processArguments)); command.AppendLine("$p = New-Object System.Diagnostics.Process"); command.AppendLine("$p.StartInfo = $pinfo"); command.AppendLine("$p.Start() | Out-Null"); command.AppendLine("$output = $p.StandardOutput.ReadToEnd()"); command.AppendLine("$p.WaitForExit()"); command.AppendLine("$output"); string shell = @"http://schemas.microsoft.com/powershell/Microsoft.PowerShell"; using (var passing = new SecureString()) { foreach (char c in password.ToCharArray()) { passing.AppendChar(c); } passing.MakeReadOnly(); var credentials = new PSCredential(userName, passing); var connection = new WSManConnectionInfo(connectTo, shell, credentials); using (var runspace = RunspaceFactory.CreateRunspace(connection)) { runspace.Open(); using (var powershell = PowerShell.Create()) { powershell.Runspace = runspace; powershell.AddScript(command.ToString()); var results = powershell.Invoke(); runspace.Close(); foreach (var obj in results.Where(o => o != null)) { Console.Writeline(string.Format("Output: [{0}].", obj)); } } } } } } }
Tags: C#PowerShell
Category: Uncategorized
This seems to start a process, but not a visible application. Same way as the WMI solutions do. How to start a visible process?
I am using a ”Connect-MSolService” method with it’s credentials, but I have missed a runspace.Close(); line of code for a couple of minutes.
For a period of time it worked properly.
But now this command (I guess!), is trying to open a dialog on Server side.
Is this ”runspace.Close();” causing the problem?
Use TaskScheduler. Or, do what PSExec does:
Create a new service on the remote machine, allow the service to interact with the desktop, have the service get the user’s session token and Winsta, then either impersonate the logged on user (or use System) to run your remote program.