読者です 読者をやめる 読者になる 読者になる

tech.guitarrapc.cóm

C#, PowerShell, Unity, Cloud, Serverless Technical Update and Features

PowerShell で Profile を利用して スクリプトの自動読み込みをしてみよう

PowerShellを起動したら、特定のコマンドを自動実行してほしい。

時にはこのような希望があるかと思います。 いわゆる、bashなどでいう bash_profile 的なモノですね。 PowerShell にも profile な考えは存在していますので、紹介しましょう。

参考

MSDN先生は偉大です。

Windows PowerShell Profiles

現在のProfile確認

powershell や powershell_ise.exe を起動して、以下のコマンドを入力すると読み込まれているProfileがわかります。

$profile

しかしここに出るのは、現在のProfileで自分のユーザーでのみ適用されるものです。 もう少し詳細を見てみましょう。

Profileと適用対象

Profileは、適用対象応じて以下のつのタイプが存在します。

例えばそのユーザーのPowerShellとPowerShell_iseで、共通のprofileを読み込みたい場合は、 $env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1を作成して、処理を記述します。

ユーザー単位

  • 基底パス : $env:USERPROFILE\Documents\WindowsPowerShell
  • パス例 : C:\Users\hoge\Documents\WindowsPowerShell
適用対象 PowerShell PowerShell ISE 両方
ファイル PowerShell_profile.ps1 Microsoft.PowerShellISE_profile.ps1 Profile.ps1

システム単位

  • 基底パス : $PSHOME
  • パス例 : C:\Windows\System32\WindowsPowerShell\v1.0
適用対象 PowerShell PowerShell ISE 両方
ファイル PowerShell_profile.ps1 Microsoft.PowerShellISE_profile.ps1 Profile.ps1

適用可能なprofileパスの確認

上記の適用可能なパスは、以下のコマンドで確認が可能です。

$profile | Get-Member | where MemberType -eq NoteProperty

結果は、PowerShell.exe と PowerShell_ise.exe で微妙に異なります。

  • PowerShell.exe における profile
PS C:\Windows\system32> $profile | Get-Member | where MemberType -eq NoteProperty | Format-List


TypeName   : System.String
Name       : AllUsersAllHosts
MemberType : NoteProperty
Definition : System.String AllUsersAllHosts=C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1

TypeName   : System.String
Name       : AllUsersCurrentHost
MemberType : NoteProperty
Definition : System.String AllUsersCurrentHost=C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1

TypeName   : System.String
Name       : CurrentUserAllHosts
MemberType : NoteProperty
Definition : System.String CurrentUserAllHosts=C:\Users\acquire\Documents\WindowsPowerShell\profile.ps1

TypeName   : System.String
Name       : CurrentUserCurrentHost
MemberType : NoteProperty
Definition : System.String CurrentUserCurrentHost=C:\Users\acquire\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
  • PowerShell_ise.exe における profile
PS C:\Windows\system32> $profile | Get-Member | where MemberType -eq NoteProperty | Format-List

TypeName   : System.String
Name       : AllUsersAllHosts
MemberType : NoteProperty
Definition : System.String AllUsersAllHosts=C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1

TypeName   : System.String
Name       : AllUsersCurrentHost
MemberType : NoteProperty
Definition : System.String AllUsersCurrentHost=C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1

TypeName   : System.String
Name       : CurrentUserAllHosts
MemberType : NoteProperty
Definition : System.String CurrentUserAllHosts=C:\Users\acquire\Documents\WindowsPowerShell\profile.ps1

TypeName   : System.String
Name       : CurrentUserCurrentHost
MemberType : NoteProperty
Definition : System.String CurrentUserCurrentHost=C:\Users\acquire\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

権限に気を付けよう

いずれの Profileを読み込むにしても、.ps1 を読み込むための権限は必須です。

そのため、もし初めてPowerShellを起動する人は、以下のコマンドを管理者で実行しておくと Profileの.ps1を読み込み可能です。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

profile の作成

よくある紹介で、以下のコマンドでProfile を作成するというのがあります。

if (-not(Test-Path $profile))
{
    New-Item -Path $profile -ItemType file
}

しかし$Profile とやると、Powershell.exePowerShell_ise.exe によって、生成されるProfileが変わることがわかります。

そのため、特にPowershell.exePowerShell_ise.exeで分ける必要がない場合は、以下でprofile.ps1を作るほうが楽かもしれません。

if (-not(Test-Path $profile.CurrentUserAllHosts))
{
    New-Item -Path $profile.CurrentUserAllHosts -ItemType file
}

Profile でスクリプトを読ませる

作成した、Profileに以下を入力すると、 PowerShell.exe と PowerShell_ise.exe の両方で起動時に文字が表示することがわかります。

Write-Host ("Hello PS Profile from {0}" -f $PSCommandPath) -ForegroundColor Green

f:id:guitarrapc_tech:20161008011121p:plain

スクリプトの統合

Profileはいくつも種類があります。

と、いうことは各Profile にスクリプト設定が分散する可能性があります。

そのため、どの Profileでも、直接Profile に書くのではなく、読み込むファイルを実行するスクリプトへ流して読み込み先を統合するのも一つの手です。

例えば、私がやる場合は、Profileには以下の一文だけにします。

  • ここでは、Profileに読み込ませるスクリプトへのパスをdot-sourceで読み込むように指示しているだけです。
$loadscript = "${env:PSCustomScripts}\Profile\PowerShellEnvironment.ps1"
if (Test-Path $loadscript)
{
    .$loadscript
}

あとは、PowerShellEnvironment.ps1に以下を入力して、autoloadフォルダにおいた.ps1だけdot-sourceで読み込ませます。

$psdir="$(env:PSCustomScripts)"
Get-ChildItem $psdir\autoload | where Extension -eq ".ps1" | %{.$_}

Write-Host "Custom PowerShell Environment Loaded" -ForegroundColor Cyan

このようにすることで、自動読み込みする.ps1を統合、管理しやすくできます。

Profile モジュールはいりますか?

Profileの 作成、テスト、ファイル取得、削除、バックアップ、編集 をするためのModule を作ったのでよろしければどうぞ。

Git-Hub / guitarrapc/PS-Profile

最後に

Profile をうまく使えば、 Windows Server 2012 などで、毎回Import-Module 特定のWindowsFeature をする必要がなくなります。

ぜひ活用されるとPowerShellが楽になるかと思います。