PowerShellで巨大なファイルをGet-Contentし、Export-Csvするのを省メモリで行う

PowerShellで、ファイルを加工し、CSVファイルに出力する、ということを行った。

しかし、Get-Contentで取得したファイルを、下記の様にそのまま変数に突っ込むとファイル容量の数倍のメモリを確保しまう、というPowerShellの仕様が存在することがわかった。

$inputfile="c:\tmp\input.txt"
$inputdata=Get-Content $inputfile -Encoding UTF8 
foreach($line in $inputdata){
  いろんな処理~ 
}

しかも、配列を追加していく処理は重いらしく、かなり時間がかかる。

開発段階では、元のファイルサイズが1MB程度だったので気がつきませんでしたが、500MBや800MBになると、とんでもなくメモリを食っていました。

配列を確保しないで、次の処理を行わせるようにするには、パイプで繋いでForEach-Objectで回します。

$inputfile="c:\tmp\input.txt"
Get-Content $inputfile -Encoding UTF8 | ForEach-Object {
  $line=$_
  いろんな処理~
}

これにより、Get-Contentで読み込んだファイルに対するメモリ確保は行わずに、次の処理を行わせることができるようになります。

次に、各行を処理した結果をcsvファイルで出力する方法について改善します。

例えば、下記の様に出力結果を$results配列に入れ、それをまとめてexport-csvする、というのが簡単な実装でしょう。

$inputfile="c:\tmp\input.txt"
$outputfile="c:\tmp\output.csv"

$results=Get-Content $inputfile -Encoding UTF8 | ForEach-Object {
  $line=$_
  いろんな処理~
  $output = New-Object -TypeName PSObject
  $output | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
  $output | Add-Member -MemberType NoteProperty -Name "Value" -Value $value
  $output | Add-Member -MemberType NoteProperty -Name "Details" -Value $details
  $output
}
$results | Export-Csv $outputfile -Encoding UTF8 -NoTypeInformation -Append -NoClobber

これも、input側と同じく、配列のメモリ確保問題があります。

しかし、Export-Csvは、配列を使わないと出力できませんし、ファイルの入出力処理を毎行実行するにはコストが高いです。 (ファイルを開く処理、閉じる処理というのは一般的に遅い)

1000行ぐらいであればメモリへの影響も少なく、また、1回当たりの書き込み負荷もそれほどではないようなので、1000行に1回、Export-Csvを実行するようにしたものが、下記です。

$inputfile="c:\tmp\input.txt"
$outputfile="c:\tmp\output.csv"

$results=@()
$linecount=0
Get-Content $inputfile -Encoding UTF8 | ForEach-Object {
  $line=$_
  いろんな処理~
  $output = New-Object -TypeName PSObject
  $output | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
  $output | Add-Member -MemberType NoteProperty -Name "Value" -Value $value
  $output | Add-Member -MemberType NoteProperty -Name "Details" -Value $details
  $results+=$output

  $linecount++
  if(($linecount % 1000) -eq 0 ){
    $results | Export-Csv $outputfile -Encoding UTF8 -NoTypeInformation -Append -NoClobber
    $results = @()
  }
}
$results | Export-Csv $outputfile -Encoding UTF8 -NoTypeInformation -Append -NoClobber

これにより、読み込ませるファイルが大きい場合でも、PowerShellが使用するメモリ容量を少なく抑えることが可能となりました。


NetAppのperfstatデータ収集ツールで取得したファイルを分解する」で1行1出力で動かしてみたところ5時間かかりました。それを1000行まとめてから出力かけるように変更したところ2分で終わりました。

やはりファイル出力処理は重いですね。

vSphere PowerCLIの一部コマンドがPowerShell ISEで動作しない 2016/12/15版

2017/02/27追記
Windows環境以外でも動作するPowerCLI Coreが登場し、この手順を行おうとしたら、モジュール名が異なり実施できませんでした。
PowerCLIとPowerCLI Coreの双方で動くPowerShellスクリプトの作り方」に、対処方法を記載しています。


