简体   繁体   English

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

[英]How to get ScriptProperty Values of PSObject.Properties in C#?

I am trying to get drive information for a server through PowerShell 6.0 using the 'GET-PSDrive' command. 我正在尝试使用'GET-PSDrive'命令通过PowerShell 6.0获取服务器的驱动器信息。 Running the command directly in PowerShell, I see the values for 'Used' and 'Free' within the output table, but running the same command in code though using the Microsoft.Powershell.Sdk the 'Used' and 'Free' fields are not available. 直接在PowerShell中运行命令,我在输出表中看到'Used'和'Free'的值,但是在代码中运行相同的命令但是使用Microsoft.Powershell.Sdk'Used'和'Free'字段不是可用。

I see both items listed under the PSObject.Properties array, but trying to access the value I receive the exception: 我看到PSObject.Properties数组下列出了两个项目,但是尝试访问我收到异常的值:

"There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of the System.Management.Automation.Runspaces.Runspace type. The script block you attempted to invoke was: ##" “在此线程中没有可用于运行脚本的Runspace。您可以在System.Management.Automation.Runspaces.Runspace类型的DefaultRunspace属性中提供一个。您尝试调用的脚本块是:##”

The following is the POC code that I am working with: 以下是我正在使用的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;
     }
}

I am expecting to get the value of that property, but each time the value is evaluated I get an error saying that no runspace is available. 我期望得到该属性的值,但每次评估该值时,我都会收到一条错误消息,指出没有可用的运行空间。 Inspecting the property I do see that its a ScriptProperty, so how do you go about getting that generated value? 检查属性我确实看到它是一个ScriptProperty,那么你如何获得生成的值呢?

The property Used is a called a ScriptProperty. Used属性称为ScriptProperty。 It means when it is called it runs a script. 这意味着它在被调用时会运行一个脚本。 We can see this by calling : 我们可以通过以下方式看到:

get-PSDrive | get-member -Name Used

This returns 这回来了

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

We can dig deeper and see the script that is running also 我们可以深入挖掘并查看正在运行的脚本

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

This will return 这将返回

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
    };
}

This is why you get the exception There is no Runspace available to run scripts in this thread . 这就是您获得异常的原因。 There is no Runspace available to run scripts in this thread It is because that info runs a script which needs a runspace. 这是因为该信息运行需要运行空间的脚本。

to work around this you can turn all the properties into note properties like this 要解决这个问题,您可以将所有属性转换为这样的音符属性

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

OR as @mklement0 pointed out in the comments 或者@ mklement0在评论中指出

Get-PSDrive | Select-Object *

Which is much better solution. 哪个是更好的解决方案。

It will return an array of PSobjects with the values as notes instead of script 它将返回一个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;
    }
}

*Note the value will just the integer of bytes used. *注意,该值只是所用字节的整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM