【问题标题】:Execute a Powershell Script with parameters in C#在 C# 中使用参数执行 Powershell 脚本
【发布时间】:2021-10-11 09:40:34
【问题描述】:

我被困在这个项目上,我正在尝试使用 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 个参数, 所以用户名、全名、密码和组[数组],导致脚本中的方法需要这些。

当我尝试从我的 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# 代码现在看起来像这样,必须添加 Runspace Invoke,导致 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() 中添加参数。当然,它甚至在它存在之前就没有运行,称为函数 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";
}

【问题讨论】:

  • File.ReadAllText 在这里完全不需要,PowerShell 可以自己从磁盘读取脚本:)

标签: c# visual-studio powershell cmdlet


【解决方案1】:

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

Command 对象在使用其单参数构造函数创建时,指的是命令名称或文件路径,而不是脚本文件的内容 ,这就是您试图通过 File.ReadAllText() 进行的操作。[1] 请注意,同样,相关的 .AddCommand() method,直接在 PowerShell 实例上可用,只需要名称或文件路径,而需要源代码文本的是不同的.AddScript() method[2]

因此,请尝试以下方法:

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

注意:


[1] 可以用脚本text构造一个Command实例,即一段源代码,即如果你通过@ 987654336@ 到第二个参数(有点混淆命名isScript);例如,new Command("'hi'", true)。但是,通过首先将脚本文件显式读入内存来这样做不仅在您的情况下是不必要的,而且还会改变代码行为的某些方面,特别是在自动 $PSScriptRoot$PSCommandPath 变量报告的内容方面。支持>

[2] 请注意,如果您碰巧将不包含空格的脚本文件路径传递给.AddScript(),调用也会成功,但脚本不会接收参数 em>,因为代码实际上被评估为
. { C:\Code\PathToScript\CreateUser.ps1 } ...... 表示参数) - 请参阅this answer 了解更多信息。

【讨论】:

    【解决方案2】:

    改为创建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();
    

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      • 2016-01-20
      相关资源
      最近更新 更多