1年前に「vSphere PowerCLIの一部コマンドがPowerShell ISEで動作しない」というのを書いた。

最近、環境を作り直すのと一緒にPowerShellを最新にして、そして、PowerCLIを最新の6.5にしてみた。(New Release: PowerCLI 6.5 R1)

以前と同じように、PowerShell ISE上で「Add-PSSnapin VMware.VimAutomation.Core」を実行すると、「Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 5.」というエラーが発生。
「Add-PSSnapin」は使わないようだ。

 C:\Users\test3> Add-PSSnapin VMware.VimAutomation.Core


Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 5.
At line:1 char:1
+ Add-PSSnapin VMware.VimAutomation.Core
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (VMware.VimAutomation.Core:String) [Add-PSSnapin], PSArgumentException
    + FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand
 

 C:\Users\test3> 

代替はなんだろ?と確認すると「Import-Module -Name VMware.VimAutomation.Core」。

いままでスクリプトにAdd-PSSnapin~と書いていたところを、どちらでも対応できるように書き換えるとすると、下記のようになるだろうか?

if ( $PSVersionTable.PSVersion.Major -lt 5){
    Add-PSSnapin VMware.VimAutomation.Core
}else{
    Import-Module -Name VMware.VimAutomation.Core
}

下記は参考資料の実行ログ

PS C:\Users\test3> Get-Module

ModuleType Version    Name                                ExportedCommands                                                                           
---------- -------    ----                                ----------------                                                                           
Script     1.0.0.0    ISE                                 {Get-IseSnippet, Import-IseSnippet, New-IseSnippet}                                        
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}                         
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}                                  



PS C:\Users\test3> Get-Module -ListAvailable


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                                                                           
---------- -------    ----                                ----------------                                                                           
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...}                     
Script     1.0.0.1    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}                               


    Directory: C:\Windows\system32\WindowsPowerShell\v1.0\Modules


