🦋

[PowerShell]文字コードと管理者権限を判定しウィンドウタイトルを変更

2024/02/06に公開

概要

日本語のWindows OSでPowerShellを使用する場合、文字コードの規定値が複雑で実行するとコマンドによっては文字化けしてしまう。なんてことがよくあります。
現状の設定値が把握しやすいようウィンドウタイトルに“PowerShellの各文字コードの設定”と“管理者として実行しているかの情報”を追加できるFunctionを作成してみました。

この記事のターゲット

  • Windows ユーザーの方
  • PowerShell ユーザーの方
  • PowerShell の文字コードをウィンドウのタイトルで把握したい方

環境

OSのバージョン

Windows 10 Pro環境

Get-WmiObjectコマンド
PS C:\Users\"ユーザー名"> Get-CimInstance CIM_OperatingSystem

SystemDirectory     Organization BuildNumber RegisteredUser SerialNumber            Version
---------------     ------------ ----------- -------------- ------------            -------
C:\WINDOWS\system32              19045       XXXXX          00000-00000-00000-AAAAA 10.0.19045
                                             ^^^^^          ^^^^^ ^^^^^ ^^^^^ ^^^^^
                                             ↑マスク       ↑マスク

PS C:\Users\"ユーザー名">

PowerShell

PowerShell 5.x(PSEdition: Desktop)

$PSVersionTable - PowerShell 5.x
PS C:\Users\"ユーザー名"> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.3930
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.3930
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1


PS C:\Users\"ユーザー名">

PowerShell 7.x(PSEdition: Core)

$PSVersionTable - PowerShell 7.x
PS C:\Users\"ユーザー名"> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.3.10
PSEdition                      Core
GitCommitId                    7.3.10
OS                             Microsoft Windows 10.0.19045
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

PS C:\Users\"ユーザー名">

Windows ターミナル(Microsoft Store版)

winget list コマンドでバージョン確認
PS C:\Users\"ユーザー名"> winget list --id '9N0DX20HK701'
名前               ID           バージョン  ソース
----------------------------------------------------
Windows ターミナル 9N0DX20HK701 1.18.3181.0 msstore
PS C:\Users\"ユーザー名">

対応方法

作成したFunction

さっそく作成したPowerShellのコードを紹介します。コードの説明は後述します。

PowerShell ウィンドウタイトル変更するFunction
# 管理者として実行しているか確認(Trueの場合、“管理者として実行”していると判断)
Function isAdminPowerShell {
    $win_id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $win_principal = new-object System.Security.Principal.WindowsPrincipal($win_id)
    $admin_permission = [System.Security.Principal.WindowsBuiltInRole]::Administrator
    return $win_principal.IsInRole($admin_permission)
}
# 現在、設定している文字コードを取得
Function GetPsCharcode {
    [System.String[]]$ps_charcode = @()
    $ps_charcode = @(
        # コンソールに出力する文字コードの規定値
        ($PSDefaultParameterValues['*:Encoding']),
        # PowerShellから外部プログラムに渡す文字エンコードの設定
        ($global:OutputEncoding).WebName,
        # PowerShellのコンソールに出力する文字エンコードの設定
        ([console]::OutputEncoding).WebName
    )

    return $ps_charcode
}
# PowerShellウィンドウのタイトル変更
Function ChangeWindowTitle {
    # 区切り文字の設定
    [System.String]$pos1 = '|'
    [System.String]$pos2 = ';'

    # 現在のタイトルを取得
    [System.String]$title = $Host.UI.RawUI.WindowTitle
    [System.String]$base_title = $title

    # すでにこのFunctionでタイトル変更している場合、一番左にある元のタイトル名のみ抽出
    [System.String[]]$title_array = $title.Split($pos1)
    if ($title_array.Length -ne 0) {
        $base_title = ($title_array[0]).TrimEnd()
    }

    # 現在の文字コードを取得
    [System.String[]]$ps_charcode = GetPsCharcode

    # 管理者として実行しているかにより設定するタイトル名を分岐
    [System.String]$change_title = $base_title
    if (isAdminPowerShell) {
        # PowerShellを管理者として実行している場合
        $change_title = $base_title + " $pos1 " +
                        "DefaultParameter='$($ps_charcode[0])'" + " $pos2 " +
                        "GlobalEncoding='$($ps_charcode[1])'" + " $pos2 " +
                        "ConsoleEncoding='$($ps_charcode[2])'" + " $pos2 " +
                        "#Administrator"
    }
    else {
        # していない場合
        $change_title = $base_title + " $pos1 " +
                        "DefaultParameter='$($ps_charcode[0])'" + " $pos2 " +
                        "GlobalEncoding='$($ps_charcode[1])'" + " $pos2 " +
                        "ConsoleEncoding='$($ps_charcode[2])'" + " $pos2 " +
                        "#Not_Administrator"
    }
    $Host.UI.RawUI.WindowTitle = $change_title

    # 完了メッセージ
    Write-Host 'タイトルに“文字コード”と“管理者権限の有無”の情報を追加しました。' -ForegroundColor Cyan
}

