4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PowerShellおぼえがき

Last updated at Posted at 2021-09-06

はじめに

PowerShellスクリプトを書いているときにハマったところを覚え書きにして残します。

環境編

PowerShell ISEの起動

PowerShell及びPowerShell ISEは、デフォルトでスタートメニューに入っている。

スタートメニュー → 「Windows PowerShell」

ちなみにPowerShell本体及びISEは、
C:\Windows\System32\WindowsPowerShell\v1.0 (64bit)
C:\Windows\SysWOW64\WindowsPowerShell\v1.0 (32bit)
に格納されている。

PowerShell ISEでデバッグできない!

PowerShell ISEは、保存されていないスクリプトの場合、画面下部のコンソールに
編集中のスクリプトをそのまま流し込むことで実行する。
この場合、スクリプトファイルの実行ポリシーの影響を受けないので問題なくデバッグは
できるが、一旦ファイルとして保存したスクリプトに関しては先述の実行ポリシーが
適用されるため、実行することができない。
この場合、下記のような手順で実行ポリシーを変更することで
スクリプトファイルについてもデバッグ実行ができるようになる。

PowerShell ISEを起動し、画面下部のプロンプトで以下のコマンドを入力しEnter。

> Get-ExecutionPolicy

結果が Restricted になっている場合は(というかそうなってるはず)、
下記のコマンドを入力しEnter、「実行ポリシーの変更」メッセージが表示されるので、
「はい」を押す。
(実行ポリシーの内容は「スクリプトの実行ポリシー一覧」を参照)

> Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Set-ExecutionPolicy のデフォルトのスコープは LocalMachine となっているため
コマンド実行に管理者権限が必要となってしまうが、
-Scope CurrentUser を追加することで現ユーザープロファイルにスコープが
変更されるため、管理者権限で実行しなくても実行ポリシーを変更できる。
なおこの設定は永続的な設定(レジストリに記録される)になるため注意が必要。
(実行ポリシーのスコープは「実行ポリシーのスコープ一覧」を参照)

※恒久的な設定になってしまうのが嫌な場合
Set-ExecutionPolicy-ScopeProcess を指定すると、
現在開いているプロセスのみを対象に実行ポリシーを設定できる。
ただし設定されているウィンドウ(またはISE)を閉じるとその設定は失われるので
開く都度に再設定は必要となる。

> Set-ExecutionPolicy -Scope Process RemoteSigned

実行ポリシーのスコープ一覧

スコープ名 説明
MachinePolicy すべてのユーザーグループポリシー
UserPolicy 現在適用されているユーザーグループポリシー
Process 現在のPowerShellセッションのみ。
設定はレジストリではなく環境変数 $env:PSExecutionPolicyPreference に保存される。
PowerShellセッションが閉じられると、変数と値が削除される。
CurrentUser 現在のユーザー。
設定はレジストリの HKEY_CURRENT_USER に保存される。
LocalMachine 現在のコンピューター上のすべてのユーザー。
設定はレジストリの HKEY_LOCAL_MACHINE に保存される。

スクリプトの実行ポリシー一覧

実行ポリシー 署名付き 署名なし/ローカル 署名なし/非ローカル 概要
Restricted × × × 全てのスクリプトが実行禁止。
(PowerShellまたはWindows OSインストール直後のデフォルト)
AllSigned × × 署名されているスクリプトのみが実行可能。
署名されていないスクリプトは実行禁止
RemoteSigned × ローカルに保存されているスクリプトは実行可能。
インターネットからダウンロードしたスクリプト(非ローカルのスクリプト)は、
署名されているもののみが実行可能。
Unrestricted 全てのスクリプトが実行可能。
ただしインターネットからダウンロードしたスクリプトは、
実行するかどうかが確認される。
Bypass 警告やユーザーへの確認なしに、全てのスクリプトが実行可能

スクリプト起動

Windowsのデフォルト設定では .ps1 ファイルを直接実行できない。

powershell.exe 起動時に、 -ExecutionPolicy オプションで実行ポリシーを一時的に変更可能。

> powershell.exe -ExecutionPolicy Bypass -File <スクリプトのパス>

