web-dev-qa-db-ja.com

「管理者として実行」がバッチファイルの現在のディレクトリを(ときどき)変更するのはなぜですか?

xcopyにするファイルと同じディレクトリにあるバッチファイルがあります。しかし、何らかの理由でファイルが見つかりません。

現在のディレクトリは常にバッチファイルが置かれている場所だと思いました。

管理者としてバッチファイルを実行します。これは、Windows 7 64ビットデスクトップコンピューターで発生します。

バッチファイル:

@ECHO OFF
XCOPY /y "File1.txt" "File2.txt"
PAUSE

エラー:

File not found - File1.txt
0 File(s) copied
14
mcu

コンテキストメニュー項目でバッチファイルを開始するときに現在の作業ディレクトリがどのディレクトリであるか(== --- ==)管理者として実行ユーザーアカウント制御によって異なります現在のユーザーの(UAC)設定。

これは、次の小さなバッチファイルC:\Temp\Test.batで説明できます。

@echo Current directory is: %CD%
@pause

で選択した場合ユーザーアカウント制御設定

デフォルト-プログラムがコンピューターに変更を加えようとしたときにのみ通知する

  • Windowsの設定を変更しても通知しない

管理者として実行を使用すると、Windowsはレジストリキーを使用します

HKEY_CLASSES_ROOT\batfile\Shell\runasuser\command

このレジストリキーには、バッチファイルを実行するためのデフォルトの文字列は含まれていません。代わりに、CLSID {ea72d00e-4960-42fa-ba92-7792a7944c1d}を含む文字列値DelegateExecuteがあります。

結果は、タイトルユーザーアカウント制御とテキストを含むダイアログウィンドウを開きます。

次のプログラムがこのコンピュータに変更を加えることを許可しますか?

プログラム名:Windows Command Processor
確認済み発行元:Microsoft Windows

ユーザーによる確認後、Windowsはコマンドライン RunAs で使用する場合と同様に、一時的に新しいユーザーセッションを開きます。

この新しいユーザーセッションでは、現在の作業ディレクトリは%SystemRoot%\System32です。デフォルトのキー文字列を使用して、Windowsレジストリで定義されたコマンドを実行します。

HKEY_CLASSES_ROOT\batfile\Shell\runas\command

それは:

%SystemRoot%\System32\cmd.exe /C "%1" %*

したがって、コンソールウィンドウはタイトルC:\ Windows\System32\cmd.exeと2行で開かれます。

Current directory is: C:\Windows\System32
Press any key to continue . . .

いずれかのキーを押すと、バッチ実行が終了してcmd.exeが終了し、ユーザーセッションが終了します。


ただし、ユーザーアカウント制御設定で選択した場合

いつ通知しないでください

  • プログラムがソフトウェアをインストールするか、コンピューターに変更を加えようとする

  • Windowsの設定を変更した

ユーザーがすでに昇格した権限を持っているため、動作は異なります。

現在、Windowsはコマンドを直接使用します

%SystemRoot%\System32\cmd.exe /C "%1" %*

キーのデフォルト文字列に従って

HKEY_CLASSES_ROOT\batfile\Shell\runas\command

現在のユーザーセッション。

結果は、タイトルもC:\ Windows\System32\cmd.exeのコンソールウィンドウを開きますが、ウィンドウには次のように表示されます。

Current directory is: C:\Temp
Press any key to continue . . .

この場合、別のユーザーセッションに切り替える必要がなかったため、親ファイルの現在の作業ディレクトリ(デスクトップとしてのWindowsエクスプローラー)がバッチファイルの実行に使用されます。


[〜#〜] pa [〜#〜] は彼の回答にすでに2つの可能な解決策を投稿していますが、これをここで少し改善して(二重引用符で囲んだディレクトリを含むpushd)および3つ目を追加します。

  1. pushdおよびpopdを使用して、現在のディレクトリをバッチファイルのディレクトリに変更します。

    pushd "%~dp0"
    %SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
    popd
    

    これはUNCパスでも機能します。これがUNCパスでも機能する理由については、コマンドプロンプトウィンドウpushd /?で実行してください。

  2. ソースと宛先の仕様でバッチファイルのディレクトリを使用:

    %SystemRoot%\System32\xcopy.exe "%~dp0File1.txt" "%~dp0File2.txt" /Y
    
  3. cdを使用して、作業ディレクトリをバッチファイルのディレクトリに変更します。

    cd /D "%~dp0"
    %SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
    

    コマンドインタープリターcmdはデフォルトで現在のディレクトリとしてUNCパスをサポートしないため、これはUNCパスでは機能しません。たとえば、 CMDは詳細については、現在のディレクトリとしてUNCパスをサポートしない

21
Mofi

エラーメッセージは非常に自明です。ファイル file1.txt 見つかりません。

ファイル名には絶対パスが含まれていないため、システムは現在のディレクトリでそのファイルを見つけようとします。現在のディレクトリにはこのファイルが含まれていません。

あなたの誤解は、現在のディレクトリではない batファイルを含むディレクトリだということです。これらは2つの無関係な概念です。

この2つのコマンドをbatファイルに追加すると、簡単に確認できます

echo BAT directory is %~dp0
echo Current directory  is %CD%

あなたはそれらが異なることに気付くことができ、最後のバックスラッシュが追加されるかどうかに微妙な違いがあることに気づくでしょう。

したがって、この問題に対処するには本質的に2つの方法があります

  1. 予想されるディレクトリと一致するように現在のディレクトリを変更するか、

    pushd %~dp0
    XCOPY /y "File1.txt" "File2.txt"
    popd
    
  2. またはコマンドでフルパスを指定します

    XCOPY /y "%~dp0File1.txt" "%~dp0File2.txt"
    
2
PA.

完全性と曖昧さのために、Windows 8.1で動作することが確認されており、文書化された機能に依存しているため、他の場所で動作することが予想される別の回避策を追加します。

runasコマンド定義キーを変更できます
HKEY_CLASSES_ROOT\batfile\Shell\runas\commandおよび
HKEY_CLASSES_ROOT\cmdfile\Shell\runas\command

%SystemRoot%\System32\cmd.exe /S /C "(for %%G in (%1) do cd /D "%%~dpG") & "%1"" %*

これにより、bat動詞、または「管理者として実行」メニューエントリをそれぞれ使用して開始すると、その包含ディレクトリでcmdまたはrunasファイルが開始されます。

元のコマンドへの追加が正確に行うこと:

  • cmd /Sは、コマンド文字列の/Cの後の最初と最後の(二重)引用符を取り除きます
  • for %%G in (%1) doは、単一のエントリである%1引数を列挙し、ループ本体の%%Gとして展開できるようにします。手紙は任意ですが、一部は「予約」される場合があります
  • %%~dpGd riveおよびp ath of %%Gに展開され、チルダは引用符を取り除きますif存在するため、明示的に追加し直します
  • cd /Dd riveとディレクトリの両方をその引数に変更し、最後に
  • &は、最初のコマンドの成功に関係なく、2番目のコマンド"%1" %*を実行します。

UNCパスもサポートするpushdを使用できますが、popdsystem32ディレクトリにスクリプトをランディングしますが、私が好きな動作ではありません。

exefileエントリでもこれを行うことができる必要がありますが、率直に言って、私はシステムでこれを試みるよりも、一貫性がない状態で暮らしたい、エラーが発生すると、多くの問題が発生する可能性があります。

お使いのオペレーティングシステムのセキュリティメカニズムを打ち負かしてください:)

1
Viktor Svub