Open13
Powershell で個人的によく使うあれこれ
batファイルからPowerShellを実行する
- 管理者権限なしの場合
@powershell -NoProfile -ExecutionPolicy RemoteSigned "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s "%~dp0 %*&goto:eof
- 管理者権限ありの場合
@echo off
for /f "tokens=3 delims=\ " %%i in ('whoami /groups^|find "Mandatory"') do set LEVEL=%%i
if NOT "%LEVEL%"=="High" (powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process %~f0 -Verb runas"&exit)
powershell -NoProfile -ExecutionPolicy RemoteSigned "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 4})-join\"`n\");&$s "%~dp0 %*&goto:eof
参考
PowerShellでインストール済みプログラムの取得
$AppName = "hoge"
Get-WmiObject Win32_Product | Where-Object{$_.Name -eq $AppName)
管理者権限に昇格して現在のスクリプトを実行
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit }
参考
管理者権限で実行されているか確認する関数
function IsAdmin(){
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
一時フォルダーにPowershellセッションを保存する
素のStart-Transcriptでは、「トランスクリプトが開始されました。出力ファイル:␣<FilePath>」の形式でパスがもどってくるので、-Split 演算子でファイルパスのみ戻すように作成
[string]$transPath=((Start-Transcript -OutputDirectory $env:TEMP) -Split " ")[1]
Get-Item $transPath | Format-Table
<#プログラムを記述#>
Stop-Transcript | Out-Null
実行結果(例)
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022/10/18 6:45 1616 PowerShell_transcript.<HostName>.LZxPG2qs.20221018064537.txt
ハッシュ値を求める関数
標準のGet-FileHashでは文字列のハッシュ値を求められないため
function Script:Get-HashValue {
param(
[parameter(mandatory = $true)][string]$text,
[ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")][string]$Algorithm = "SHA256",
[uint32]$stretch = 1
)
if ($stretch -ne 0) {
$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write($text)
$writer.Flush()
$stringAsStream.Position = 0
return Get-HashValue -text ([string](Get-FileHash -InputStream $stringAsStream -Algorithm $Algorithm).Hash) -Algorithm $Algorithm -stretch ($stretch - 1)
}
else {
return $text
}
}
Base64 エンコード・デコード
function ConvertTo-Base64 ([parameter(mandatory = $true)][string]$text) {
$byte = ([System.Text.Encoding]::Default).GetBytes($text)
return [Convert]::ToBase64String($byte)
}
function ConvertFrom-Base64 ([parameter(mandatory = $true)][string]$Base64) {
$byte = [System.Convert]::FromBase64String($Base64)
return [System.Text.Encoding]::Default.GetString($byte)
}
$text = "Hello World!!"
$base64 = Convertto-Base64 -text $text
$res = ConvertFrom-Base64 -Base64 $base64
Write-Host "変換前:$($text),Base64:$($base64),変換後:$($res)"
# > Hello World!!,Base64:SGVsbG8gV29ybGQhIQ==,変換後:Hello World!!
選択肢プロンプトを呼び出す関数
function Invoke-ChoicePrompt {
<#
.SYNOPSIS
コンソール上で選択肢プロンプトを呼び出す
.PARAMETER ChoiceDescriptions
以下のオブジェクトが含まれる配列データを渡す。
[PSCustomObject]@{
label = Mandatory
helpMessage = Optional
}
#>
param([parameter(Mandatory, HelpMessage = "[PSCustomObject]@{label,helpMessage}")][array]$ChoiceDescriptions,
[string]$title,
[string]$message,
[int]$Default
)
$ChoiceDescription = @()
$ChoiceDescriptions | ForEach-Object { $ChoiceDescription += New-Object System.Management.Automation.Host.ChoiceDescription($_.label, $_.helpMessage) }
return $host.ui.PromptForChoice($title, $message, $ChoiceDescription, $Default)
}
function New-ChoiceDescription {
[Alias("ChoDesc")]
param (
[parameter(Mandatory)][string]$label,
[string]$helpMessage
)
return [PSCustomObject]@{
label = $label
helpMessage = $helpMessage
}
}
$result = Invoke-ChoicePrompt -ChoiceDescriptions @((ChoDesc "はい(&Y)" -helpMessage "次の処理を実行します。"), (ChoDesc "いいえ(&N)" -helpMessage "処理を実行しません。"))
メッセージボックスを呼び出す関数
function Invoke-MessageBox {
param (
[parameter(mandatory)][string]$text,
[string]$caption = "",
[ValidateSet("OK" , "OKCancel", "AbortRetryIgnore", "YesNoCancel", "YesNo", "RetryCancel", "CancelTryContinue")][string]$button = "OK",
[ValidateSet("None" , "Stop", "Question", "Exclamation", "Information")][string]$icon = "None",
[ValidateSet("Button1" , "Button2", "Button3", "Button4")][string]$defaultButton = "Button1"
)
Add-Type -Assembly System.Windows.Forms
return [System.Windows.Forms.MessageBox]::Show($text, $caption, $button, $icon, $defaultButton)
}
インプットボックスを呼び出す関数
function Invoke-InputBox {
param (
[parameter(mandatory)][string]$Prompt,
[string]$Title = " ",
[string]$DefaultResponse
)
[void][System.Reflection.Assembly]::Load("Microsoft.VisualBasic, Version=8.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
return [Microsoft.VisualBasic.Interaction]::InputBox($Prompt, $Title, $DefaultResponse)
}
ランダムな文字列を作成する関数
function Get-RandomText {
param (
[int]$length = 10,
[switch]$upperCase,
[switch]$lowercase,
[switch]$number,
[switch]$symbols,
[switch]$duplicated
)
if (($upperCase -or $lowercase -or $number -or $symbols) -eq $false) {
$upperCase = $true
$lowercase = $true
$number = $true
$symbols = $true
}
if ($upperCase) { $asciiTable += [char[]](65..90) }
if ($lowercase) { $asciiTable += [char[]](97..122) }
if ($number) { $asciiTable += [char[]](48..57) }
if ($symbols) { $asciiTable += [char[]](33, 47) + [char[]](58..64) + [char[]](91..96) + [char[]](123..126) }
if ($duplicated) { return [string][char[]]((1..$length) | ForEach-Object { $asciiTable | Get-Random } ) -replace " " , "" }
else {
if ($asciiTable.Length -ge $length) { return [string][char[]]($asciiTable | Get-Random -Count $length) -replace " " , "" }
else { Write-Error -Message "Length Is Too Long." }
}
}
トースト通知を作成する関数
Function Show-Toast {
[CmdletBinding()]
PARAM (
[String]$title = "",
[String]$message = "",
[String]$detail = "",
[String]$icon = "",
[String]$hero = "",
[string]$uri = "",
[string]$appID = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
)
if ($detail -ne "" ) { $detail = "<text>$($detail)</text>" }
if ($icon -ne "" ) { if (Test-Path $icon ) { $icon = "<image placement=`"appLogoOverride`" hint-crop=`"circle`" src=`"$($icon)`"/>" } }
if ($hero -ne "" ) { if (Test-Path $hero ) { $hero = "<image placement=`"hero`" hint-crop=`"circle`" src=`"$($hero)`"/>" } }
if ($uri -ne "" ) { $uri = "activationType=`"protocol`" launch=`"$($uri)`"" }
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
$content = @"
<?xml version="1.0" encoding="utf-8"?>
<toast $($uri) >
<visual>
<binding template="ToastGeneric">
<text>$($title)</text>
<text>$($message)</text>
$($detail)
$($icon)
$($hero)
</binding>
</visual>
</toast>
"@
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
$xml.LoadXml($content)
$toast = New-Object Windows.UI.Notifications.ToastNotification $xml
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appid).Show($toast)
}
進行状況バーを作成する関数
Function Show-ProgressToast {
[CmdletBinding()]
PARAM (
[String]$title,
[String]$message,
[String]$progressTitle,
[String]$tag = (New-Guid).Guid ,
[String]$group = (New-Guid).Guid ,
[string]$appID = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
)
$meta = [PSCustomObject]@{
Tag = $tag
Group = $group
AppID = $appID
}
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
$content = @"
<?xml version="1.0" encoding="utf-8"?>
<toast>
<visual>
<binding template="ToastGeneric">
<text>$($title)</text>
<text>$($message)</text>
<progress value="{progressValue}" title="{progressTitle}" valueStringOverride="{progressValueString}" status="{progressStatus}" />
</binding>
</visual>
</toast>
"@
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
$xml.LoadXml($content)
$toast = New-Object Windows.UI.Notifications.ToastNotification $xml
$toast.Tag = $meta.Tag
$toast.Group = $meta.Group
$toastData = New-Object 'system.collections.generic.dictionary[string,string]'
$toastData.add("progressTitle", $progressTitle)
$toastData.add("progressValue", "")
$toastData.add("progressValueString", "")
$toastData.add("progressStatus", "")
$toast.Data = [Windows.UI.Notifications.NotificationData]::new($toastData)
$toast.Data.SequenceNumber = 1
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($meta.AppID).Show($toast)
return $meta
}
Function Update-ProgessToast {
[CmdletBinding()]
PARAM (
[Parameter(Mandatory)]$meta,
[Parameter(Mandatory)][String] $value,
[Parameter(Mandatory)][String] $message,
[Parameter(Mandatory)][String] $status
)
$toastData = New-Object 'system.collections.generic.dictionary[string,string]'
$toastData.add("progressValue", $value)
$toastData.add("progressValueString", $message)
$toastData.add("progressStatus", $status)
$progressData = [Windows.UI.Notifications.NotificationData]::new($toastData)
$progressData.SequenceNumber = 2
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($meta.AppID).Update($progressData, $meta.Tag , $meta.Group) | Out-Null
}