Home > Windows にまつわる e.t.c.

作成した PowerShell 関数のモジュール化とオンラインインストール/オンライン更新の実装


PowerShell で作成した関数は、モジュールとして組み込むと PowerShell のプロンプトで簡単に使えるようになりますし、配布可能なツールとして使用できます

ただ、GitHub でスクリプトを管理していると、モジュールのインストールや更新するためにリポジトリの Clone/Pull が必要だったりするので、意外とハードルが高いのが展開/更新時の悩みの種です

簡単に展開/更新するためには、オンラインインストールやオンライン更新が出来ると便利ですよね

今までモジュールのインストーラー作成までは断片的にコンテンツに書いていたので、オンライン更新も含めて新たにコンテンツにまとめます

 

手順としては、以下となります

・関数の作成(ここは解説飛ばします)
・モジュールの作成
・インストーラーの作成
・オンラインインストールの仕組みを実装
・オンライン更新の仕組みを実装

 

利用者は、以下の手順でインストールと更新をします

・スクリプト実行許可の設定(1回のみ)
・モジュールのオンラインインストール
・モジュールのオンライン更新

 

 

モジュールの作成

関数を作成し、debug も完了したら、GitHub 上にモジュールを作成します

モジュールを作成するリポジトリは、インターネットで https ダウンロードするので公開リポジトリにします

リポジトリ名は、モジュール名と同じにします
(モジュールはインストール単位なので、モジュール名と関数名は異なっていも問題ありません)

リポジトリ内に作成するモジュールは、「モジュール名.psm1」とし( BOM 付き UTF-8 )、作成した関数をコピペします

この「モジュール名.psm1」を、Profile のモジュールディレクトリにコビーすればモジュールのインストール完了です

以降は普通のコマンドレットと同様に使うことが出来ます

 

デフォルトのモジュール フォルダーは以下となります

Windows PowerShell 5.x C:\Users\<User Name>\Documents\WindowsPowerShell\Modules
PowerShell Core 6.0 以降 C:\Users\<User Name>\Documents\PowerShell\Modules

 

スクリプトでモジュール フォルダーの取得を書くとこうなります

$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

 

例えば、「hoge」というユーザー名で「TestModule.psm1」というモジュールを Windows PowerShell インストールする場合は、以下のようにします

モジュールファイル TestModule.psm1
モジュール フォルダー C:\Users\hoge\Documents\WindowsPowerShell\Modules\TestModule

 

 

インストーラーの作成

都度手動でモジュールをセットするのも面倒なので、汎用インストーラーとアンインストーラーを作りましょう

結論から言うと、こんな感じになります

インストーラー(install.ps1)

# モジュール名
$ModuleName = "<モジュール名>"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールを配置する Path
$NewPath = Join-Path $ModulePath $ModuleName

# ディレクトリ作成
if( -not (Test-Path $NewPath)){
    New-Item $NewPath -ItemType Directory
}

# モジュールのコピー
$ModuleFileName = Join-Path $PSScriptRoot ($ModuleName + ".psm1")
Copy-Item $ModuleFileName $NewPath

 

アンインストールは、モジュールディレクトリを削除すればいいので、こちらも汎用アンインストーラーが書けますね

アンインストーラー(uninstall.ps1)

# モジュール名
$ModuleName = "<モジュール名>"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールが配置されている Path
$RemovePath = Join-Path $ModulePath $ModuleName

# ディレクトリ削除
if( Test-Path $RemovePath ){
    Remove-Item $RemovePath -Force -Recurse
}

 

これで、リポジトリに置いた install.ps1 を実行すれば、モジュールのインストール/更新が出来ます

アンインストールも uninstall.ps1 を実行すれば完了です

 

 

オンラインインストールの仕組みを実装

オンラインインストールを実現するには、GitHub に置いたファイルをインターネット経由でダウンロードして、インストーラーを実行すれば良いことになります

GitHub に置いたファイルは、raw 形式で以下に公開されています

https://raw.githubusercontent.com/<GitHub名>/<リポジトリ名>/master/<ファイル名>

 

こいつをローカルにコピーします

