【问题标题】:Calling Powershell from C# (ASP.NET) - pass custom object?从 C# (ASP.NET) 调用 Powershell - 传递自定义对象?
【发布时间】:2023-04-03 02:26:01
【问题描述】:

我在尝试从 C# 调用 Powershell 函数时遇到问题。具体来说,我在尝试将项目的通用列表传递给 powershell 模块函数时遇到了困难。代码如下:

var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand";
var allProjects = _pmRepository.GetAllProjects();
using (Runspace runSpace = RunspaceFactory.CreateRunspace())
{
    runSpace.Open();
    PowerShell posh = PowerShell.Create();
    posh.Runspace = runSpace;
    posh.AddScript(script);
    posh.AddArgument(allProjects);

    Collection<PSObject> results = posh.Invoke();
}

GetAllProjects() 方法返回 Project 的通用列表,并且 Project 是一个自定义类。我的模块函数签名如下所示:

function Get-MyCommand
{
    [CmdletBinding()]
    Param
    (
        [Parameter(ValueFromPipeline = $true)]
        [PSCustomObject[]] $Projects
    )
    Begin
    {}
    Process
    {
        $consumables = New-GenericList "Company.Project.Entities.Project"
        foreach($project in $projects)
        {
            if ($project.State -eq $ProjectStates.Development)
            {
                $consumables.Add($project)
            }
        }
    }
}

当我尝试迭代数组时出现此错误:

{“在此对象上找不到属性‘状态’。请确保它存在。”}

有可能做我想做的事吗?

编辑: 我使用了以下代码一段时间,但最终使用了此 Web 应用程序的后端 C# 代码。创建 powershell 会话的加载时间对于我们的情况来说太长了。希望这会有所帮助。

    private void LoadConsumableProjects()
    {
        var results = new Collection<PSObject>();
        InitialSessionState iss = InitialSessionState.CreateDefault();
        iss.ImportPSModule(_modules);

        using (Runspace runSpace = RunspaceFactory.CreateRunspace(iss))
        {
            runSpace.Open();
            using (var ps = PowerShell.Create())
            {
                ps.Runspace = runSpace;
                ps.AddScript("Get-LatestConsumableProjects $args[0]");
                ps.AddArgument(Repository.GetAllProjects().ToArray());

                results = ps.Invoke();
                if (ps.Streams.Error.Count > 0)
                {
                    var errors = "Errors";
                }
            }
        }

        _projects = new List<Project>();
        foreach (var psObj in results)
        {
            _projects.Add((Project)psObj.BaseObject);
        }
    }

【问题讨论】:

  • 在你的脚本中,你点源'Runspace.ps1',然后调用你的函数Get-MyCommand,没有参数你不会忘记$args?
  • 这个参数是在我构建 Runspace 和 Powershell 对象时传入的。 posh.AddArgument(allProjects);
  • 好的,但我在想你必须写这样的东西 var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand $args"; 将参数传递给你的函数Get-MyCommand
  • @Kiquenet 今天下午我会尽力为你挖掘出来。
  • @Kiquenet 我用我当时使用的解决方案更新了原始问题。我最终消耗了后端 C# 代码,因为创建 powershell 会话的时间损失对于我们的需求来说太大了。希望这会有所帮助。

标签: powershell powershell-2.0


【解决方案1】:

好的,我把它作为答案,因为我认为你可以测试它。据我了解您的代码,您将参数传递给您的脚本:

posh.AddArgument(allProjects);

但在您的脚本中,您不会使用此参数传递给您的函数。对我来说,你可以测试:

var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand $args[0]";

在您的脚本中,点 source 'Runspace.ps1',然后调用不带参数的函数 Get-MyCommand。 PowerShell 进入 foreach 循环, $project 等于 null。如果 $Projects 为空,只需发出哔声。

【讨论】:

  • 我明白你的意思了。我的印象是 AddArgument 方法将该参数传递给函数,而不是我要求它在运行空间中运行的脚本。我走得更远,但我没有收到此错误:Cannot process argument transformation on parameter 'Projects'. Cannot convert the "Company.Project.Entities.Project[]" value of type "Company.Project.Entities.Project[]" to type "Company.Project.Entities.Project".
  • 另外,powershell函数参数是这样定义的[Parameter(ValueFromPipeline = $true)] [Company.Project.Entities.Project[]] $Projects
  • 看起来_pmRepository.GetAllProjects() 只返回一个项目。你能不能只声明$Projects 不带类型并使用$Projects.gettype 来查看类型。
  • 我删除了函数参数的类型约束并添加了 $paramType = $Projects.GetType() 并重新运行,我又得到了这个:Property 'State' cannot be found on this object. Make sure that it exists.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 2012-11-21
  • 1970-01-01
相关资源
最近更新 更多