コードの説明(作成したFunctionの流れ)

  1. 現在のタイトル名を取得

    • (すでにこのFunctiondでタイトル変更済みの場合)元のタイトル名のみを抽出
  2. 文字コードを取得

    • $PSDefaultParameterValues['*:Encoding']
      コンソールに出力する文字コードの規定値。
      仮にこの設定値をutf8にした場合、Out-FileコマンドレットのパラメーターEncodingの規定値がutf8となる。
    • $global:OutputEncoding
      PowerShellから外部プログラムに渡す文字エンコードの設定。
      PowerShellのコマンドからPythonなどの外部プログラムで文字列を表示する際に使用される。
    • [console]::OutputEncoding
      PowerShellのコンソールに出力する文字エンコードの設定。
      PowerShellのCLIウィンドウやWindows ターミナルなどで文字列を表示する際に使用される。
  3. PowerShellを管理者として実行しているか確認

  4. 取得した情報を使用しタイトルを変更する

    • 管理者として実行している場合
      元のタイトル + 区切り文字1() + 文字コード1(DefaultParameter='xxx') + 区切り文字2(;) + 文字コード2(GlobalEncoding='xxx') + 区切り文字2(;) + 文字コード3(ConsoleEncoding='xxx') + 区切り文字2(;) + #Administrator
    • 管理者として実行していない場合
      元のタイトル + 区切り文字1() + 文字コード1(DefaultParameter='xxx') + 区切り文字2(;) + 文字コード2(GlobalEncoding='xxx') + 区切り文字2(;) + 文字コード3(ConsoleEncoding='xxx') + 区切り文字2(;) + #Not_Administrator

PowerShellバージョン毎の文字コードの規定値

PowerShell 5.x の場合

確認方法 - PowerShell 5.x

  • PowerShell 5.x のコンソールで確認
    名前を指定して実行で“powershell”
    (⊞スタートメニュー → Windows PowerShell フォルダー → Windows PowerShell)

    実行ファイルの場所: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

文字コードの規定値 - PowerShell 5.x

  • $PSDefaultParameterValues['*:Encoding']
    `` ← 空文字で設定なし
    ※ 設定がないので各コマンドレットの規定値が設定される。
      こちらの公式サイトによるとPowerShellの文字エンコードの規定値はutf8NoBOMとの事。
  • $global:OutputEncoding
    us-ascii
  • [console]::OutputEncoding
    shift_jis

PowerShell 7.x の場合

確認方法 - PowerShell 7.x

  • PowerShell 7.x のコンソールで確認
    名前を指定して実行で“pwsh”
    [⊞スタートメニュー → PowerShell フォルダー → PowerShell 7 (x64)]

    実行ファイルの場所: C:\Program Files\PowerShell\7\pwsh.exe

  • Windows ターミナルで確認
    名前を指定して実行で“wt”
    (⊞スタートメニュー → ターミナル)

    実行ファイルの場所: C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.18.3181.0_x64__8wekyb3d8bbwe\WindowsTerminal.exe

文字コードの規定値 - PowerShell 7.x

PowerShell 7.x のコンソール と Windows ターミナル 2つで確認すると同じ結果だった為、
結果をまとめて表示。

  • $PSDefaultParameterValues['*:Encoding']
    `` ← 空文字で設定なし
    ※ 設定がないので各コマンドレットの規定値が設定される。
      こちらの公式サイトによるとPowerShellの文字エンコードの規定値はutf8NoBOMとの事。
  • $global:OutputEncoding
    utf-8
  • [console]::OutputEncoding
    shift_jis

実際にタイトル変更のFunction実行してみる

Function実行 - PowerShell 5.x コンソール

