9
8

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 5 years have passed since last update.

Power shell を使おうぜ☆(^~^)<その1>

Last updated at Posted at 2019-02-23

見たことがない人もいる

会社のWindows PCは、PCでできること に制限がかかっていて、
自宅PC にフリーソフトをインストールして バリバリ使っている人に比べて
デフォルトに近い状態の PC しか見たことがない人もいる。
それも 隣の人のPCも、客先のPCも制限がかかっているのだから、世界中のPCがそんなもんだと思うのも無理ない。

逆に わたしは 制限がかかっている PC があることを知らず、
UAC(ユーザーアクセス制御) が出てきて .bat ファイルが実行できないPCが
あることを知らず runas したり、権限を昇格させたり いろいろするはめになる。

グローバルポリシーを設定できる管理者と、制限のかかったPCの中間ぐらいに 開発部 があったりする。
せっかく作ったスクリプトが 他のPCでは動かない、という 制限 を頭に入れてから 取り組んでほしい。

マルチ プラットフォーム

Microsoft は Power shell に .bat を オーバーラップ(そのまま使えるようにする意味だが 習慣が異なる部分でつまづくのは自力で乗り越えろ)させ、
.NET Framework をマルチ プラットフォームに書き直した .NET Core に差し替えたことで
Windowsユーザーを Linux にもそのまま 持っていけるように狙っているようだ……、何かの記事で読んだ。

Node.jsを使ってマルチプラットフォームで動くように Webサーバーを作っても
Windows Server 2016 で OSのリスタート時に タスク スケジューラーから .bat を叩く部分だけ Windows/Linux で切り分けていて めんどうだったので .ps1 に書き直すことを試そうとしたりする。
本当にうまくいくのか 知らないが……☆(^~^)

ダブルクリックして起動しようぜ

2015年 12月 24日 PowerShell スクリプトファイル(.ps1)をダブルクリックしても実行されないとお嘆きのあなたへ

Windows 10 を使っているとする。
Power shell の拡張子は .ps1 なんで、 hello-world.ps1 という空ファイルを作って
ダブルクリックしてみろだぜ☆(^~^)

メモ帳で 空のテキストファイル が開くだろう。
こんなことでは Power shell を使い始めようという気にはならない。

[Windows] + [R] と打鍵して regedit を検索しろだぜ。
レジストリーエディターが出てくる。

v コンピューター
  v HKEY_CLASSES_ROOT
    v Microsoft.PowerShellScript.1
      v Shell
        v 0
        v Edit
        v Open

というのがあることを目視確認する。

0 をクリックすると

名前 種類 データ
MUIVerb REG_EXPAND_SZ @"%systemroot%\system32\windowspowershell\v1.0\powershell.exe",-108

というのがあれば、 PowerShell のバージョン1.0 が使えることが分かる。古い……。

次は Shell をクリックし、

名前 種類 データ
(規定) REG_SZ Open

名前の (規定) をダブルクリック。 [値のデータ(v)]テキストボックスに Open と入っているが、
0 に書き換えて[OK]をクリックしろだぜ。

レジストリーエディターは閉じろだぜ。

hello-world.ps1 ファイルをダブルクリックしてみろだぜ☆(^~^)
今度は Power Shell が起動する。

Windows Power Shell ISE を使おうぜ

Visual Studio Code にも Power shell エクステンションはあるんだが、使いやすい方でいいだろう。

Windows 10 には最初から アイス(ISE) が入っている。
Power Shell を使う、と決めたら アイス は普段使うソフトになるので、
タスクバーにピン留めしておくといいだろう。

バッチ(.bat)ファイルのように、コマンドプロンプトを開いて打鍵して……、とか やらなくなる。
アイスをずっと開いておく。

ローカルPCでは ユーザー・ホームに最初居る。

PS C:\Users\むずでょ>

バーチャル ホストでも ユーザー・ホームに最初居る。

PS X:\>

とりあえず 知らないドライブ にいたら社内環境依存だ、ググっても出てこない。知ってるドライブ に行けだぜ。

# スクリプトの置いてあるディレクトリへ移動
PS C:\Users\むずでょ> cd $PSScriptRoot

# 現在のディレクトリを確認
PS C:\Users\むずでょ> pwd

Path
----
PS C:\Users\むずでょ

実行権限を設定しようぜ