Formアプリケーション起動中プロンプト画面が邪魔!

スクリプト起動オプションに -WindowStyle Hidden を追加することで
Formアプリケーション起動時にプロンプト画面が消えるようになる。

それでも起動時に一瞬プロンプト画面が表示されるんですけど!

ショートカットを作って「実行時の大きさ」を「最小化」にすることで抑止できる。

ODBCドライバ

スクリプトが動作しているPowerShellと同じアーキテクチャのODBCドライバしか使用できない。
(64bit版のPowerShellでスクリプトを動作させるならなら64bit版のODBCドライバが必要)

おまじない編

Add-Type

.NETクラスを使うときに必要なおまじない。
ISE上でこのおまじないを実行すると.NETオブジェクトがロードされ、
おまけに.NETのインテリセンスが使えるようになる。

Add-Type -AssemblyName <.NETクラス名称>

using namespace

現行のWindows10環境であれば using namespace が使用できる。
C#みたいな感覚で.NETクラスを扱える。
ただし必ず行頭に書かなきゃならない。

変数・配列・ハッシュテーブル編

グローバル変数

基本的に子スコープからは参照可能だが、値の変更は不可。
コマンドレットを使えば子スコープから値を更新することができるらしいが、
そこまですることもない気がする。
というか個人的にはクラス作っちゃってグローバル変数は
その入れ物にしておくというスタイルが便利。

型宣言

型名称を [] で囲む

[string] $a

型の一覧(抜粋)

型定義 型名称 説明
[bool] System.Boolean $true,$falseのみ
[sbyte] System.SByte 8bit符号付整数
[byte] System.Byte 8bit整数
[int] System.Int32 32bit符号付整数
[int16] System.Int16 16bit符号付整数
[int32] System.Int32 32bit符号付整数
[int64] System.Int64 64bit符号付整数
[long] System.Int64 64bit符号付整数
[uint16] System.UInt16 16bit整数
[uint32] System.UInt32 32bit整数
[uint64] System.UInt64 64bit整数
[single] System.Single 単精度浮動小数点
[float] System.Single 単精度浮動小数点
[double] System.Double 倍精度浮動小数点
[char] System.Char 文字
[string] System.String 文字列
[decimal] System.Decimal 10進整数
[datetime] System.DateTime 日時
[timespan] System.TimeSpan 時間
[object] System.Object オブジェクト型

配列宣言

型名称の後ろに [] を書く。

[string[]] $a

配列の初期化

@(値1,値2,値3,...) という構文で任意の要素数の配列に初期化できる。

$a = @("hoge","fuga","hage")

ちなみに @()で要素数0の配列を作れる。

配列の拡張

配列変数に += で配列を拡張しつつ値を入れることができる。
また文字列の拡張も同様の書き方でできる。

$a += "piyo"

ハッシュテーブルの宣言(というかDictionaryオブジェクトの生成)

$a = [System.Collections.Generic.Dictionary[<型名称>,PSObject]]::new()

文字列の連結

+ 演算子でつなげることができる。

"hoge" + "fuga"

ハッシュテーブルの初期化

@{<キー> = <値>} という構文で初期化できる。
複数指定する場合は ; か改行で区切る。

$a = @{"aaa" = "hoge";"bbb" = "fuga";"ccc" = "hage"}
$b = @{
    "aaa" = "hoge"
    "bbb" = "fuga"
    "ccc" = "hage"
}

ちなみに @{} で要素数0のハッシュテーブルを作れる。

ハッシュテーブルへの追加と削除

add(<キー>,<値>) メソッドで要素を追加できる。

$a.add("ddd","piyo")

要素の削除は Remove(<キー>) メソッドを使う。

$a.Remove("aaa")

ハッシュテーブル値の取得と変更

配列の添え字と同じ感覚で扱える。

$a["aaa"]
$a["aaa"] = "piyo" #値の変更も可能

キーが見つからない時は $null が返る。

ハッシュテーブルに含まれるキー、値の検索

キーは ContainsKey(<キー>) メソッドで検索できる。
値は ContainsValue(<値>) メソッドで検索できる。

if($a.ContainsKey("aaa") -eq $true){ echo "True" }
if($a.ContainsValue("hoge") -eq $true){ echo "True" }

