3件のコメント

PowerShell上でコマンドを実行する場合の注意点(式モードとコマンドモード)

今回はPowerShell上でコマンドを実行する場合の注意点に関してです。PowerShell上で色々な作業を行う便利さに慣れてくると、コマンドプロンプトは全く使わずにPowerShell上で作業を完結させるようになってきます。が、このときにちょっとした落とし穴があります。

私がはまったのはwbadminコマンドの利用時でした。wbadminコマンドはPowerShellのコマンドレットではない、純粋なコマンドプロンプト上で動作するプログラムです。Windows Server 2008のバックアップを行うことができます。

PowerShell上からwbadminコマンドを実行しようとしたところ以下のような現象が発生しました。「きちんと入力しているのに、文法ミスと言われてしまう」というものです。

 1: PS C:\Windows\System32> wbadmin start systemstatebackup -backuptarget:f:

 

 2: wbadmin 1.0 - バックアップ コマンド ライン ツール

 

 3: (C) Copyright 2004 Microsoft Corp.

 

 4:

 

 5:

 

 6: エラー - オプション: backuptarget の値がありません。以下の使用法を参照してください。

 

 7:

 

 8: 使用法: WBADMIN START SYSTEMSTATEBACKUP

 

 9:     -backupTarget:{ボリューム名}

 

 10:     [-quiet]

 

 11:

 

 12: 指定されたオプションに基づいてシステム状態のバックアップを実行します。

 

 13:

 

 14: -backupTarget   バックアップの記憶域の場所です。記憶域のドライブ文字が

 

 15:                 必要です。

 

 16:

 

 17: -quiet          ユーザー プロンプトなしでコマンドを実行します。

 

 18:

 

 19: 例:

 

 20: WBADMIN START SYSTEMSTATEBACKUP -backupTarget:f:

 

例のところに書かれているオプションをそのままコピー&ペーストしても動きません!原因がわからずかなり悩んでしまいました。しかも、全く同じコマンドをコマンドプロンプト上で実行すると正常に動作するのです。

結局原因はPowerShellの「式モード」と「コマンドモード」の違いにありました。結局以下のように入力すればうまく動くことがわかりました。

 1: wbadmin start systemstatebackup "-backuptarget:f:"

 

原因は-bakuptarget:f:という文字列をPowerShellに直接入力してみるとわかります。

 1: PS C:\Windows\System32> -backuptarget:f:

 

 2: 単項演算子 '-' の後に式が存在しません。

 

 3: 発生場所 行:1 文字:2

 

 4: + -b <<<< ackuptarget:f:

 

このようにPowerShellが”-“という文字を単項演算しとして認識してしまい、それが原因でコマンドとして成立していなかった、というわけです。

「式モード」と「コマンドモード」

PowerShellでは「式モード(expression mode)」と「コマンドモード(command mode)」の2つがあります。詳細は以下のリンク先の辺りをご確認ください。(#私自身まだきちんと整理できていません。整理できたらわかりやすく書こうと思います。)

まとめ

今回の件のまとめです。

  • 通常のDosのコマンドとその引数をそのまま記述した場合、それは式モードで解釈される
  • 特に特別な文字等が含まれない場合にはそれはそのまま実行される(計算式なら実行される、Dosコマンドなら実行される)
  • 特別な意味を持つ文字が含まれる場合には「計算」されてしまう
  • 「計算」されることを防ぐにはダブルクォーテーションで囲うなりして、「文字列」として認識させる必要がある。
子供3人。家族優先。都内SIer勤務。Windows系中心のインフラよりの何でも屋。脱原発。 Microsoft MVP for Cloud and Datacenter Management.

3件のコメント

  1. こんにちは。
    現在コマンドモードについて調べているので、ここの実例は興味深いです。
    しかし、残念ながら「コマンドモード」と「式モード」の違いがエラーの原因ではありません。

    ”よく分からなかったらエスケープ(” か ‘を使って)する” がこういう問題にかんする一番簡単な対処法です。

  2. もうひとつコメントしておくと、最初のエラーについても、backuptaraget オプション自体は wbadmin に認識されているけれど、その引数が存在しないというエラーに見えます。
    先ほどの test 関数の結果と合致していると思います。
    ご参考までに。

  3. 行等に”-“があれば単項演算子と解釈されるのは当然かもしれませんが、コマンドレット等の後に”-“が来る場合には基本的にそのまま渡されると思います。

    以下の関数でテストしてみました。

    function test {
    $args
    }

    test start systemstatebackup -backuptarget:f:
    start
    systemstatebackup
    -backuptarget:
    f:

    test start systemstatebackup “-backuptarget:f:”
    start
    systemstatebackup
    -backuptarget:f:

    “:”には特殊な意味があるので、それによりコマンドモードではあるけれど別々の引数と解釈されてしまったのかもしれません。
    http://www.itlab51.com/?p=5503

    式モードとコマンドモードの存在、引数の扱いに注意が必要なのは参考になりました。
    ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。