7

I tried running a script localwindows.ps1 from C# using the following Code :

PSCredential credential = new PSCredential(userName, securePassword);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(false, "machineName", 5985, "/wsman", shellUri, credential);
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
    runspace.Open();
    String file = "C:\\localwindows.ps1";
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript(file);
    pipeline.Commands.Add("Out-String");
    Collection<PSObject> results = pipeline.Invoke();
}

                  

But getting exception :'The term 'C:\localwindows.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program.

So I tried the following :

PSCredential credential = new PSCredential(userName, securePassword);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(false, "machineName", 5985, "/wsman", shellUri, credential);
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{

    runspace.Open();
 
    using (PowerShell powershell = PowerShell.Create())
    {
        powershell.Runspace = runspace;           
        
        PSCommand new1 = new PSCommand();
        String machinename = "machinename";
        String file = "C:\\localwindows.ps1";
        new1.AddCommand("Invoke-Command");
        new1.AddParameter("computername", machinename);
        new1.AddParameter("filepath", file);         
        

        powershell.Commands = new1;
        Console.WriteLine(powershell.Commands.ToString());
        Collection<PSObject> results = powershell.Invoke();
       
     }

I am getting the error : "Cannot find path 'C:\localwindows.ps1' because it does not exist."

But using command 'Invoke-Command -ComputerName "machineName" -filepath C:\localwindows.ps1' ,from powershell in local machine created a new account in the remote machine.

How to call the script localwindows.ps1 from C#? How to execute the command 'Invoke-Command -ComputerName "machineName" -filepath C:\localwindows.ps1' through C#?

The script localwindows.ps1 is

$comp = [adsi]“WinNT://machinename,computer”
$user = $comp.Create(“User”, "account3")
$user.SetPassword(“change,password.10")
$user.SetInfo()

2 Answers 2

4

Actually your invocation style should work. But in both of your examples, the script c:\localwindows.ps1 must reside on the local computer. In the Invoke-Command case, it will be copied from the local computer to the remote computer.

If, in the Invoke-Command case, the script already exists on the remote computer and you don't need to copy it over, remove the FilePath parameter and add this:

new1.AddParameter("Scriptblock", ScriptBlock.Create(file));
Sign up to request clarification or add additional context in comments.

7 Comments

I tried the case pipeline.Commands.AddScript(System.IO.File.ReadAllText(file));. I am getting the error : 'Unexpected token '�WinNT://machineName�' in expression or statement.' Whereas the same script creates a local user account using with invoke-command. I tried the solution - pipeline.Commands.AddScript(System.IO.File.ReadAllText(". " + file)); The program was not able to locate the file.
I tried - new1.AddParameter("Scriptblock", "{. " + file + "}"); I am getting the error - 'Cannot bind parameter 'ScriptBlock'. Cannot convert the "{ C:\localwindows.ps1}" value of type "System.String" to type "System.Management.Automation.ScriptBlock".'
See the updated answer. I believe the crux of your problem is that the script is not on your local computer at the c:\localwindows.ps1.
I used the command -'new1.AddParameter("Scriptblock", ScriptBlock.Create(file));'. I am still getting the following error - 'Cannot bind parameter 'ScriptBlock'. Cannot convert the "C:\localwindows.ps1" value of type "System.String" to type "System.Management.Automation.ScriptBlock".'
Using the command - pipeline.Commands.AddScript(System.IO.File.ReadAllText(file)); - it worked fine. The issue was with script. I used single quotes instead of double quotes and it worked.
|
0

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);

// for your specific issue I think this would be easier
var results = machineManager.RunScript(
    File.ReadAllText("C:\\LocalWindows.ps1"));

// 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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.