I am trying to connect to a remote powershell file from a C # .NET WinForms application. My goal is to create my own version of Microsoft PowerShell ISE. Therefore, I need a way to execute PowerShell scripts from my application on remote computers. I created a couple of methods and tested them on the local machine from my application. If I do not use WSManConnectionInfo and use using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()) , I can execute scripts locally, as if it were true powershell (small scripts, using variables, output using ft , fl , do a lot other things that I usually do with PowerShell. The problem starts when I add WSManConnectionInfo and point it to my Exchange server instead of using a local connection. It seems to be able to do basic things like get-mailbox, but as soon as I'm trying to transfer data using use some of the scripting features, for example, variables that it breaks, saying that they are not supported.
Similarly, I need to disable powershell.AddCommand ("out-string"); if it is not used locally.
An unhandled exception of type "System.Management.Automation.RemoteException" occurred in System.Management.Automation.dll.
Additional information: the term "Out-String" is not recognized as the name of a cmdlet, function, script file or executable program. Check the spelling of the name or if the path was included, check the path and try again.
The error itself does not appear if I cannot forcibly delete the connection, but just do it locally. SchemaUri seems to make it very strict to execute only the basic commands. I saw other examples in which people using very direct information, such as:
powershell.AddCommand("Get-Users"); powershell.AddParameter("ResultSize", count);
But with this approach, I would need to identify many possible options, and I do not want to go through the defining parameters and other things. I just wanted to load the "script" and execute it the same way as in the PowerShell window. Here is an example of what I am using now.
public static WSManConnectionInfo PowerShellConnectionInformation(string serverUrl, PSCredential psCredentials) { var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", psCredentials); //var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell", psCredentials); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic; connectionInfo.SkipCACheck = true; connectionInfo.SkipCNCheck = true; connectionInfo.SkipRevocationCheck = true; connectionInfo.MaximumConnectionRedirectionCount = 5; connectionInfo.OperationTimeout = 150000; return connectionInfo; } public static PSCredential SecurePassword(string login, string password) { SecureString ssLoginPassword = new SecureString(); foreach (char x in password) { ssLoginPassword.AppendChar(x); } return new PSCredential(login, ssLoginPassword); } public static string RunScriptPs(WSManConnectionInfo connectionInfo, string scriptText) { StringBuilder stringBuilder = new StringBuilder(); // Create a remote runspace using the connection information. //using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace()) using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo)) { // Establish the connection by calling the Open() method to open the runspace. // The OpenTimeout value set previously will be applied while establishing // the connection. Establishing a remote connection involves sending and // receiving some data, so the OperationTimeout will also play a role in this process. remoteRunspace.Open(); // Create a PowerShell object to run commands in the remote runspace. using (PowerShell powershell = PowerShell.Create()) { powershell.Runspace = remoteRunspace; powershell.AddScript(scriptText); //powershell.AddCommand("out-string"); powershell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); Collection<PSObject> results = powershell.Invoke(); foreach (PSObject result in results) { stringBuilder.AppendLine(result.ToString()); } } // Close the connection. Call the Close() method to close the remote // runspace. The Dispose() method (called by using primitive) will call // the Close() method if it is not already called. remoteRunspace.Close(); } // convert the script result into a single string return stringBuilder.ToString(); }
Any advice on why this is happening and the workaround is how to make it behave the same? I have seen many blogs, for example, but defining each simple command does not make sense to me. I also saw the possibility of creating a local connection and then making a remote connection inside this , but this should be a last resort, as it relies on several other factors.