しばたテックブログ

気分で書いている技術ブログです。

PowerShellからコマンドプロンプトを呼んだ時にちょっとだけ便利にする方法

需要は少ないと思いますが、地味に便利な方法です。

はじめに

突然ですが質問です。
下の画像は何のプログラムを起動していると思いますか?

f:id:stknohg:20160527120253p:plain

正解はPowerShellコンソールから起動したコマンドプロンプト(cmd.exe)でした。

f:id:stknohg:20160527120320p:plain

Process Explorerで見るとこんな感じになっています。

f:id:stknohg:20160527120342p:plain

よく見るとプロンプト左のPSの部分が無いので違いがわかります。

PowerShellからコマンドプロンプトを呼んだ時にちょっと便利にする方法

普段PowerShellのコンソールを使っていて調査などで一時的にコマンドプロンプトを使うことがあると思います。

PowerShellからコマンドプロンプトを起動すると上図の様になり、パッと見で自分が作業してるのがPowerShellコンソールなのかコマンドプロンプトなのか見分けが付かなくなります。

この状態でたまーにコマンドプロンプトなのにPowerShellのコマンドを実行してしまうことがあったりして、まあ大して実害はないのですが地味に嫌な気分になりますw

そんな時は以下のコードをプロファイルに仕込むと少しだけ便利になります。

# PowerShellからコマンドプロンプトを呼んだ際のプロンプト文字列をカスタマイズ
$ENV:PROMPT = "PS(CMD) `$P`$G"

コマンドプロンプトのプロンプトに表示される文字列はPROMPT環境変数で設定することができます。
このため、PowerShellを起動したときにこの環境変数を変更してやるとPowerShellからコマンドプロンプトを呼び出した時だけプロンプトに表示する文字列を変えることができるわけです。

仕込みを入れるとPowerShellからコマンドプロンプトを起動した場合以下の様になり、

f:id:stknohg:20160527121712p:plain

プロンプトの文字列がPS(CMD) ...と変わっていることがわかります。
この表示であれば最初のよりは大分わかりやすいかと思います。

【おまけ】PowerShellをネストして実行した場合にちょっとだけ便利にする方法

本エントリの趣旨からは外れるのですが、私の場合PowerShellからPowerShellをネストして呼び出すこともたまにあるので以下のファンクションを使ってプロンプトにネストの段数を表示させたりもしています。
雑なコードなのでpowersehll.exe → cmd.exe → powershell.exeみたいな呼び出しをした場合は対応できませんが、それなりに使えています。

#
#   現在のPowerShell.exeのネストを取得します。
#   環境によっては Get-WmiObject を Get-CimInstance に変えると良い感じになると思います。
#
function Get-PowerShellNest()
{
    $Nest = 0
    $ParentPID = (Get-WmiObject -Class Win32_Process -Property ParentProcessId -Filter "ProcessId = $PID").ParentProcessId
    $Parent = Get-WmiObject -Class Win32_Process -Property Name, ProcessID, ParentProcessId -Filter "ProcessId = $ParentPID"
    while( $Parent.Name -eq "powershell.exe" )
    {
        $Nest += 1
        $ParentPID = $Parent.ParentProcessId
        $Parent = Get-WmiObject -Class Win32_Process -Property Name, ProcessID, ParentProcessId -Filter "ProcessId = $ParentPID"
    }
    return $Nest
}

#
#   Promptファンクションをオーバーライドします。
#
$Nest = $null
function prompt()
{
    if( $null -eq $Nest )
    {
        $Nest = Get-PowerShellNest
        $NestValue = ""
        if( $Nest -gt 0 )
        {
            $NestValue = "({0})" -F $Nest
        }
        # PowerShellからCmd.exeが呼ばれた際にプロンプト文字列をカスタマイズするための設定
        $ENV:PROMPT = "PS{0}(CMD) `$P`$G" -F $NestValue
    }
    # プロンプト文字列を変更
    return "PS{0} {1}> " -F $NestValue, (Get-Location)
}

実行結果はこんな感じになります。

f:id:stknohg:20160527122744p:plain

Windows 10でのNTPサーバーの指定方法

最近お仕事で使っているPCにもWindows 10化の波がきており、NTPサーバーの設定をしようとしたらUIがガラッと変わって面倒なことになっていたので備忘録を兼ねてメモっておきます。

GUIでの設定方法

Windows 10でタスクトレイの時刻から日付と時刻の設定を選択すると、

