PowerShellをダブルクリックで実行する方法3つ＋α

[**PowerShellスクリプトをワンアクションで実行できるようにする**](https://qiita.com/heliojack/items/1cf3cc74f180374618ce#powershell%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E3%83%AF%E3%83%B3%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B) で使った内容について、改めて調べてみたら自分で仕事中に使いたいものが全部まとまってる記事が見つからなかったので、書こうと思います。ほぼ自分用メモ。

PowerShellスクリプト(.ps1)は、素でダブルクリックすると『Windows PowerShell ISE』というPowerShell編集ソフトが起動してしまいます。
「ちがう、そうじゃない！ 作るんじゃなくて使いたいんじゃ！」という人向けです。

クリック数の少なさは正義！

| |オススメ度|難易度|ファイル (数)|PowerShell|
|:---|:-------:|:----:|:-----------|:---------|
|**A**|★★★★☆|★☆☆☆☆|*lnk*+ps1 (2)|ps1ファイル|
|**B**|★★★★★|★★☆☆☆|*bat*+ps1 (2～)|ps1ファイル × n|
|**C**|★★★☆☆|★★★★★|*bat* (1～)|As you want|

## A．ショートカット(.lnk)

|**メリット**|コーディングできなくても使える|
|:----------|:--------------------------|
|**デメリット**|複数ファイルNG[^1]|
[^1]: 「外部PowerShellスクリプト内でさらに外部スクリプト呼べばイイジャン」ではありますが……個人的には好みではないので、表立って紹介はしないです。

1．ショートカット配置場所（デスクトップ等）で何もないところを右クリックし、`新規作成 ＞ ショートカット`をクリックします。
![20200801_ps1act_lnk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683056/e97ada42-5e5f-38f2-2227-ced7abf0a6f4.png)
2．「項目の場所を入力してください」を、下記のようにします。
`<ps1_LocalFilepath>`はPowerShellスクリプトファイルのパスだとお考え下さい。

```
powershell -ExecutionPolicy RemoteSigned -File "<ps1_LocalFilepath>"
```

3．「このショートカットの名前を入力してください」に任意の名前を入力し、完了ボタンをクリックします。

#### プチ解説：PowerShellの実行ポリシー
2で単に`"<ps1_LocalFilepath>"`と外部スクリプトパスだけ指定した場合、実行時エラーになります。
PowerShellには〈実行ポリシー〉というものがあり、最近のWindowsでは「実行できない」＝*Restricted* がデフォルトになっています。
〈実行ポリシー〉を**一時的に**変更するために、`-ExecutionPolicy パラメーター`を指定しています。*RemoteSigned* は、「署名付きファイルは実行できる。ローカルファイルなら署名なくても実行できる」です。

例えばローカルではない場所の外部スクリプトパスを指定する場合、`-ExecutionPolicy RemoteSigned`だと実行時エラーになります。
その場合は`-ExecutionPolicy Bypass`にすると通るのでしょうが、これは「どんなファイルでも実行する」というセキュリティ的にザルな設定なので、軽率に使うのは推奨されません。

なお、〈実行ポリシー〉は`Set-ExecutionPolicy コマンドレット`によって、ユーザー設定レベルで変更することもできます。一度変更したら〈実行ポリシー〉を毎回変更しなくてよくなる便利さがあります。
しかし、ユーザー設定ですので、ユーザーが変われば再度`Set-ExecutionPolicy コマンドレット`で変更しないといけません。使うのが自分だけでなければ、`-ExecutionPolicyパラメーター`で一時的に変更するほうがメンドウがありません。

## B．バッチファイル(.bat)で外部PowerShellスクリプト呼び出し
|**メリット**|コーディングできなくても使えるし、複数ファイルOK|
|:----------|:-------------------------------------------|
|**デメリット**|デスクトップにはショートカット以外置かない派の信義に反する|

**A** のような内容を列挙したバッチファイル(.bat)を作成します。
バッチの中でPowerShellスクリプトを読むだけですね。

```例：ps1_call.bat
@echo off
powershell -ExecutionPolicy RemoteSigned -File "<ps1_LocalFilepath_1>"
powershell -ExecutionPolicy RemoteSigned -File "<ps1_LocalFilepath_2>"
powershell -ExecutionPolicy RemoteSigned -File "<ps1_LocalFilepath_3>"
```

**A** とは異なり、複数のPowerShellスクリプトを呼び出すことができます。
PowerShellスクリプトを役割毎で分けて作り、実行するバッチの内容を変えたパターン化などが期待できますね。

## C．バッチ＆PowerShell混合
|**メリット**|〈実行ポリシー〉を意識しなくていいし、複雑なことができる|
|:----------|:--------------------------------------------------|
|**デメリット**|｜(パイプ)に弱い|

バッチの中でPowerShellをコマンド実行します。
**A**／**B** はPowerShellスクリプトさえあれば自分自身でコーディングできなくても可能ですが、これは自分で作れないと厳しいです。
代わりに、バッチで作ると複雑になってしまうことも簡潔に実装できたりします。

例えば、日時の扱いなんかはバッチよりもPowerShellのほうが、はるかに優れています。
バッチだけで日付を計算しようとすると、月の末日やうるう年を考慮しなければいけませんが、PowerShellなら意識する必要がありません。
「メインはバッチで、日時の計算だけはPowerShellを使う」というようなこともできます。

もちろん、**B** との混合も可能です。

```例：ps1_call.bat
@echo off
set dateformat="M月d日"
set /a num=5
set ps=Write-Host ((Get-Date).ToString(%dateformat%) + " の%num%日前は " + (Get-Date).AddDays(-%num%).ToString(%dateformat%) + " です");
set ps=%ps:"=\"%
powershell -Command "%ps%"
pause
```
```
8月1日 の5日前は 7月27日 です
```

#### プチ解説：エスケープ
`-Command パラメーター`に指定するため、特定文字をエスケープする必要があります。上記例では`"`をエスケープしています。

※エスケープについては汎用的な知識ですので、解説しません。

## 【番外】キーボード ショートカット割り当て
キーボード操作派にとってはダブルクリック（キーボード的には〔ファイル名を指定して実行〕）すら邪道みたいなアレがありますよね。[^2]
[^2]: 業界の Windows 以外 のOSへの愛が深い方々からよく聞く……。彼らにとっては、そもそもGUIが邪道。（個人的には楽ならなんでもOK）
そんなときはショートカット(.lnk)を作り、プロパティに「ショートカット キー」という項目があるため、そこでお好きなキーボード ショートカットを割り当てられます。
**A** の場合は、そのショートカットをそのまま使えます。
**B**／**C** の場合でもバッチファイル(.bat)を指定したショートカット(.lnk)を作り、それに対して割り当てればOKです。
![20200801_ps1act_lnkkey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683056/9ad49bf9-61b7-1942-7ab1-144e8b5776a0.png)