4

「GET-PSDrive」コマンドを使用して、PowerShell 6.0 からサーバーのドライブ情報を取得しようとしています。コマンドを PowerShell で直接実行すると、出力テーブル内に 'Used' と 'Free' の値が表示されますが、コードで同じコマンドを実行しても、Microsoft.Powershell.Sdk を使用しても 'Used' フィールドと 'Free' フィールドは表示されません。利用可能。

PSObject.Properties 配列の下に両方の項目がリストされていますが、値にアクセスしようとすると例外が発生します。

「このスレッドでスクリプトを実行できる実行空間がありません。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 であることがわかります。では、その生成された値を取得するにはどうすればよいでしょうか?

4

1 に答える 1

5

使用されるプロパティは、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 の配列を返します。

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

*値は、使用されるバイトの整数だけになることに注意してください。

于 2019-04-20T18:46:16.193 に答える