存在すれば $true 、存在しなければ $false が返る。

制御構文編

IF文の書き方

うっかり以下のような書き方をしちゃうと、エラーも出ないし式も当然ながら正しく評価されない。

if($a > 0){処理}

$aの中身が0というファイルにリダイレクトされるという動作になってしまう。
エラーにならないので案外気づきにくい。なのでシェルスクリプトよろしくこう書く必要がある。

if($a -gt 0){処理}

比較演算子一覧

比較演算子 C言語表記 意味
-eq == 等しい
-ne != 等しくない
-gt > より大きい
-ge >= 以上
-lt < より小さい
-le <= 以下
-like なし ワイルドカードと等しい
-notlike なし ワイルドカードと等しくない
-match なし 正規表現と等しい
-notmatch なし 正規表現と等しくない

switch文の書き方

書き方がちょっと特殊なので丸暗記しよう。

switch(){
    1{処理1}
    2{処理2}
    3{処理3}
    ...
}

関数編

ユーザ定義関数の定義

以下のような構文で定義する。

function <関数名>([][変数],...){
    #処理
    [return <戻り値>]
}

デフォルト値を指定することで引数の省略も可能。

function <関数名>([]<変数>[ = ]>){

ユーザ定義関数の呼び出し

構文は以下のように、引数をスペースで区切る。(コマンドに引数を渡すイメージ)

hoge [引数1] [引数2] [...]

ちなみにカンマで区切ると、引数リストとして渡される模様。(配列みたいなもん)
.NETクラスと呼び出し方が違うので混乱しやすい。

ユーザ定義関数の引数

計算式を引数とする場合、またはユーザ定義関数の返り値を引数としたい場合はかっこで囲んでおくとよい。

hoge (1 + 2) (fuga 1 2)

関数への参照渡し

参照渡しにしたい引数変数の前に [ref] をつける。

function hoge([ref]$a){処理}

関数を引数に入れたい

引数としたい関数の前後を{}で囲む。
イベントハンドラ登録時などで多用します。

hoge({fuga})

クラス編

クラスのコンストラクタ

クラス名と同名のメソッドを定義すればよい。

Class MyClass{
    [int]$a
    MyClass(){
        $this.a = 0
    }
}

クラスのプロパティ

クラスの変数がそのままプロパティになる。
ISEのインテリセンスに出したくない時は hidden 修飾子をつけるとよい。
※最新の仕様ではprivate修飾子があるようだが、現バージョンでは使えない模様。

クラスのインスタンス化

2通りのやり方がある。お好きな方で。

$c = [<クラス名>]::new()
$c = New-Object <クラス名>

自身のプロパティ、メソッドにアクセス

$this.<メソッドorプロパティ> という構文でアクセスする。

class Hoge {
    [string] $s
    
    GetStr(){
        return $this.s #プロパティの参照
    }
    
    GetString(){
        return $this.GetStr() #メソッドを呼び出す
    }
}

クラスの静的メソッドへのアクセス

クラスの静的メソッドにアクセスしたいときに使用します。
ちなみに自身に定義した静的メソッドへも同様の記述でアクセスします。
(特に.NETクラスの定数とかを取りたいときに多用します)

[<クラス名称>]::<定数名>

クラスの継承

class <クラス名称> : <継承元クラス名称> {} で継承できる。

class Fuga : Hoge {
    #処理
}

継承元クラスメソッドのオーバーライド

継承したクラスで継承元クラスにあるメソッドと同名のメソッドを定義でき、
全く違うメソッドにすることもできるし継承元メソッドを呼び出すことで機能拡張もできる。

class Fuga : Hoge {
    Hage(){
        ([Hoge]$this).Hage() #継承元クラスのメソッド
        #追加の処理とか
    }
}

フォーム編

フォーム作成の流れ

フォームに表示する各コントロールのオブジェクトを作成

フォームオブジェクトを作成

フォームに各コントロールオブジェクトを登録

フォーム表示

フォームの基本サンプル

################################################################################
## おまじない
################################################################################
# .NETのFormsクラスを読み込む
Add-Type -AssemblyName System.Windows.Forms
# .NETのDrawingクラスを読み込む
Add-Type -AssemblyName System.Drawing

################################################################################
## 各種コントロール
################################################################################
## OKボタンの設定
# ボタンコントロールオブジェクトを作成
$OKButton = New-Object System.Windows.Forms.Button
# コントロールの表示位置を設定
$OKButton.Location = New-Object System.Drawing.Point(40,100)
# コントロールのサイズを設定
$OKButton.Size = New-Object System.Drawing.Size(75,30)
# ボタンに表示するテキストを設定
$OKButton.Text = "OK"
# ダイアログの返り値を設定
$OKButton.DialogResult = "OK"

## キャンセルボタンの設定
# ボタンコントロールオブジェクトを作成
$CancelButton = New-Object System.Windows.Forms.Button
# コントロールの表示位置を設定
$CancelButton.Location = New-Object System.Drawing.Point(130,100)
# コントロールのサイズを設定
$CancelButton.Size = New-Object System.Drawing.Size(75,30)
# ボタンに表示するテキストを設定
$CancelButton.Text = "Cancel"
# ダイアログの返り値を設定
$CancelButton.DialogResult = "Cancel"

## ラベルの設定
# ボタンコントロールオブジェクトを作成
$label = New-Object System.Windows.Forms.Label
# コントロールの表示位置を設定
$label.Location = New-Object System.Drawing.Point(10,30)
# コントロールのサイズを設定
$label.Size = New-Object System.Drawing.Size(250,20)
# ラベルのテキストを設定
$label.Text = "好きな言葉を入力してください"

## テキストボックスの設定
# テキストボックスコントロールオブジェクトを作成
$textBox = New-Object System.Windows.Forms.TextBox
# コントロールの表示位置を設定
$textBox.Location = New-Object System.Drawing.Point(10,70)
# コントロールのサイズを設定
$textBox.Size = New-Object System.Drawing.Size(225,50)

################################################################################
## フォーム
################################################################################
# フォームオブジェクトを作成
$form = New-Object System.Windows.Forms.Form
# フォームのキャプションを設定
$form.Text = "入力"
# フォームのサイズを設定
$form.Size = New-Object System.Drawing.Size(260,180)

# フォームの決定ボタンとしてOKボタンコントロールを登録
$form.AcceptButton = $OKButton
# フォームのキャンセルボタンとしてキャンセルボタンコントロールを登録
$form.CancelButton = $CancelButton

# フォームにOKボタンコントロールを追加
$form.Controls.Add($OKButton)
# フォームにキャンセルボタンコントロールを追加
$form.Controls.Add($CancelButton)
# フォームにラベルコントロールを追加
$form.Controls.Add($label)
# フォームにテキストボックスコントロールを追加
$form.Controls.Add($textBox)

# フォームを表示させ、その結果を受け取る
$result = $form.ShowDialog()

# フォームの結果による処理分岐
if ($result -eq "OK")
{
    $x = $textBox.Text
    $x
}

実行結果
form_sample.png

イベントハンドラ

各コントロール及びフォームオブジェクトにイベントハンドラを登録するには
$<オブジェクト>.Add_<イベント名>({<イベントハンドラ>})
という構文で登録できる。

################################################################################
## おまじない
################################################################################
# .NETのFormsクラスを読み込む
Add-Type -AssemblyName System.Windows.Forms
# .NETのDrawingクラスを読み込む
Add-Type -AssemblyName System.Drawing

################################################################################
## イベントハンドラ
################################################################################
# フォームが表示されたときのイベントハンドラ
function Form_Shown(){
    [System.Windows.MessageBox]::Show("Form_Shownが呼ばれました!")
}

################################################################################
## フォーム
################################################################################
# フォームオブジェクトを作成
$form = New-Object System.Windows.Forms.Form
# フォームのサイズを設定
$form.Size = New-Object System.Drawing.Size(260,180)
# フォームのキャプションを設定
$form.Text = "イベントテスト"

# フォームが表示された時のイベントハンドラを登録
$form.Add_Shown({Form_Shown})

# フォームを表示させる。
$form.ShowDialog()

実行結果
event_sample.png

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?