コピー先はどこでも良いのですが、僕は Windows でも Linux でも必ず存在している Profile ディレクトを使っています

Profile ディレクトリは、Windows/Linmux 共通で「~」と表現できるので、こいつを使います

http ダウンロードは Invoke-WebRequest コマンドレットで出来ます

スクリプトで書くと以下のようになります

# ダウンロード
Invoke-WebRequest -Uri https://raw.githubusercontent.com/<GitHub名>/<リポジトリ名>/master/<ファイル名> -OutFile ~/<出力ファイル名>

 

オンラインインストーラーは、インストールに必要なファイルをローカルにダウンロードし、実行すれば良い事になります

インストール/アンインストールに必要なのは、以下3ファイルです

・モジュールファイル
・インストーラー
・アンインストーラー

 

これらをローカルにダウンロードして、インストーラーを実行すればオンラインインストールが出来ます

最後に不要になったファイルを削除すればスッキリ

 

OnlineInstall.ps1

# Online installer
# リポジトリ名とモジュール名は同一名にしている前提
# インストーラーは install.ps1 にしている前提
# アンインストーラーは uninstall.ps1 にしている前提

$ModuleName = "<モジュール名>"
$GitHubName = "<GitHub名>"

$Module = $ModuleName + ".psm1"
$Installer = "Install" + $ModuleName + ".ps1"
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"

# ダウンロード
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/$Module -OutFile ~/$Module
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/install.ps1 -OutFile ~/$Installer
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/uninstall.ps1 -OutFile ~/$UnInstaller

# インストーラー実行
& ~/$Installer

# 不要ファイル削除
Remove-Item ~/$Module
Remove-Item ~/$Installer

# オンラインインストーラー削除
Remove-Item ~/OnlineInstall.ps1

 

アンインストーラーもオンラインインストール対応にして、不要ファイルを削除するように更新します

アンインストーラー(uninstall.ps1)

# モジュール名
$ModuleName = "<モジュール名>"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールが配置されている Path
$RemovePath = Join-Path $ModulePath $ModuleName

# ディレクトリ削除
if( Test-Path $RemovePath ){
    Remove-Item $RemovePath -Force -Recurse
}

# オンラインインインストール対応
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"
if( Test-Path ~/$UnInstaller ){
    Remove-Item ~/$UnInstaller
}

 

このオンラインインストーラーをダウンロードして実行すれば良いので、以下コマンドを PowerShell プロンプトにコピペすればインストールが完了します

$ModuleName = "<モジュール名>"
$GitHubName = "<GitHub名>"
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/OnlineInstall.ps1 -OutFile ~/OnlineInstall.ps1
& ~/OnlineInstall.ps1

 

サンプル実装は以下のようになります

モジュール名 & リポジトリ名 TestModule
GitHub名 MuraAtVwnet

 

install.ps1

# モジュール名
$ModuleName = "TestModule"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールを配置する Path
$NewPath = Join-Path $ModulePath $ModuleName

# ディレクトリ作成
if( -not (Test-Path $NewPath)){
    New-Item $NewPath -ItemType Directory
}

# モジュールのコピー
$ModuleFileName = Join-Path $PSScriptRoot ($ModuleName + ".psm1")

Copy-Item $ModuleFileName $NewPath

uninstall.ps1

# モジュール名
$ModuleName = "TestModule"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールが配置されている Path
$RemovePath = Join-Path $ModulePath $ModuleName

# ディレクトリ削除
if( Test-Path $RemovePath ){
    Remove-Item $RemovePath -Force -Recurse
}

# オンラインインインストール対応
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"
if( Test-Path ~/$UnInstaller ){
    Remove-Item ~/$UnInstaller
}

OnlineInstall.ps1

# Online installer
# リポジトリ名とモジュール名は同一名にしている前提
# インストーラーは install.ps1 にしている前提
# アンインストーラーは uninstall.ps1 にしている前提

$ModuleName = "TestModule"
$GitHubName = "MuraAtVwnet"

$Module = $ModuleName + ".psm1"
$Installer = "Install" + $ModuleName + ".ps1"
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"

# ダウンロード
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/$Module -OutFile ~/$Module
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/install.ps1 -OutFile ~/$Installer
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/uninstall.ps1 -OutFile ~/$UnInstaller

# インストーラー実行
& ~/$Installer

# 不要ファイル削除
Remove-Item ~/$Module
Remove-Item ~/$Installer

# オンラインインストーラー削除
Remove-Item ~/OnlineInstall.ps1

インストールコマンド

$ModuleName = "TestModule"
$GitHubName = "MuraAtVwnet"
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/OnlineInstall.ps1 -OutFile ~/OnlineInstall.ps1
& ~/OnlineInstall.ps1

 

このオンラインインストーラーでインストールされる関数は「TestFunction」ですので、PowerShell プロンプトで、TestFunction をコマンドレットして使用できるようになります

アンインストールは、以下コマンドで出来ます

& ~/UnInstallTestModule.ps1

 

 

オンライン更新の仕組みを実装

オンライン更新は、スクリプトが更新されたらオンラインインストールを実行すれば良い事になります

スクリプトの更新の検知は、簡単にしたいので、バージョン管理ファイルを作成し、バージョン管理ファイルが更新(変更)されたオンラインインストールするようにします

仕組みとしては Vertion.txt をリポジトリに置いて、バージョンアップするごとにこのファイルを更新します
(僕は、バージョン管理ファイルにモジュールを更新した日時をセットするようにしています)

 

ローカルにバージョン管理ファイルをダウンロードしておき、内容が変更されたら更新されたと判断します

 

インストーラーにバージョンチェックファイルのダウンロードを追加します

install.ps1

# モジュール名
$ModuleName = "<モジュール名>"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールを配置する Path
$NewPath = Join-Path $ModulePath $ModuleName

# ディレクトリ作成
if( -not (Test-Path $NewPath)){
    New-Item $NewPath -ItemType Directory
}

# モジュールのコピー
$ModuleFileName = Join-Path $PSScriptRoot ($ModuleName + ".psm1")
Copy-Item $ModuleFileName $NewPath

# バージョンファイルのコピー
$Vertion = "Vertion" + $ModuleName + ".txt"
$VertionFileName = Join-Path $PSScriptRoot "Vertion.txt"

# ローカルインストール時のバージョンファイル
if( Test-Path $VertionFileName ){
    Copy-Item $VertionFileName ~/$Vertion
}

 

アンインストーラーにバージョン管理ファイルの削除を追加します

uninstall.ps1

# モジュール名
$ModuleName = "<モジュール名>"

# モジュール Path
$ModulePath = Join-Path (Split-Path $PROFILE -Parent) "Modules"

# モジュールが配置されている Path
$RemovePath = Join-Path $ModulePath $ModuleName

# ディレクトリ削除
if( Test-Path $RemovePath ){
    Remove-Item $RemovePath -Force -Recurse
}

# オンラインインインストール対応
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"
if( Test-Path ~/$UnInstaller ){
    Remove-Item ~/$UnInstaller
}

# バージョン管理ファイル削除
$Vertion = "Vertion" + $ModuleName + ".txt"
if( Test-Path ~/$Vertion ){
    Remove-Item ~/$Vertion
}

 

オンラインインストーラーにバージョン管理ファイルを追加します

OnlineInstall.ps1

# Online installer
# リポジトリ名とモジュール名は同一名にしている前提
# インストーラーは install.ps1 にしている前提
# アンインストーラーは uninstall.ps1 にしている前提
# バージョン管理ファイルは vertion.txt にしている前提

$ModuleName = "<モジュール名>"
$GitHubName = "<GitHub名>"

$Module = $ModuleName + ".psm1"
$Installer = "Install" + $ModuleName + ".ps1"
$UnInstaller = "UnInstall" + $ModuleName + ".ps1"
$Vertion = "Vertion" + $ModuleName + ".txt"

# ダウンロード
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/$Module -OutFile ~/$Module
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/install.ps1 -OutFile ~/$Installer
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/uninstall.ps1 -OutFile ~/$UnInstaller
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/Vertion.txt -OutFile ~/$Vertion

# インストーラー実行
& ~/$Installer

# 不要ファイル削除
Remove-Item ~/$Module
Remove-Item ~/$Installer

# オンラインインストーラー削除
Remove-Item ~/OnlineInstall.ps1

 

 

作成している関数に、バージョンチェックオプションを追加して、バージョンチェックオプションが指定されたら、バージョン管理ファイルをチェックし、バージョンが更新されていたらオンライン インストール コマンドを実行します

関数 TestFunction に実装する場合は以下のようにします

function TestFunction([switch]$VertionCheck){

    # バージョンチェックとオンライン更新
    if( $VertionCheck ){
        $ModuleName = "<モジュール名>"
        $GitHubName = "<GitHub名>"

        $Module = $ModuleName + ".psm1"
        $Vertion = "Vertion" + $ModuleName + ".txt"
        $VertionTemp = "VertionTemp" + $ModuleName + ".tmp"

        $Update = $False

        if( -not (Test-Path ~/$Vertion)){
            $Update = $True
        }
        else{
            # 現在のバージョン
            $LocalVertion = Get-Content -Path ~/$Vertion

            # ローカルにリポジトリに置いてあるバージョン管理ファイルをダウンロードし読み込む
            Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/Vertion.txt -OutFile ~/$VertionTemp
            $NowVertion = Get-Content -Path ~/$VertionTemp
            Remove-Item ~/$VertionTemp

            # バージョン チェック
            if( $LocalVertion -ne $NowVertion ){
                $Update = $True
            }
        }

        if( $Update ){
            Write-Output "最新版に更新します"
            Write-Output "更新完了後、PowerShell プロンプトを開きなおしてください"
            Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/OnlineInstall.ps1 -OutFile ~/OnlineInstall.ps1
            & ~/OnlineInstall.ps1
            Write-Output "更新完了"
            Write-Output "PowerShell プロンプトを開きなおしてください"
        }
        else{
            Write-Output "更新の必要はありません"
        }
        return
    }

    # 以下本来の処理

}

 

これで -VertionCheck オプションを指定すると、バージョン チェックをしをし、必要に応じてモジュール更新がされます

 

 

利用者の操作

スクリプト実行許可の設定(1回のみ)

利用者側では、PowerShell のスクリプト実行を許可する必要があります(Windows PowerShell の場合)

スクリプト実行許可は、PowerShell プロンプトで「Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force」とすれば良いのですが、管理権限を持っていない場合は、ログインユーザーのみ実行許可を与えます

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force

 

モジュールのオンラインインストール

スクリプト実行許可設定が出来たら、オンラインインストールコマンドをコピペすれば、モジュールがインストールされます

$ModuleName = "<モジュール名>"
$GitHubName = "<GitHub名>"
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/OnlineInstall.ps1 -OutFile ~/OnlineInstall.ps1
& ~/OnlineInstall.ps1

 

先に紹介したサンプルだと、以下になります

$ModuleName = "TestModule"
$GitHubName = "MuraAtVwnet"
Invoke-WebRequest -Uri https://raw.githubusercontent.com/$GitHubName/$ModuleName/master/OnlineInstall.ps1 -OutFile ~/OnlineInstall.ps1
& ~/OnlineInstall.ps1

 

モジュールのオンライン更新

モジュールの更新は、関数のオプションに -VertionCheck を指定します

サンプルをインストールした場合は、以下のようにオプションを指定します

TestFunction -VertionCheck

 

 

今回使用したモジュールは、以下リポジトリで公開しています

https://github.com/MuraAtVwnet/TestModule

git@github.com:MuraAtVwnet/TestModule.git

 

 

参考情報

PowerShell の関数をモジュールとしてインストールする
https://www.vwnet.jp/windows/PowerShell/2019101401/InstallModule.htm

 

自作 PowerShell モジュールのインストーラー
https://www.vwnet.jp/Windows/PowerShell/2024032201/PowerShellModuleInstaller.htm

 

管理権限を持っていないユーザーで PowerShell スクリプトを実行する
https://www.vwnet.jp/Windows/PowerShell/2020072901/SetExecutionPolicy.htm

 

 

back.gif (1980 バイト)

home.gif (1907 バイト)

Copyright © MURA All rights reserved.