在 C# 中获取此 Powershell 输出的正确方法是什么
Whats the correct way to get output for this Powershell in C#
我在下面没有收到任何错误,但我也没有收到输出。下面是 Powershell cmd 和调用它的 C# 方法。我想知道它是否写得正确以及如何获得来自 powershell 的输出。当我从 PowerShell 运行 window
时它工作正常
Pwsh 命令:
public class GetRowAndPartitionKeys : Cmdlet
{
[Parameter(Mandatory = false)]
public List<string> Properties { get; set; } = new List<string>();
}
[Cmdlet( VerbsCommon.Get, "RowAndPartitionKeys" )]
public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKeys
{
protected override void ProcessRecord()
{
WriteObject ("Hi");
}
}
}
C# 方法:
public async Task<IEnumerable<object>> RunScript( )
{
// create a new hosted PowerShell instance using the default runspace.
// wrap in a using statement to ensure resources are cleaned up.
string scriptContents = "Import-Module 'C:\Users\...\Powershell.dll";
using( PowerShell ps = PowerShell.Create() )
{
// specify the script code to run.
ps.AddScript( scriptContents ).AddCommand( "Get-RowAndPartitionKeys" );
// execute the script and await the result.
var pipelineObjects = await ps.InvokeAsync().ConfigureAwait( false );
foreach( var item in pipelineObjects )
{
Console.WriteLine( item.BaseObject.ToString() );
}
return pipelineObjects;
}
与 answer to your previous question 类似,以下 自包含的示例代码演示了该方法在 原则上 后有效更正代码中的以下问题:
在 .AddScript()
和 .AddCommand()
调用之间缺少一个 .AddStatement()
调用;这对于(基于脚本块的)Import-Module
调用和 Get-RowAndPartitionKeys
调用被视为 单独的语句 .
是必要的
伪代码行 string scriptContents = "Import-Module 'C:\Users\...\Powershell.dll";
缺少结束符 '
(可能只是在此处发布的人工制品)。
另外,下面添加故障排除代码。
虽然编排代码在 PowerShell 中,实际 C# 项目,通过 .NET SDK are used, in combination with version 7.1.2
of the PowerShell (Core) SDK package, Microsoft.PowerShell.SDK
.
编译
在运行创建和运行测试项目的代码之后,您可以自己检查和试验它们(./module
是项目定义 Get-RowAndPartitionKeys
cmdlet 的模块 DLL,./app
是调用它的应用程序的项目):
$tmpDir = (New-Item -Force -Type Directory (Join-Path temp: $PID)).FullName
$tmpModuleDir = (New-Item -Force -Type Directory (Join-Path $tmpDir module)).FullName
$tmpAppDir = (New-Item -Force -Type Directory (Join-Path $tmpDir app)).FullName
$tmpPublishDir = (New-Item -Force -Type Directory (Join-Path $tmpDir publish)).FullName
$tmpModuleDll = Join-Path $tmpPublishDir module.dll
Push-Location
# ---
Write-Verbose -vb "Creating module DLL with sample cmdlet..."
Set-Location $tmpModuleDir
dotnet new classlib --force >$null || $(exit $LASTEXITCODE)
dotnet add package Microsoft.PowerShell.SDK >$null || $(exit $LASTEXITCODE)
@'
using System;
using System.Collections.Generic;
using System.Management.Automation;
namespace demo {
public class GetRowAndPartitionKeys : Cmdlet
{
public List<string> Properties { get; set; }
}
[Cmdlet( VerbsCommon.Get, "RowAndPartitionKeys" )]
public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKeys
{
protected override void ProcessRecord()
{
WriteObject ("Hi");
}
}
}
'@ | Set-Content Class1.cs
dotnet publish -o $tmpPublishDir >$null || $(exit $LASTEXITCODE)
# ---
Write-Verbose -vb "Creating console application that imports the module DLL and calls the sample cmdlet..."
Set-Location $tmpAppDir
dotnet new console --force >$null || $(exit $LASTEXITCODE)
dotnet add package Microsoft.PowerShell.SDK >$null || $(exit $LASTEXITCODE)
@"
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Threading.Tasks;
namespace demo {
public static class App {
static void Main(string[] args)
{
var unused = new Foo().RunScript().Result;
}
}
public class Foo {
public async Task<IEnumerable<object>> RunScript()
{
string scriptContents = @"Import-Module -Verbose ""$tmpModuleDll""";
using(PowerShell ps = PowerShell.Create())
{
ps.AddScript(scriptContents).AddStatement().AddCommand("Get-RowAndPartitionKeys");
var pipelineObjects = await ps.InvokeAsync().ConfigureAwait( false );
// --- TROUBLESHOOTING CODE
// Print verbose output from the Import-Module call
foreach (var v in ps.Streams.Verbose) { Console.WriteLine("VERBOSE: " + v.ToString()); }
// Print any errors.
foreach (var e in ps.Streams.Error) { Console.WriteLine("ERROR: " + e.ToString()); }
// ---
foreach (var item in pipelineObjects)
{
Console.WriteLine(item.BaseObject.ToString());
}
return pipelineObjects;
}
}
}
}
"@ | Set-Content Program.cs
# ---
Write-Verbose -vb "Compiling and invoking the console application..."
dotnet run
Pop-Location
Write-Verbose -vb @"
The test projects are located in $tmpDir.
To clean up, run:
Remove-Item "$tmpdir" -Recurse
"@
在我的 Windows 10 机器上(运行 来自 PowerShell 7.1.2),我得到:
如您所见:
- 详细输出确认 cmdlet 已正确导入
Hi
表明已成功调用 cmdlet。
我在下面没有收到任何错误,但我也没有收到输出。下面是 Powershell cmd 和调用它的 C# 方法。我想知道它是否写得正确以及如何获得来自 powershell 的输出。当我从 PowerShell 运行 window
时它工作正常Pwsh 命令:
public class GetRowAndPartitionKeys : Cmdlet
{
[Parameter(Mandatory = false)]
public List<string> Properties { get; set; } = new List<string>();
}
[Cmdlet( VerbsCommon.Get, "RowAndPartitionKeys" )]
public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKeys
{
protected override void ProcessRecord()
{
WriteObject ("Hi");
}
}
}
C# 方法:
public async Task<IEnumerable<object>> RunScript( )
{
// create a new hosted PowerShell instance using the default runspace.
// wrap in a using statement to ensure resources are cleaned up.
string scriptContents = "Import-Module 'C:\Users\...\Powershell.dll";
using( PowerShell ps = PowerShell.Create() )
{
// specify the script code to run.
ps.AddScript( scriptContents ).AddCommand( "Get-RowAndPartitionKeys" );
// execute the script and await the result.
var pipelineObjects = await ps.InvokeAsync().ConfigureAwait( false );
foreach( var item in pipelineObjects )
{
Console.WriteLine( item.BaseObject.ToString() );
}
return pipelineObjects;
}
与 answer to your previous question 类似,以下 自包含的示例代码演示了该方法在 原则上 后有效更正代码中的以下问题:
在
是必要的.AddScript()
和.AddCommand()
调用之间缺少一个.AddStatement()
调用;这对于(基于脚本块的)Import-Module
调用和Get-RowAndPartitionKeys
调用被视为 单独的语句 .伪代码行
string scriptContents = "Import-Module 'C:\Users\...\Powershell.dll";
缺少结束符'
(可能只是在此处发布的人工制品)。另外,下面添加故障排除代码。
虽然编排代码在 PowerShell 中,实际 C# 项目,通过 .NET SDK are used, in combination with version 7.1.2
of the PowerShell (Core) SDK package, Microsoft.PowerShell.SDK
.
在运行创建和运行测试项目的代码之后,您可以自己检查和试验它们(./module
是项目定义 Get-RowAndPartitionKeys
cmdlet 的模块 DLL,./app
是调用它的应用程序的项目):
$tmpDir = (New-Item -Force -Type Directory (Join-Path temp: $PID)).FullName
$tmpModuleDir = (New-Item -Force -Type Directory (Join-Path $tmpDir module)).FullName
$tmpAppDir = (New-Item -Force -Type Directory (Join-Path $tmpDir app)).FullName
$tmpPublishDir = (New-Item -Force -Type Directory (Join-Path $tmpDir publish)).FullName
$tmpModuleDll = Join-Path $tmpPublishDir module.dll
Push-Location
# ---
Write-Verbose -vb "Creating module DLL with sample cmdlet..."
Set-Location $tmpModuleDir
dotnet new classlib --force >$null || $(exit $LASTEXITCODE)
dotnet add package Microsoft.PowerShell.SDK >$null || $(exit $LASTEXITCODE)
@'
using System;
using System.Collections.Generic;
using System.Management.Automation;
namespace demo {
public class GetRowAndPartitionKeys : Cmdlet
{
public List<string> Properties { get; set; }
}
[Cmdlet( VerbsCommon.Get, "RowAndPartitionKeys" )]
public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKeys
{
protected override void ProcessRecord()
{
WriteObject ("Hi");
}
}
}
'@ | Set-Content Class1.cs
dotnet publish -o $tmpPublishDir >$null || $(exit $LASTEXITCODE)
# ---
Write-Verbose -vb "Creating console application that imports the module DLL and calls the sample cmdlet..."
Set-Location $tmpAppDir
dotnet new console --force >$null || $(exit $LASTEXITCODE)
dotnet add package Microsoft.PowerShell.SDK >$null || $(exit $LASTEXITCODE)
@"
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Threading.Tasks;
namespace demo {
public static class App {
static void Main(string[] args)
{
var unused = new Foo().RunScript().Result;
}
}
public class Foo {
public async Task<IEnumerable<object>> RunScript()
{
string scriptContents = @"Import-Module -Verbose ""$tmpModuleDll""";
using(PowerShell ps = PowerShell.Create())
{
ps.AddScript(scriptContents).AddStatement().AddCommand("Get-RowAndPartitionKeys");
var pipelineObjects = await ps.InvokeAsync().ConfigureAwait( false );
// --- TROUBLESHOOTING CODE
// Print verbose output from the Import-Module call
foreach (var v in ps.Streams.Verbose) { Console.WriteLine("VERBOSE: " + v.ToString()); }
// Print any errors.
foreach (var e in ps.Streams.Error) { Console.WriteLine("ERROR: " + e.ToString()); }
// ---
foreach (var item in pipelineObjects)
{
Console.WriteLine(item.BaseObject.ToString());
}
return pipelineObjects;
}
}
}
}
"@ | Set-Content Program.cs
# ---
Write-Verbose -vb "Compiling and invoking the console application..."
dotnet run
Pop-Location
Write-Verbose -vb @"
The test projects are located in $tmpDir.
To clean up, run:
Remove-Item "$tmpdir" -Recurse
"@
在我的 Windows 10 机器上(运行 来自 PowerShell 7.1.2),我得到:
如您所见:
- 详细输出确认 cmdlet 已正确导入
Hi
表明已成功调用 cmdlet。