アイスが使えるようになったら、使っていこう。

アイスは、 アイコンをダブルクリックするのではなく、右クリックして [管理者として実行(A)] を使って実行する。

PS C:\Users\むずでょ> Get-ExecutionPolicy -List

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       Undefined

PS C:\Users\むずでょ> Get-ExecutionPolicy
Restricted

カレントユーザーの実行ポリシーは未設定、わたしは制限されている。
まずは制限を解除したい。

# 確認ダイアログが出てくるので [はい] で進める。
PS C:\Windows\system32> Set-ExecutionPolicy RemoteSigned

PS C:\Windows\system32> Get-ExecutionPolicy -List

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    RemoteSigned

これで、ローカルPCの Power shell のスクリプトは証明書なしで実行できるし、
メールなどインターネットからダウンロードした Power shell のスクリプトは 証明書あり なら
実行できるようだぜ。

じゃあ アイスは一回閉じろ。管理者権限なしで開き直せだぜ。

Path にくせがある

Copy-Item -Recurse の振舞

C:\
    

パソコンには、フロッピーディスクを差し込む穴である Aドライブ、Bドライブ があり、
ハードディスクを内蔵している高価なPCは ハードディスクが Cドライブ だ、
という意味でドライブは C から始まるが、
バーチャルホストも当たり前になってくると URL の方でやりたくなる。
ドライブが頭にあっても 同じ アルファベット で始まるが ホストが違う、とか出てきて 状況説明がめんどくさい。

この パス を最短ステップでどう説明できるだろうかと、現場で 1分 ぐらいで実践するはめになることがある。
バッチファイルは ローカルPC で実行される、という説明をするために
ローカルPCとは何か、PCだと思っている「鉄のケース」の中には何が入っているのか、
ドライブとは 円盤が回転することであり……、と ろくろ を回すジェスチャーをする人になる。
ヒマがあれば UNC も自習しろだぜ。頭に \\ が付いている、ネットワークにつながっている Windows でよく見かけるやつだぜ。

C:\
    apple\
        banana.txt

という階層で、ファイルがあるとする。Power shell では、

C:\apple

C:\apple\

では意味が違うケースと出会う。
URLでは、末尾に \ が付いていようと、付いていまいと ブラウザが判別してくれるが、
Power shell では
ディレクトリーをコピーしようとしたとき、
宛先のディレクトリを置き換えるのか、宛先のディレクトリの中にコピーするのか、
ぐらいの違いが出てくる。

8パターンぐらいあって 暗記するのも面倒なので
動きがおかしいと思ったら その場で 動作確認しよう。

次の記事にわたしの考えをまとめておいた。
何かだぜだぜ言っているタイトルがめんどくさい(略)

コンパイラの考え方が役に立つ

Power shell が有ったって、仕事がなければ 何の足しにもならないし、
しかも Power shell が役に立つような 仕事 でなければ 何の足しにもならない。

仕事の方を Power shell に合わせるなんて 本末転倒 ではないか、というと
Power shell に合わせた仕事は 全自動化 されるんで 末節自動 であり 正しいPCとの付き合い方だぜ。

良い例も無いんで とりあえず 手順書を書いて、1つにまとめる 状況をやってみる。
いまどき Git Hub を使って README.md を書くのも慣れてるだろ。
Markdown(マークダウン)形式で手順書を書こう。というか Qiita も Markdown だ。

Visual Studio Code で Market Place から Markdown All in One をインストールしているものとする。
[Ctrl]+[Shift]+[P] で Markdown: Print current document to HTML を選ぶと、同じディレクトリに HTML ファイルが自動的に出力されるようにしておけだぜ。

