C# 从C运行PowerShell 6中的PowerShell脚本#
我有一个与REST服务器通信的PowerShell脚本。此脚本仅适用于PowerShell 6。 我想从C#调用它,因为C#程序需要来自REST服务器的信息,我不想在C#中重写REST代码 所以基本上,我想从C#运行一个PowerShell脚本但是,在C#中,C# 从C运行PowerShell 6中的PowerShell脚本#,c#,powershell,start-process,C#,Powershell,Start Process,我有一个与REST服务器通信的PowerShell脚本。此脚本仅适用于PowerShell 6。 我想从C#调用它,因为C#程序需要来自REST服务器的信息,我不想在C#中重写REST代码 所以基本上,我想从C#运行一个PowerShell脚本但是,在C#中,PowerShell.Create()创建一个使用PowerShell 5的PowerShell实例 我已经替换了默认文件夹中的pwsh.exe,删除了PowerShell 5 everywhere等。当我shift+右键单击anywher
PowerShell.Create()
创建一个使用PowerShell 5的PowerShell
实例我已经替换了默认文件夹中的pwsh.exe,删除了PowerShell 5 everywhere等。当我
shift+右键单击
anywhere使用“在此处运行PowerShell”时,我会看到一个PowerShell 6窗口。但出于某种原因,C#在使用PowerShell
类时坚持使用PowerShell 5
这是我要重用的PowerShell代码:
function Get-JSONWebToken {
param (
[Parameter(Mandatory=$True)][string] $BaseUri,
[Parameter(Mandatory=$True)][string] $ApiToken
)
if ($PSVersionTable.PSVersion.Major -lt 6) {
$version = $PSVersionTable.PSVersion
Throw "Your PowerShell version is: $version. Please upgrade to PowerShell 6 or above"
}
$uri = "$BaseUri/auth/token"
$bodyJson = ConvertTo-Json @{token = $ApiToken} -Compress
Write-Host "Authenticating ..."
try {
$response = Invoke-RestMethod `
-Uri $uri `
-Method Post `
-ContentType "application/json" `
-Body $bodyJson
$jwtToken = $response.token
$secureToken = ConvertTo-SecureString $jwtToken -AsPlainText -Force
return $secureToken
}
catch {
#handle error
}
}
所以现在我尝试手动调用PowerShell 6,先导入一个模块,然后再使用它。下面是我的三次尝试,它们都应该做相同的事情:调用获取JSONWebToken
(在rest api.psm1
中)并正确检索输出
C#version 1,使用PowerShell
类:
ps=PowerShell.Create();
//模块导入。。。
PSCommand cmd=ps.Commands.AddCommand(“Get-JSONWebToken”);
cmd.AddParameter(“baseUri”,baseUri);
cmd.AddParameter(“apiToken”,apiToken);
ps.Invoke();
由于某些原因,它始终在PowerShell 5上运行,因此无法使用
C#version 2,改用过程
Process ps6 = new Process();
ps6.StartInfo = new ProcessStartInfo {
FileName = "C:/Program Files/PowerShell/6/pwsh.exe",
Arguments = "-Command {\n" +
"Import-Module " + modulePath + ";\n" +
"Get-JSONWebToken " + apiToken + ";\n" +
"}",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false
};
ps6.Start()
这在PowerShell 6上运行,但只输出我传递的参数,而不输出Get JSONWebToken
C#version 3:从C从PS5调用PS6#
这根本不起作用:
Result: Usage: pwsh[.exe] [[-File] <filePath> [args]]
Result: [-Command { - | <script-block> [-args <arg-array>]
Result: | <string> [<CommandParameters>] } ]
Result: [-ConfigurationName <string>] [-CustomPipeName <string>]
...
...
Result:用法:pwsh[.exe][[-File][args]]
结果:[-Command{-|[-args]
结果:|[]}]
结果:[-ConfigurationName][-CustomPipeName]
...
...
PowerShell版本:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $Ps6Path
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.CreateNoWindow = $false
$pinfo.Arguments = "-Command {Import-Module <myPath>\rest-api.psm1; Get-JSONWebToken 123inputStringExample;}"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
$pinfo=新对象System.Diagnostics.ProcessStartInfo
$pinfo.FileName=$Ps6Path
$pinfo.RedirectStandardError=$true
$pinfo.RedirectStandardOutput=$true
$pinfo.CreateNoWindow=$false
$pinfo.Arguments=“-Command{Import Module\rest-api.psm1;Get JSONWebToken 123inputStringExample;}”
$p=新对象System.Diagnostics.Process
$p.StartInfo=$pinfo
$p.Start()|输出为空
$p.WaitForExit()
$stdout=$p.StandardOutput.ReadToEnd()
$stderr=$p.StandardError.ReadToEnd()
写入主机“stdout:$stdout”
写入主机“stderr:$stderr”
写入主机“退出代码:”+$p.ExitCode
这也只输出我在从C#或从PS6或PS5调用时传递的参数,这在技术上并不能解决问题,但我按照建议做了,并完全用C#重写了代码。这不是一个简单的问题,但最终它是一个很好的解决方案
如果您对如何正确解决这个问题有想法,请在这里发布,因为我仍然对如何从C#调用PowerShell 6上的东西感兴趣。用任何.NET语言重写PowerShell脚本都非常简单,因为PS1脚本可以直接调用.NET Framework代码。除此之外,试一试?@MindSwipe如何?参见第二段:“PowerShell.Create();创建一个使用PowerShell 5的PowerShell实例。”。关于重写:我正在使用
Invoke RestMethod
,但我在C#中还没有找到一个同样易于使用的挂件,因此我有兴趣调用PS脚本。我们是在看不同版本的页面还是完全不同的页面?Create方法文档声明:Create()构造一个空的PowerShell实例;在调用此实例之前必须添加脚本或命令能否将PowerShell脚本添加到问题中?通过谷歌搜索Invoke-rest方法,我发现它与通过HttpClient@MindSwipe所有这些代码段都是为了实现同一目标而进行的不同尝试,我编辑了我的问题,以澄清这一点。那么PowerShell构造函数呢?我发现在创建实例时没有(简单的)方法来指定PowerShell版本,如果这就是您引用文档的原因的话。
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $Ps6Path
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.CreateNoWindow = $false
$pinfo.Arguments = "-Command {Import-Module <myPath>\rest-api.psm1; Get-JSONWebToken 123inputStringExample;}"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode