Каков правильный способ получить вывод для этой Powershell на С #
Я не получаю никаких сообщений об ошибках ниже, но я также не получаю вывод. Ниже приведены cmd Powershell и вызывающий его метод C#. Я хотел бы знать, правильно ли он написан и как я могу получить результат, исходящий от powershell. Он отлично работает, когда я запускаю из окна PowerShell
Pwsh cmd:
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;
}
1 ответ
Подобно ответу на ваш предыдущий вопрос , следующий автономный пример кода демонстрирует, что подход работает в принципе после исправления следующих проблем в вашем коде:
An
.AddStatement()
звонок отсутствует между.AddScript()
и.AddCommand()
вызов; это необходимо для (сценария блочного)Import-Module
call и call должны рассматриваться как отдельные утверждения .Строка псевдокода
string scriptContents = "Import-Module 'C:\Users\...\Powershell.dll";
отсутствует закрытие'
(возможно, просто артефакт публикации здесь).Кроме того, ниже добавлен код устранения неполадок.
Хотя код оркестрации находится в PowerShell, используются реальные проекты C #, скомпилированные с помощью .NET SDK , в сочетании с версией
7.1.2
из (ядра) пакета SDK PowerShell,
<tcode id="1472893"></tcode>.
После запуска кода, который создает и запускает тестовые проекты, вы можете самостоятельно проверить их и поэкспериментировать (
./module
это проект для модуля DLL, который определяет
Get-RowAndPartitionKeys
командлет,
./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) я получаю:
Как вы видете:
- подробный вывод подтверждает, что командлет был правильно импортирован
- то
Hi
показывает, что командлет был успешно вызван.