f:id:stknohg:20160525192009p:plain


【2017/07/13追記】
最新のWindows 10だとタスクバーを右クリックしないと日付と時刻の設定が出なくなってしまいました...

f:id:stknohg:20170713191606p:plain

f:id:stknohg:20170713191617p:plain

【追記ここまで】


以下の様に新しい日付と時刻の設定ダイアログが表示され、こいつにはNTPサーバーを指定するところがありません...

f:id:stknohg:20160525192131p:plain

ここからNTPサーバーを指定するには、このダイアログを下までスクロールさせて関連設定日付、時刻、地域の追加設定をクリックしてコントロールパネルを起動し、

f:id:stknohg:20160525192333p:plain

そこから日付と時刻の設定を選択、

f:id:stknohg:20160525192510p:plain

すると従来の日付と時刻の設定ダイアログが表示されるのでインターネット時刻タブからNTPサーバーの指定をすることができます。

f:id:stknohg:20160525192601p:plain

f:id:stknohg:20160525192634p:plain

率直に言ってかなり面倒なことになっています。

楽な設定方法

流石にこれは辛すぎるのでもう少し楽にできないか調べました。

従来の日付と時刻の設定ダイアログの実体はtimedate.cplファイルですのでコマンドプロンプトやPowerShellから

PS C:\> timedate.cpl

と打てば一発で日付と時刻の設定ダイアログを呼び出しNTPサーバーの設定をすることができます。

f:id:stknohg:20160525193003p:plain

これなら我慢できるレベルですね。

コマンドでの設定方法

さらに楽してすべてコマンドでやりたい場合はw32tmコマンドが使えます。

w32tmコマンドは昔からあるコマンドで使い方も変わっていません。
残念ながら今に至るまでこのコマンドを代替するPowerShell Cmdletは出ておらず、使えそうなPowerShellモジュールも無さげです。
なのでWindows 10でも頑張ってw32tmコマンドを使っていきます。

NTPサーバーを指定する場合はw32tm /configコマンドを以下の様な感じで実行すればOKです。
パラメーターの詳細はググればいくらでも出てきますので本エントリでは触れません(

w32tm /config /update /manualpeerlist:"time.windows.com,0x9" /syncfromflags:manual

時刻同期はw32tm /resyncコマンドで可能です。

w32tm /resync

設定値を確認する場合は、w32tm /query /statusw32tm /query /configurationコマンドが使えます。

w32tm /query /status
w32tm /query /configuration

ただし、w32tmコマンドからNTPサーバーの指定をするとインターネット時刻設定ダイアログの画面表示と実際の設定値が同期しないので注意が必要です。

ダイアログの画面表示はレジストリHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Serversの内容を基に設定されていますので、同期させたい場合はこのキーを適切に設定しする必要があります。
0から始まる連番のキーがダイアログのコンボボックスに表示されるNTPサーバーのリストになり、既定のキーにリストから選択したNTPサーバーの番号を設定します。

本エントリでは具体的な手順にまで触れませんが、頑張れば何とかできるレベルだと思いますので同期させたい場合は気合いでなんとかしてください。

はてなから"シンタックス・ハイライト機能で対応してほしい言語"を聞かれたのでPowerShellを追加してください。お願いします。

お題「シンタックス・ハイライト機能で対応してほしい言語」

developer.hatenastaff.com

何でもはしませんけど何卒よろしくお願いします。
PowerShell 1.0のリリースから今年で10周年とキリもよいので何卒よろしくお願いします。


【2016/07/01追記】

対応していただけた様です。
はてな様ありがとうございます。これでブログを書くのが捗ります。

matarillo.hateblo.jp


以下余談というか愚痴。

言語に対する熱い思いをお待ちしています。

とのことなのですが、コレ、言語に対する情熱を書き綴ってそれでも対応してもらえなかったらお前の情熱が足りなかったからだって扱いにされるんですかねぇ...

個人的には新機能を導入する際の評価基準に感情を持ち込むのはちょっと微妙なんじゃないかって気がしております。
該当言語のグループのユーザー数やカテゴリ付きのブログ投稿数とかもう少し客観的な指標をベースに要望数を加味した方が良い気がします。

あと私の要望を出す動機は情熱というよりもブログを書いてて圧倒的に不便だからという方が強いのでなかなかお題に沿う事を書けない感じです…

こんなこと書くと機能追加してもらえないかもしれませんが思ってしまったので仕方ないですね。