c# - 如何在 C# 中获取 PSObject.Properties 的 ScriptProperty 值?

标签 c# powershell .net-core powershell-sdk

我正在尝试使用“GET-PSDrive”命令通过 PowerShell 6.0 获取服务器的驱动器信息。直接在 PowerShell 中运行命令,我在输出表中看到“已用”和“免费”的值,但在代码中运行相同的命令虽然使用 Microsoft.Powershell.Sdk,但“已用”和“免费”字段不是可用。

我看到 PSObject.Properties 数组下列出了这两个项目,但尝试访问我收到异常的值:

“没有运行空间可用于在该线程中运行脚本。您可以在 System.Management.Automation.Runspaces.Runspace 类型的 DefaultRunspace 属性中提供一个。您尝试调用的脚本 block 是:##”

以下是我正在使用的 POC 代码:

using (var psCon = PowerShell.Create())
{
     psCon.AddCommand("GET-PSDrive");
     var psReturn = psCon.Invoke();
     foreach (var psObj in psReturn)
     {
          var driveUsedValue = psObj.Properties["Used"].Value;
     }
}

我希望获得该属性的值,但每次计算该值时,我都会收到一条错误消息,指出没有可用的运行空间。检查该属性,我确实看到它是一个 ScriptProperty,那么您如何获取生成的值?

最佳答案

Used 属性称为 ScriptProperty。这意味着当它被调用时它会运行一个脚本。我们可以通过调用看到这一点:

get-PSDrive | get-member -Name Used

返回

Name MemberType     Definition
---- ----------     ----------
Used ScriptProperty System.Object Used {get=## Ensure that this is a FileSystem drive...

我们可以深入挖掘并查看正在运行的脚本

get-PSDrive  | get-member -Name Used | select -ExpandProperty Definition

这将返回

System.Object Used {
    get=## Ensure that this is a FileSystem drive
    if($this.Provider.ImplementingType -eq [Microsoft.PowerShell.Commands.FileSystemProvider]){
        $driveRoot = ([System.IO.DirectoryInfo] $this.Root).Name.Replace('\','')
        $drive = Get-CimInstance Win32_LogicalDisk -Filter "DeviceId='$driveRoot'"
        $drive.Size - $drive.FreeSpace
    };
}

这就是您得到异常的原因没有可用于在此线程中运行脚本的运行空间。这是因为该信息运行的脚本需要运行空间。

要解决这个问题,您可以将所有属性转换为这样的注释属性

Get-PSDrive | %{
    $drive = $_
    $obj = new-object psobject
    $_.psobject.Properties.GetEnumerator() | %{
        $obj | Add-Member -MemberType NoteProperty -name $_.Name -Value $drive."$($_.name)" 
    }
    $obj
}

或者正如@mklement0 在评论中指出的那样

Get-PSDrive | Select-Object *

哪个是更好的解决方案。

它将返回一个 PSobjects 数组,其值作为注释而不是脚本

using (var psCon = PowerShell.Create()){
    psCon.AddScript(@"
        Get-PSDrive | Select-Object *
    ");


    var psReturn = psCon.Invoke();
    foreach (var psObj in psReturn)
    {
        var driveUsedValue = psObj.Properties["Used"].Value;
    }
}

*请注意,该值将只是使用的字节整数。

关于c# - 如何在 C# 中获取 PSObject.Properties 的 ScriptProperty 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55776105/

相关文章:

c# - 实体对象不能被 IEntityChangeTracker 的多个实例引用

powershell - 在 Windows Powershell 中获取小时和分钟

.net - Github 操作 : Report dotnet test result as annotations

c# - 开发存储账户需要身份验证

c# - 范围内的 Excel NumberFormat 无法使用 c# 工作

c# - 如何将所有案例合并为一个?

c# - 如何在wpf中调用按钮的样式函数?

windows - 如何静默安装RabbitMq

powershell - 更新应用程序时,Get-AppxPackage唯一值

c# - 将 Env Conn String 注入(inject) .NET Core 2.0 w/EF Core DbContext 与 Startup prj 不同的类库中并实现 IDesignTimeDbContextFactory