在 C# 中使用参数执行 Powershell 脚本

Execute a Powershell Script with parameters in C#

我坚持这个项目,我试图用 Powershell 脚本创建一个用户,但我想 运行 来自我的 Windowsform 的脚本。

脚本如下所示:

[CmdletBinding()]
 param (
[string] $Password
)  
[SecureString] $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force

CreateUser $Username $Fullname $securePassword $Groups

function CreateUser { 
Param([string] $Username, [string] $Fullname, [SecureString] $Password, [string[]] $Groups)

Process{   
New-localuser -name $Username -FullName $Fullname -password $Password | Out-Null

    Write-Host "User" $_.username "created!"
    
    AddUserToGroup($Username, $Groups)
}
}

function AddUserToGroup([string] $Username, [string[]] $Groups){
Write-Output "Hello World";
}

我知道代码可以工作,因为当我在 Powershell 中 运行 它然后它就可以工作了。

我需要在 C# 代码中添加 4 个参数, 所以用户名、全名、密码和组[array],因为脚本中的方法需要这些。

当我尝试从我的 C# 代码 运行 脚本时,我得到了错误:

The term "" is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

我的 C# 看起来像这样

        RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
        Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
        runspace.Open();

        RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
        string _pathToPSFile = File.ReadAllText(@"C:\Code\PathToScript\CreateUser.ps1");
        Pipeline pipeline = runspace.CreatePipeline();
        Command scriptCommand = new Command(_pathToPSFile);
        List<CommandParameter> commandParameters = new List<CommandParameter>();
        foreach (string scriptParameter in scriptParameters)
        {
            CommandParameter commandParm = new CommandParameter(null, scriptParameter);
            commandParameters.Add(commandParm);
            scriptCommand.Parameters.Add(commandParm);
        }
        pipeline.Commands.Add(scriptCommand);
        Collection<PSObject> psObjects;
        psObjects = pipeline.Invoke();

我不知道当我 运行 使用 c# 编写脚本并添加参数时会发生什么, 我必须调用 C# 代码中的函数,还是自动执行? 我是 Powershell 代码的初学者

这里真的需要帮助:)

如果您需要更多信息,或者有什么不清楚的地方,请告诉我:)

编辑#1 C# 代码现在看起来像这样,必须添加运行空间调用,导致 ExecutionPolicy 问题

        RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
        Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
        runspace.Open();

        RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
        scriptInvoker.Invoke("$ExecutionPolicy = Get-ExecutionPolicy -Scope CurrentUser");
        scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted -Scope CurrentUser ");

        PowerShell ps = PowerShell.Create();
        ps.Runspace = runspace;
        ps.AddCommand(@"C:\Code\Internal\as1UserManager\as1UserManager\PSScripts\CreateUser.ps1");

        foreach (string scriptParameter in scriptParameters)
        {
            ps.AddArgument(scriptParameter);
        }

        Collection<PSObject> psObjects = ps.Invoke();
        scriptInvoker.Invoke("Set-ExecutionPolicy -Scope CurrentUser $ExecutionPolicy -Force");

编辑#2 我必须按照建议在 CmdletBinding() 中添加参数。当然,它不是 运行ning,在它存在之前称为函数 CreateUser。 现在一切都很好。代码现在看起来像这样

[CmdletBinding()]
param (  
[string] $Username = "Leon",
[string] $Fullname = "Kennedy",
[string] $Password = "sml12345",
[string] $Groups = "something"
) 
[SecureString] $securePassword = ConvertTo-SecureString $Password              -AsPlainText -Force


function CreateUser {
Param([string] $Username, [string] $Fullname, [SecureString]    securePassword, [string] $Groups)

Process{   
New-localuser -name $Username -FullName $Fullname -password  $securePassword | Out-Null

    Write-Host "User" $Username "created!"
    
    AddUserToGroup($Username, $Groups)
   }
}

CreateUser $Username $Fullname $securePassword $Groups

function AddUserToGroup([string] $Username, [string] $Groups){
Write-Output "Hello World";
}

顺便说一句:您的脚本有问题:函数 CreateUser 在定义 之前被调用 ,但失败了。

A Command object, when created with its single-argument constructor, refers to a command name or file path, not to a script file's content, which is what you're attempting to via File.ReadAllText().[1] Note that, similarly, the related .AddCommand() method, directly available on a PowerShell instance, expects only a name or file path, whereas it is the distinct .AddScript() method 需要源代码 text.[2]

因此,请尝试以下操作:

Command scriptCommand = new Command(@"C:\Code\PathToScript\CreateUser.ps1");

注:

  • 您的代码可以大大简化,如 所示。

[1] 可以使用脚本 text 构造一个 Command 实例,即,一段源代码,即如果您将 true 传递给第二个参数(名称有点令人困惑 isScript);例如,new Command("'hi'", true)。但是,通过首先明确地将脚本文件读入内存来这样做不仅对您的情况没有必要,而且还会改变代码行为的某些方面,特别是关于自动 $PSScriptRoot and $PSCommandPath 变量报告的内容。

[2] 请注意,如果您恰好将不包含空格的脚本文件路径传递给 .AddScript(),调用也会成功,但脚本 不会收到参数,因为代码实际上被评估为
. { C:\Code\PathToScript\CreateUser.ps1 } ...... 表示参数)- 有关详细信息,请参阅

改为创建 the PowerShell class 的实例,它将允许您添加未命名的参数:

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();

PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddCommand(@"C:\Code\PathToScript\CreateUser.ps1");

foreach (string scriptParameter in scriptParameters)
{
    ps.AddArgument(scriptParameter);
}

Collection<PSObject> psObjects;
psObjects = pipeline.Invoke();