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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在C#中获取PSObject.Properties的ScriptProperty值?相关的知识,希望对你有一定的参考价值。

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

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

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

以下是我正在使用的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
    ;

这就是你获得There is no Runspace available to run scripts in this thread例外的原因。这是因为该信息运行需要运行空间的脚本。

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

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数组,其值为notes而不是script

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#中获取PSObject.Properties的ScriptProperty值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C/C++ 中获取 HTML [关闭]

在 C/C++ 中,如何在虚拟内存空间中获取数据?

如何在c中获取屏幕截图[关闭]

如何在c中获取文件长度?

如何在 Lua/C# 中获取 HWID?

如何在从 C 到 C# 的结构中获取非托管可变长度 C 数组?