管理者として実行した場合 - PowerShell 5.x コンソール

  • タイトル変更前
    PowerShell 5.x - 管理者権限あり - タイトル変更前
  • タイトル変更後
    PowerShell 5.x - 管理者権限あり - タイトル変更後

通常起動した場合 - PowerShell 5.x コンソール

通常起動した場合、つまりは管理者として実行していないパターンでFunctionを実行。

  • タイトル変更前
    PowerShell 5.x - 管理者権限なし - タイトル変更前
  • タイトル変更後
    PowerShell 5.x - 管理者権限なし - タイトル変更後

Function実行 - PowerShell 7.x コンソール

管理者として実行した場合 - PowerShell 7.x コンソール

  • タイトル変更前
    PowerShell 7.x - 管理者権限あり - タイトル変更前

  • タイトル変更後
    PowerShell 7.x - 管理者権限なし - タイトル変更後

    タイトル名が長く見切れてしまったので、コマンドでタイトル名を取得してみました。

    見切れたウィンドウのタイトル名を取得
    PS C:\Users\"ユーザー名"> Get-Process | Where-Object {$_.MainWindowTitle} | Select-Object Name, MainWindowTitle | Format-Table -AutoSize -Wrap
    
    Name                 MainWindowTitle
    ----                 ---------------
    pwsh                 Administrator: C:\Program Files\PowerShell\7\pwsh.exe | DefaultParameter='' ; GlobalEncodi
                        ng='utf-8' ; ConsoleEncoding='shift_jis' ; #Administrator
    
    PS C:\Users\"ユーザー名">
    

通常起動した場合 - PowerShell 7.x コンソール

通常起動した場合、つまりは管理者として実行していないパターンでFunctionを実行。

  • タイトル変更前
    PowerShell 7.x - 管理者権限なし - タイトル変更前

  • タイトル変更後
    PowerShell 7.x - 管理者権限なし - タイトル変更後

Windows ターミナル

管理者として実行した場合 - Windows ターミナル

  • タイトル変更前
    Windowsターミナル(PowerShell 7.x) - 管理者権限あり - タイトル変更前
  • タイトル変更後
    Windowsターミナル(PowerShell 7.x) - 管理者権限あり - タイトル変更後

通常起動した場合 - Windows ターミナル

通常起動した場合、つまりは管理者として実行していないパターンでFunctionを実行。

  • タイトル変更前
    Windowsターミナル(PowerShell 7.x) - 管理者権限なし - タイトル変更前

  • タイトル変更後
    Windowsターミナル(PowerShell 7.x) - 管理者権限なし - タイトル変更後

Windows ターミナルでウィンドウタイトルを表示する方法

初期状態のWindows ターミナルでは ウィンドウタイトルがなくタブのタイトルに反映されます。
タブのタイトルだけだと確実に見切れてしまうので、Windows ターミナルのウィンドウタイトルを表示する設定を行いました。

  1. Windows ターミナルの設定を開く
    Windows ターミナル - 設定
  2. 設定の項目「外観」を選択する
  3. “タイトル バーを非表示にする”をオンからオフに変更
    • オン状態
      Windows ターミナル - 設定 - 外観 - タイトル バーを非表示にする が オンの状態
    • オフ状態
      Windows ターミナル - 設定 - 外観 - タイトル バーを非表示にする が オフの状態
  4. 保存ボタンを押す
  5. Windows ターミナルを再起動

Windows ターミナル再起動後、ウィンドウタイトルが表示されました。
ウィンドウタイトルが表示された後、タイトル名変更のFunctionを実行し見切れず表示されている事を確認。
Windows ターミナルでウィンドウタイトルを表示し長いタイトル名を設定

参考情報

現在のセッションが管理者権限で実行しているか確認する方法

https://tex2e.github.io/blog/powershell/check-is-admin

まとめ

  • PowerShell CLIでコマンドをガシガシ実行する方は、タイトルに文字コードが見えると便利かも
    ただ、タイトル名を変更後に文字コードを設定しなおした場合、
    その都度、Functionを実行しないといけないのは不便。もう少し改良の余地があると思います。

  • このFunctionをProfileに設定しPowerShell起動時に実行すると再実行も簡単にできて便利かも

関連記事

https://haretokidoki-blog.com/pasocon_powershell-startup/
https://zenn.dev/haretokidoki/articles/7e6924ff0cc960

GitHubで編集を提案

Discussion