PowerShell Tips
ショートカットを作成する
コマンドレットとしては用意されていないので、WScript.Shell
のCreateShortcut
を使う。
ファイル名の拡張子が.lnk
ならWshShortcut
(ローカルショートカット)、.url
ならWshUrlShortcut
(インターネットショートカット)になる。
enum WindowStyle {
Active = 1
Maximize = 3
Minimize = 7
}
function New-Shortcut {
param(
[Parameter(Position=0, Mandatory, ValueFromPipelineByPropertyName)]
[string] $TargetPath,
[Parameter(Position=1, Mandatory, ValueFromPipelineByPropertyName)]
[string] $Name,
[Parameter(ValueFromPipelineByPropertyName)]
$WindowStyle,
[Parameter(ValueFromPipelineByPropertyName)]
$WorkingDirectory,
[Parameter(ValueFromPipelineByPropertyName)]
[string] $HotKey,
[Parameter(ValueFromPipelineByPropertyName)]
[string] $Description,
[Parameter(ValueFromPipelineByPropertyName)]
$IconLocation
)
$sh = New-Object -ComObject WScript.Shell
$ln = $sh.CreateShortcut($Name)
$ln.TargetPath = $TargetPath
if ($null -ne $WindowStyle) {
$ln.WindowStyle = $WindowStyle
}
if ($null -ne $WorkingDirectory) {
$ln.WorkingDirectory = $WorkingDirectory
}
if (-not [string]::IsNullOrEmpty($HotKey)) {
$ln.HotKey = $HotKey
}
if (-not [string]::IsNullOrEmpty($Description)) {
$ln.Description = $Description
}
if ($null -ne $IconLocation) {
$ln.IconLocation = $IconLocation
}
$ln.Save()
}
UUIDv4を作成する
function New-UUIDv4 {
-join ("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".ToCharArray() | % {
switch ($_) {
'x' { return (Get-Random -Maximum 16).ToString('x') }
'y' { return ((Get-Random -Maximum 16) + 8).ToString('x') }
default { return $_ }
}
})
}
CSVとJSON
Import-Jsonがない
Windows 10に標準インストールされているPowerShell環境はかなり古いため、Import-Json
がない。
が、しかし、ConvertFrom-Json
とConvertTo-Json
があるため
# JSONファイル読み込み
Get-Content sample.json | ConvertFrom-Json
# JSONファイル出力
ConvertTo-Json $data | Out-File sample.json
でなんとかなる。
Shift_JISの扱い
Windows環境ならGet-Content
に-Encoding Oem
を指定するのが一番楽。
Get-Content -Encoding Oem file_in_sjis.json | ConvertFrom-Json
Export-Csvで謎の型情報が出る
PowerShell 6.0以前はExport-Csv
で出力されるファイルにはデフォルトで型情報が付与されていて、型情報なしで出力するには-NoTypeInformation
オプションを付ける必要があった。
その後、型情報なしで出力する動作がデフォルト動作として変更された。
後方互換性のために-NoTypeInformation
オプションは残されているため、どのバージョンのPowerShellであっても基本的にExport-Csv
には-NoTypeInformation
を付けておくとよい。
タブ区切りCSVを扱う
Import-Csv -Delimiter "`t"
でタブ区切りのCSV(TSVとも)を読み込める。
エスケープシーケンス
Windows 10以降の標準ターミナル(conhost.exe
)やPowerShellのターミナル(powershell.exe
)ではエスケープシーケンスによる文字色の変更などがサポートされている。
有効化する
一部環境ではデフォルトで無効になっているので、レジストリのHKEY_CURRENT_USER\Console
にDWORD値VirtualTerminalLevel
を追加し、その値を1
にする必要がある。
Set-ItemProperty -Path "HKCU:\Console" -Name "VirtualTerminalLevel" -Value 1 -Type DWord
文字色を変える
エスケープ + [31m
で文字色を赤にし、エスケープ + [0m
で文字色を元にもどしている。
PowerShell 6以降であればエスケープ($([char]27)
)は`e
でもOK。
Write-Host "$([char]27)[31mThis is a red text.$([char]27)[0m"
WPFでGUI
AttachConsole
C#コードですが、csc /target:winexe
でコンパイルした実行ファイルでもAttachConsole
を使用すれば標準出力へデータを流せます。
using System;
using System.Runtime.InteropServices;
public class Win32
{
public static int ATTACH_PARENT_PROCESS = -1;
[DllImport("kernel32.dll")]
public static extern bool AttachConsole(int dwProcessId);
}
public class Program
{
[STAThread]
public static void Main()
{
if (Win32.AttachConsole(Win32.ATTACH_PARENT_PROCESS))
{
using (var stdout = new StreamWriter(Console.OpenStandardOutput(), Encoding.GetEncoding("shift-jis")))
{
Console.SetOut(stdout);
Consolw.WriteLine("{\"hello\": "world!\\n\"}");
}
}
}
}
GUIアプリの終了を待つ
Start-Process
の-Wait
を使うとGUIアプリの終了を待つことができます。
さらに、-RedirectStandardOutput
を使えば標準出力をファイルへリダイレクトできるのでデータの受け渡しが可能です。
$tmp = New-TemporaryFile
Start-Process winexe.exe -Wait -RedirectStandardOutput $tmp
$r = Get-Content -Encoding Oem $tmp | ConvertFrom-Json
Remove-Item $tmp