(というか VS code に Power shell をインストールしていれば、 [Ctrl]+[Shift]+[`] で Power shell が起動する)

C:\kifuwarabe\
    README.md

仮にこんなディレクトリ構成とする。ここで わざわざ、

C:\kifuwarabe\
    -- META\
        kifuwarabe-doc\
            img\
                icon\
                    folder-small.png
            README.html
            README.md
        kifuwarabe-doc#make.ps1

というフォルダー構成に変換し、 kifuwarabe-doc#make.ps1 をダブルクリックすると

C:\kifuwarabe\
    -- META\
        kifuwarabe-doc\
            img\
                icon\
                    folder-small.png
            how-to-setup.html
            how-to-setup.md
            README.html
            README.md
    docs\
        kifuwarabe-doc\
            img\
                icon\
                    folder-small.png
            how-to-setup.html
    README.html
    README.md    

のように展開するプログラムを考えてみる。
.md ファイル以外をディレクトリごとコピーして、README だけ外に出す形だ。

「同じものをコピーするだけ なんて つまらない」 かもしれないが、
手順書というものが 「同じものをコピーするだけ」 の場面がいかに多いかと言えば
賢明な読者諸君なら HTMLには ハイパーリンク があることを思い出すと
大元を一元化し、コピー配布を自動化することが いかに便利か 端々まで一瞬ですべて見通せたと思う。

つまり、

C:\
    kifuwarabe\
        -- META\
            kifuwarabe-doc\
    task-scheduler\
        -- META\
            task-scheduler-doc\
    microsoft-apps\
        -- META\
            microsoft-apps-doc\

のように 手順書の大元を 物別 に作っておき、あとは Power shell を使って

C:\kifuwarabe\
    docs\
        kifuwarabe-doc\
        task-scheduler-doc\
        microsoft-apps-doc\

のように1つに まとめて、ハイパーリンクでつなげだぜ。

フォルダー数が多い!」「1つのファイルにまとめろ!」という上司の下で働いていれば、転職しよう。転職先は 外資系か、零細企業がいいだろう。 日本の大企業、中小企業は 情シス が作ったルールを守る側に回るだろうから、ルール作りから考えて作業する側には回れないだろう。

スクリプトを書き始めよう

cls
cd $PSScriptRoot
cd ..
pwd

こう書くと、.ps1 ファイルがあった上のディレクトリに移動する。じゃあ、次のように書けば……。

cls
cd $PSScriptRoot
cd ..
pwd

# Trailing slash.
$product = (Get-Location).Path + "\"
$original = $product + "-- META\kifuwarabe-doc\"

# Trailing NOT slash.
$deployment = $product + "docs\kifuwarabe-doc"

echo "Product: $product"
echo "Original: $original"
echo "Deployment: $deployment"

まだ説明していない書き方もバンバン使う。次のような出力になるはず。

Path                                           
----                                           
C:kifuwarabe
Product: C:\kifuwarabe\
Original: C:\kifuwarabe\-- META\kifuwarabe-doc\
Deployment: C:\kifuwarabe\docs\kifuwarabe-doc

ここでファイルパスが間違っていると、ディレクトリを消し飛ばしたり、知らないところにディレクトリが作られたりして まずい。よく目視確認しよう。
ここで、末尾に スラッシュ \ が付いているか、付いていないかで結果が異なる。

ひとまず、 $original が示すディレクトリを、 $deployment に丸ごとコピーすることを考えよう。

Copy-Item $original $deployment -Recurse

これで丸ごとコピーはやってくれるが、もう1回実行したときに、「既に存在します」とか言われて 失敗してしまう。
何度でも実行できるように リサイクル(Recycle)な形にしておきたい。

リサイクルとは 捨てたものを再び使うこと ではなく、何度でも捨てれることだ。
そのために必要なことは、 $deployment ディレクトリの中には 捨てられて困るものは置かないことだ。
それを実現するためには docs ディレクトリは リサイクルさせられます、というルール、習慣を周知、徹底させることが必要だが、
誰だって、知らなければ docs ディレクトリの中のファイルを編集して、いつの間にかオートマティックに消されてしまう。
ルール、習慣の周知徹底という手段は 悲観的に考えて、実現できない。できないことを、やろうと言うのは、ゲームが下手なプレイヤーだ。

それは置いておいて ひとまず さっきのコードの頭に、

# Recycle.
if (Test-Path $deployment) {
    Remove-Item $deployment -Recurse
}

Copy-Item $original $deployment -Recurse

ディレクトリがあれば、そのディレクトリを消すという3行を追加しておけば、このプログラムは何度でも実行できるようになる。

  • kifuwarabe-doc.ps1 ファイルを別のディレクトリに移動したり
  • $deployment ディレクトリをそもそも間違えて指定していたり

しなければ無事に動く。ところで ゲームが上手いプレイヤーなら、

  • 「有料」というラベルを貼っておく
  • プラス・マイナスのドライバーで開けられないネジ穴をしている
  • 信じられやすい噂話を広めて、真実は隠す

など 心理的なテクニックで 場を制圧するので、

exec\
    Windows-System.bat
    E012X201U931.call
    X1909a91c190[8e23]000d#ewoa.ewio.ada

ディレクトリ名も docs を止めて exec にしたり、
怪しげな 空ファイル を置いておくのも手だろう。中身には般若心経でもランダム生成しておけばいい。

ただ、プロジェクトによっては どのディレクトリにどのようなファイルが置いてあって パーミッションの設定まで必要なこともあるので この手法は一般的には使えない。

docs\
最初に読んでください.html

また、docs のディレクトリの外に 最初に読んでください.html を置いておく。
README.html という名前のファイルをダブルクリックする習慣はない。
しかし 最初に読んでください.html でも 読む習慣はない。
そもそも ドキュメントを読む習慣がない。
そして「ドキュメントは読まないから必要はない」の半年後に「今すぐドキュメントをください」のミドルレンジ連打がくるので、実装をドキュメント化するというより、概要だけ かいつまんだ メモ書き を入れておくと 半年後に助かる。

フィルターで ファイルを選り分けよう

ただ、今のままだと すべてのファイルを丸ごとコピーしてしまうので、 -Exclude を使って コピーしなくていいファイルを 拡張子 で弾こう。

$excludeArray = @("*.md", "*.pu")
Copy-Item $original $deployment -Recurse -Exclude $excludeArray

例えば 上記のように書けば 拡張子が .md と、 .pu のファイルはコピーされない。
-Include もあるらしいが、動きが思ったのと違ったので -Exclude ばっかり使っている。

1度書いたプログラムは使い回そうぜ。

プログラムに慣れていると、1度書いたプログラムは、使いまわしたくなる。
Power shell にも function という機能がある。

<#
 # さっき書いたプログラムを、function という書き方にしておく。
 #>
<#
 # ドキュメント作成。
 # $pro - product.
 # $ori - original.
 # $dep - deployment.
 #>
function Copy-Doc($pro, $ori, $dep) {
    # Recycle.
    if (Test-Path $dep) {
        Remove-Item $dep -Recurse
    }

    $excludeArray = @("*.md", "*.pu")
    Copy-Item $ori $dep -Recurse -Exclude $excludeArray
}

# 一度書いた function を使っている。
Copy-Doc $product $original $deployment

他のプログラム言語と違って Power shell は コマンドラインなんで、丸かっこを使ったり、カンマで区切ったりしない。

いくつものプログラムから使われるプログラムは、別ファイルにしようぜ。

Powershell > スクリプトを複数ファイルで実装する方法 > .(ドット)で別スクリプトを読込む

さっきの function を切り抜いた、新しいファイルを作る。

C:\kifuwarabe\
    -- META\
        document.ps1

Power shell 自体、オブジェクト指向ではないので ファイル名の付け方がむずかしいところだ。

document.ps1
<#
 # ドキュメント作成。
 # $pro - product.
 # $ori - original.
 # $dep - deployment. Trailing NOT slash.
 #>
function Copy-Doc($pro, $ori, $dep) {
    # Recycle.
    if (Test-Path $dep) {
        Remove-Item $dep -Recurse
    }

    $excludeArray = @("*.md", "*.pu")
    Copy-Item $ori $dep -Recurse -Exclude $excludeArray
}

切り分けたので、もう片方の .ps1 は、

kifuwarabe-doc#make.ps1
cls
cd $PSScriptRoot
cd ..
pwd

# Trailing slash.
$product = (Get-Location).Path + "\"
$original = $product + "-- META\kifuwarabe-doc\"

# Trailing NOT slash.
$deployment = $product + "docs\kifuwarabe-doc"

echo "Product: $product"
echo "Original: $original"
echo "Deployment: $deployment"

. "-- META\document.ps1"
Copy-Doc $product $original $deployment

読みやすくなった。
同じプログラムは 何度もコピー貼り付けするより、
1つのライブラリにして 色々なプログラムから 使い回す方が、
バグを見つける機会が増えるし、修正アップデートしていけば どんどん 不具合が減っていく。

大企業のプロジェクト仕事では こういう知見は相手にされないから、早く転職しよう。

// 書きかけ

9
8
2

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
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?