ModuleType Version    Name                                ExportedCommands                                                                           
---------- -------    ----                                ----------------                                                                           
Manifest   1.0.0.0    AppLocker                           {Set-AppLockerPolicy, Get-AppLockerPolicy, Test-AppLockerPolicy, Get-AppLockerFileInform...
Manifest   1.0.0.0    BitsTransfer                        {Add-BitsFile, Remove-BitsTransfer, Complete-BitsTransfer, Get-BitsTransfer...}            
Manifest   1.0.0.0    CimCmdlets                          {Get-CimAssociatedInstance, Get-CimClass, Get-CimInstance, Get-CimSession...}              
Script     1.0.0.0    ISE                                 {New-IseSnippet, Import-IseSnippet, Get-IseSnippet}                                        
Manifest   1.0.0.0    Microsoft.PowerShell.Archive        {Compress-Archive, Expand-Archive}                                                         
Manifest   3.0.0.0    Microsoft.PowerShell.Diagnostics    {Get-WinEvent, Get-Counter, Import-Counter, Export-Counter...}                             
Manifest   3.0.0.0    Microsoft.PowerShell.Host           {Start-Transcript, Stop-Transcript}                                                        
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...}                             
Script     1.0        Microsoft.PowerShell.ODataUtils     Export-ODataEndpointProxy                                                                  
Manifest   3.0.0.0    Microsoft.PowerShell.Security       {Get-Acl, Set-Acl, Get-PfxCertificate, Get-Credential...}                                  
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Format-List, Format-Custom, Format-Table, Format-Wide...}                                 
Manifest   3.0.0.0    Microsoft.WSMan.Management          {Disable-WSManCredSSP, Enable-WSManCredSSP, Get-WSManCredSSP, Set-WSManQuickConfig...}     
Manifest   1.0.0.0    NetworkSwitchManager                {Disable-NetworkSwitchEthernetPort, Enable-NetworkSwitchEthernetPort, Get-NetworkSwitchE...
Manifest   1.1        PSDesiredStateConfiguration         {Set-DscLocalConfigurationManager, Start-DscConfiguration, Test-DscConfiguration, Publis...
Script     1.0.0.0    PSDiagnostics                       {Disable-PSTrace, Disable-PSWSManCombinedTrace, Disable-WSManTrace, Enable-PSTrace...}     
Binary     1.1.0.0    PSScheduledJob                      {New-JobTrigger, Add-JobTrigger, Remove-JobTrigger, Get-JobTrigger...}                     
Manifest   2.0.0.0    PSWorkflow                          {New-PSWorkflowExecutionOption, New-PSWorkflowSession, nwsn}                               
Manifest   1.0.0.0    PSWorkflowUtility                   Invoke-AsWorkflow                                                                          
Manifest   1.0.0.0    TroubleshootingPack                 {Get-TroubleshootingPack, Invoke-TroubleshootingPack}                                      


    Directory: C:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Modules


ModuleType Version    Name                                ExportedCommands                                                                           
---------- -------    ----                                ----------------                                                                           
Binary     6.0.0.0    VMware.DeployAutomation                                                                                                        
Binary     6.0.0.0    VMware.ImageBuilder                                                                                                            
Binary     6.5.0.4... VMware.VimAutomation.Cis.Core                                                                                                  
Binary     6.5.0.4... VMware.VimAutomation.Cloud                                                                                                     
Manifest   6.5.0.4... VMware.VimAutomation.Common                                                                                                    
Binary     6.5.0.2... VMware.VimAutomation.Core           HookGetViewAutoCompleter                                                                   
Binary     6.0.0.0    VMware.VimAutomation.HA                                                                                                        
Binary     7.0.2.4... VMware.VimAutomation.HorizonView                                                                                               
Binary     6.5.0.4... VMware.VimAutomation.License                                                                                                   
Binary     6.5.0.4... VMware.VimAutomation.PCloud                                                                                                    
Manifest   6.5.0.4... VMware.VimAutomation.Sdk            Get-PSVersion                                                                              
Binary     6.5.0.4... VMware.VimAutomation.Storage                                                                                                   
Binary     6.5.0.4... VMware.VimAutomation.Vds                                                                                                       
Binary     6.5.0.4... VMware.VimAutomation.vROps                                                                                                     
Binary     6.0.0.0    VMware.VumAutomation                                                                                                           



PS C:\Users\test3> Import-Module -Name VMware.VimAutomation.Core

 C:\Users\test3> Get-Module

ModuleType Version    Name                                ExportedCommands                                                                           
---------- -------    ----                                ----------------                                                                           
Script     0.0        Initialize-VMware_VimAutomation_Cis                                                                                            
Script     1.0.0.0    ISE                                 {Get-IseSnippet, Import-IseSnippet, New-IseSnippet}                                        
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}                         
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}                                  
Binary     6.5.0.4... VMware.VimAutomation.Cis.Core       {Connect-CisServer, Disconnect-CisServer, Get-CisService}                                  
Manifest   6.5.0.4... VMware.VimAutomation.Common                                                                                                    
Binary     6.5.0.2... VMware.VimAutomation.Core           {Add-PassthroughDevice, Add-VirtualSwitchPhysicalNetworkAdapter, Add-VMHost, Add-VMHostN...
Manifest   6.5.0.4... VMware.VimAutomation.Sdk            Get-PSVersion                                                                              



 C:\Users\test3> 

なお、PowerCLI 6.5を起動した場合に読み込まれているモジュール一覧は以下の通り

          Welcome to VMware PowerCLI!

Log in to a vCenter Server or ESX host:              Connect-VIServer
To find out what commands are available, type:       Get-VICommand
To show searchable help for all PowerCLI commands:   Get-PowerCLIHelp
Once you've connected, display all virtual machines: Get-VM
If you need more help, visit the PowerCLI community: Get-PowerCLICommunity

       Copyright (C) VMware, Inc. All rights reserved.


PowerCLI C:\> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Initialize-VMware.VimAutomation....
Script     0.0        Initialize-VMware.VimAutomation....
Script     0.0        Initialize-VMware.VimAutomation....
Script     0.0        Initialize-VMware_DeployAutomation
Script     0.0        Initialize-VMware_VimAutomation_Cis
Script     0.0        Initialize-VMware_VumAutomation
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add...
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-T...
Binary     6.0.0.0    VMware.DeployAutomation             {Add-DeployRule, A...
Binary     6.0.0.0    VMware.ImageBuilder                 {Add-EsxSoftwareDe...
Binary     6.5.0.4... VMware.VimAutomation.Cis.Core       {Connect-CisServer...
Binary     6.5.0.4... VMware.VimAutomation.Cloud          {Add-CIDatastore, ...
Manifest   6.5.0.4... VMware.VimAutomation.Common
Binary     6.5.0.2... VMware.VimAutomation.Core           {Add-PassthroughDe...
Binary     6.0.0.0    VMware.VimAutomation.HA             Get-DrmInfo
Binary     7.0.2.4... VMware.VimAutomation.HorizonView    {Connect-HVServer,...
Binary     6.5.0.4... VMware.VimAutomation.License        Get-LicenseDataMan...
Binary     6.5.0.4... VMware.VimAutomation.PCloud         {Connect-PIServer,...
Manifest   6.5.0.4... VMware.VimAutomation.Sdk            Get-PSVersion
Binary     6.5.0.4... VMware.VimAutomation.Storage        {Copy-VDisk, Expor...
Binary     6.5.0.4... VMware.VimAutomation.Vds            {Add-VDSwitchPhysi...
Binary     6.5.0.4... VMware.VimAutomation.vROps          {Connect-OMServer,...
Binary     6.0.0.0    VMware.VumAutomation                {Add-EntityBaselin...


PowerCLI C:\>

PowerShellを使ってサーバにUTF8のJSONデータを送りつける

VMwareの出しているログ管理サーバvRealize Log Insight を使っている環境で、別製品のログもLog Insightで管理できるようにしたい、という要求があった。

該当するログを保存しているサーバはWindows Serverだというので、PowerShellを使用してログを整形し、JSONデータにしてLog Insightサーバに送りつけたのだが、単純に送りつけるだけでは日本語を正常な文字列として認識しなかった。

JSONデータ変換後のデータに対して「[System.Text.Encoding]::UTF8.GetBytes」のエンコードをしてやることで、UTF8のデータとして認識させることができた。

$loginsightserver = "IPアドレス"
$loginsightagentID = "34859a98"

$result="ジョブの結果"
$jobid = [ordered]@{
			name = "jobid"
			content = "ジョブのID"
			}
$appid = [ordered]@{
			name = "appid"
			content = "アプリのID"
			}

$fields = @($jobid,$appid)
$restcall = @{
			 messages =    ([Object[]]($messages = [ordered]@{
					text = $result
					fields = ([Object[]]$fields)
					}))
			} |convertto-json -Depth 4
$encodedrestcall= [System.Text.Encoding]::UTF8.GetBytes($restcall)
Write-Host $restcall
$resturl = ("http://" + $loginsightserver + ":9000/api/v1/messages/ingest/" + $loginsightagentID)
write-host ("Posting results to Log Insight server: " + $loginsightserver)
try
{
	$response = Invoke-RestMethod $resturl -Method Post -Body $encodedrestcall -ContentType 'application/json' -ErrorAction stop
	write-host "REST Call to Log Insight server successful"
	write-host $response
}
catch
{
	write-host "REST Call failed to Log Insight server"
	write-host $error[0]
	write-host $resturl
}

2019/06/19追記

上記の解説

Log Insightへのログ登録は「/api/v1/events/ingest/{agentId}」を使っている。

1つのフィールドの最大サイズは16KB、JSON化したあとの合計サイズとしては4MBまでをサポートしている。

冒頭で設定している「loginsightagentID」は適当な文字列を入れている。2019/06/19時点の「Getting started with the Log Insight REST API」で示されているサンプルでは「{UUID}」とされており「 aexample-uuid-4b7a-8b09-fbfac4b46fd9 」という文字列が使われているので、なんでも良いらしい。

ログを一括登録する場合の注意点として、現在は上記ドキュメントにも書かれているが、現在時刻から10分以上ズレているタイムスタンプは認めてくれない、というのが標準設定となっている。このため、10分以上ズレているログは、送信した時刻で記録されてしまう仕様となっている。

The timestamp of an event is optional, and expressed as milliseconds-since-epoch UTC. If the submission is authenticated, the timestamp field is trusted. Unauthenticated event submissions have their time clamped to within 10 minutes of the server’s current time.
% config.api-server.max-tolerated-client-time-drift=600000

この制限は「 config.api-server.max-tolerated-client-time-drift 」の値を変更することで解除できる。2018年初頭のバージョンだと「vRealize Log Insightで現在時刻±10分以外のデータも取り込む」に記載した手順で変更することができる。

PowerShellスクリプト(ps1)を実行しやすくする

(2023/10/11 ページ構成を手直し)

PowerShellスクリプト(ps1)に対して、ファイルをドラッグ&ドロップしてもファイルを認識して実行してくれない。

また、そもそもPowerShellスクリプトを実行しようとしても、下記のエラーで実行ができない。

PS C:\Users\osakanataro\Documents\powershell> .\powershelltest.ps1
スクリプトの実行がシステムで無効になっているため、ファイル C:\Users\osakanataro\Documents\powershell\powershelltest.ps1 を読み込めません。詳細については、「get-help about_signing」と入力してヘルプを参照してください。
発生場所 行:1 文字:25
+ .\powershelltest.ps1 <<<<
    + CategoryInfo          : NotSpecified: (:) []、PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

PS C:\Users\osakanataro\Documents\powershell> 

回避方法として、バッチファイルの中からPowerShellを起動する、というものが知られている。

具体的には以下の様なバッチファイルを作って、バッチファイルをクリックする、というものになる。

@echo off
rem PowerShellスクリプトの実行が禁止されている場合に
rem このバッチファイルを管理者権限で動作させると
rem PowerShellスクリプトが実行できます。

powershell -sta -ExecutionPolicy Unrestricted -File %0\..\powershelltest.ps1 %*

この場合、PowerShellスクリプトのファイルと、バッチファイルの2つを同時に配布しなければならない、という問題がある。

これを解消するために、バッチファイルの中にPowerShellスクリプトの記述も含めてしまおう、という技がある。

@echo off
powershell -sta -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 2})-join\"`n\");&$s" %*&goto:eof
# こんな感じで書く
$PSVersionTable
などPowerShellスクリプトの内容を記載

やってることは、バッチファイルからPowerShellを起動したら、そのPowerShellは、いま起動に使ったバッチファイルの2行目の次からスクリプトを読み出しを開始しバッチファイルの最後まで読み込んだあと、PowerShellスクリプトとして実行を開始する、というもの

これによって、バッチファイル1個だけでPowerShellを実行できるようになる。

ただ、この技を使うとLinux/MacOSXなどの他OSのPowerShell環境で動作させにくくなる、という弊害もあるので、Windows環境のみで使う場合にとどめておくと良い。

別解として下記もあると教えていただきました。

@ set args=%*
@ powershell "iex( (@('','','')+(cat '%~f0'|select -skip 3))-join[char]10)"
@ exit /b %ERRORLEVEL%

ここから下は以前の記述


回避方法は下記の2つを行う、ということ

・バッチファイル経由でPowerShellを起動する
・うまく行かない場合は、管理者権限でバッチファイルを起動する

今回使用したバッチファイルは下記の内容とした

@echo off
rem PowerShellスクリプトの実行が禁止されている場合に
rem このバッチファイルを管理者権限で動作させると
rem PowerShellスクリプトが実行できます。

powershell -sta -ExecutionPolicy Unrestricted -File %0\..\powershelltest.ps1 %*

なお、powershell起動時に「-sta」オプションをつけているのは、powershellからフォームダイアログを開こうとすると、下記のエラーがでてしまうことを回避するためです。

なお、詳細を開くと下記の情報が出力されている

Just-In-Time (JIT) デバッグを呼び出すための詳細については、
ダイアログ ボックスではなく、このメッセージの最後を参照してください。

************** 例外テキスト **************
System.InvalidOperationException: DragDrop 登録は成功しませんでした。 ---> System.Threading.ThreadStateException: OLE が呼び出される前に、現在のスレッドが Single Thread Apartment (STA) モードに設定されていなければなりません。Main 関数に STAThreadAttribute が設定されていることを確認してください。
   場所 System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
   --- 内部例外スタック トレースの終わり ---
   場所 System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
   場所 System.Windows.Forms.Control.OnHandleCreated(EventArgs e)
   場所 System.Windows.Forms.ListBox.OnHandleCreated(EventArgs e)
   場所 System.Windows.Forms.Control.WmCreate(Message& m)
   場所 System.Windows.Forms.Control.WndProc(Message& m)
   場所 System.Windows.Forms.ListBox.WndProc(Message& m)
   場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   場所 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** 読み込まれたアセンブリ **************
mscorlib
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5485 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/Microsoft.NET/Framework64/v2.0.50727/mscorlib.dll
----------------------------------------
Microsoft.PowerShell.ConsoleHost
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7600.16385
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.ConsoleHost/1.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.ConsoleHost.dll
----------------------------------------
System
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.8686 (QFE.050727-8600)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Management.Automation
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Management.Automation/1.0.0.0__31bf3856ad364e35/System.Management.Automation.dll
----------------------------------------
Microsoft.PowerShell.Commands.Diagnostics
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.Commands.Diagnostics/1.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.Commands.Diagnostics.dll
----------------------------------------
System.Core
    アセンブリ バージョン: 3.5.0.0
    Win32 バージョン: 3.5.30729.5420 built by: Win7SP1
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Core/3.5.0.0__b77a5c561934e089/System.Core.dll
----------------------------------------
System.Configuration.Install
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5483 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Configuration.Install/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.Install.dll
----------------------------------------
Microsoft.WSMan.Management
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.WSMan.Management/1.0.0.0__31bf3856ad364e35/Microsoft.WSMan.Management.dll
----------------------------------------
System.Transactions
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5483 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_64/System.Transactions/2.0.0.0__b77a5c561934e089/System.Transactions.dll
----------------------------------------
Microsoft.PowerShell.Commands.Utility
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.Commands.Utility/1.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.Commands.Utility.dll
----------------------------------------
Microsoft.PowerShell.Commands.Management
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.Commands.Management/1.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.Commands.Management.dll
----------------------------------------
Microsoft.PowerShell.Security
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.Security/1.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.Security.dll
----------------------------------------
Microsoft.PowerShell.ConsoleHost.resources
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7600.16385
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.ConsoleHost.resources/1.0.0.0_ja_31bf3856ad364e35/Microsoft.PowerShell.ConsoleHost.resources.dll
----------------------------------------
System.Xml
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5494 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Management
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5483 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Management/2.0.0.0__b03f5f7f11d50a3a/System.Management.dll
----------------------------------------
System.DirectoryServices
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5483 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.DirectoryServices/2.0.0.0__b03f5f7f11d50a3a/System.DirectoryServices.dll
----------------------------------------
System.Management.Automation.resources
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7600.16385
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Management.Automation.resources/1.0.0.0_ja_31bf3856ad364e35/System.Management.Automation.resources.dll
----------------------------------------
Microsoft.WSMan.Management.resources
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.WSMan.Management.resources/1.0.0.0_ja_31bf3856ad364e35/Microsoft.WSMan.Management.resources.dll
----------------------------------------
mscorlib.resources
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5485 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/Microsoft.NET/Framework64/v2.0.50727/mscorlib.dll
----------------------------------------
Microsoft.PowerShell.Security.resources
    アセンブリ バージョン: 1.0.0.0
    Win32 バージョン: 6.1.7601.17514
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Microsoft.PowerShell.Security.resources/1.0.0.0_ja_31bf3856ad364e35/Microsoft.PowerShell.Security.resources.dll
----------------------------------------
System.Data
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.8692 (QFE.050727-8600)
    コードベース: file:///C:/Windows/assembly/GAC_64/System.Data/2.0.0.0__b77a5c561934e089/System.Data.dll
----------------------------------------
System.Windows.Forms
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5491 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5495 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
Accessibility
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5483 (Win7SP1GDR.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/Accessibility/2.0.0.0__b03f5f7f11d50a3a/Accessibility.dll
----------------------------------------
System.Windows.Forms.resources
    アセンブリ バージョン: 2.0.0.0
    Win32 バージョン: 2.0.50727.5420 (Win7SP1.050727-5400)
    コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_ja_b77a5c561934e089/System.Windows.Forms.resources.dll
----------------------------------------

************** JIT デバッグ **************
Just-In-Time (JIT) デバッグを有効にするには、このアプリケーション、
またはコンピュータ (machine.config) の構成ファイルの jitDebugging 
値を system.windows.forms セクションで設定しなければなりません。
アプリケーションはまた、デバッグを有効にしてコンパイルされなければ
なりません。

例:

<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>

JIT デバッグが有効なときは、このダイアログ ボックスで処理するよりも、
ハンドルされていない例外はすべてコンピュータに登録された
JIT デバッガに設定されなければなりません。

2021/05/12追記

これをさらにすすめて、バッチファイル内にPowerShellスクリプトを書いてしまう、という技もあることを知った。

powershell -sta -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
# こんな感じで書く
$PSVersionTable
~

注意点として、powershellを起動するより前に日本語を書いてはいけない、ということ

これはDOSプロンプトとPowerShellとで日本語の取り扱いが異なるため発生しているので、DOS側では日本語を取り扱わず、PowerShellが起動した後には使う、というようにしなければならない

また、@echo offを入れたい、という場合は下記の様にreadcount の後の数字を増やして対応する。(指定行数より後をPowerShellスクリプトとして読み込み、という命令)

@echo off
powershell -sta -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 2})-join\"`n\");&$s" %*&goto:eof
# こんな感じで書く
$PSVersionTable
~

指定したデータストアがローカルディスクなのかを判定するPowerCLI

PowerShell/PowerCLIを使ってデータストアの空き容量チェックを行う過程で、ローカルディスクのVMFSは無視したい、というものがある。
ESXiホスト台数が増加することを考えると名前による除外などはやりたくない。
何らかの手法でローカルディスクかどうかを判定できないかを探した。

・Get-Datastoreで取得できる情報の範囲で確定できるものが無い
  vSphere6であれば「ExtensionData.Summary.MultipleHostAccess」というデータストアが
  複数のホストからアクセス可能か?というフラグ(true or false)があるが、
  1台のホストだけ接続しているiSCSi,FCデータストアも対象になるのでは?(未確認)
・Get-ScsiLunには「IsLocal」というローカルディスク判定フラグがある
・Get-ScsiLunはデータストアを指定して実行することができる
・ESXiホストが停止しているデータストアに対するGet-ScsiLunはエラーとなる
・アクセス出来ないデータストアは「Accessible」フラグがfalseとなる

これらを元に作成した判定

$localdatastore=$false # フラグ
$datastore = Get-Datastore "データストア名" 
if($datastore.Type -eq "VMFS"){
  # VMFSだとローカルディスクの可能性があり
  # それ以外の、NFS,vsanは対象外
  if($datastore.ExtensionData.Summary.MultipleHostAccess -eq $true){
    # MultipleHostAccessがTrueなら、ローカルディスクではないことが確定
    $localdatastore=$false
  }elseif($datastore.Accessible -eq $true){
    # アクセスできるならGet-ScsiLunがエラーにならない
    $diskinquire = Get-ScsiLun -Datastore $datastore
    if($diskinquire.IsLocal -eq $true){
      # IsLocalによるローカルディスク確定
      $localdatastore=$true
    }
  }else{
    # アクセスできないデータストア
  }
}