次の方法で共有


batファイルからPowerShell引数にspaceのあるパスを渡したい

質問

2018年3月26日月曜日 8:47

お世話になります。

batファイルを使って、Program Files内でファイルをコピー&ペーストするのが目的で

スクリプトを作ったのですが、powershellの引数設定がうまく行かず悩んでいます。

管理者権限を回避するため、2つのbatファイルを用意し、一方のファイルから

powershellのStart-Processを使ってもう一方のファイルを呼び出してコピーを行う方法で

以下のように記述しています。

<file1.bat>

powershell.exe -Command Start-Process .\file2.bat  '%1 %2'  -Verb Runas

<file2.bat>

copy %1 %2

2つの引数に指定するパスにスペースが含まれていない場合は、これでうまく行くのですが

「Program Files」にはスペースが含まれているため、「C:\Program」の所までで第一引数と認識されてしまい

うまくパスを渡せません。

ダブルクォーテーションで囲む、「&」を付ける、バッククォート(`)で無効化・・・等、ネットで調べられる限りの工夫をしてみましたが

いずれも効果がないかエラーになるかのどちらかで、正解は見つかりませんでした。

何かうまい方法はないでしょうか。よろしくお願い致します。

すべての返信 (8)

2018年3月26日月曜日 11:10

powershell -Command "Start-Process .\file2.bat '"""%1""" """%2"""'" -verb Runas

copy "%1" "%2"

でどうでしょう。

// エスケープやらなんやらで大変なことになってますなぁ。


2018年3月27日火曜日 1:02

Hongliang様

回答ありがとうございます。

下記の通り記述してやってみましたが、うまくいきませんでした。

<file1.bat>

powershell -Command "Start-Process .\file2.bat '"""%1""" """%2"""'" -verb Runas

<file2.bat>

copy "%1" "%2"

<コマンドプロンプト>

方法1:file1.bat C:\Program Files\Test\test1.txt C:\Program Files\Test\test2.txt

方法2:file1.bat "C:\Program Files\Test\test1.txt" "C:\Program Files\Test\test2.txt"

方法1では、file1.bat実行時点で引数のパスがスペースで分割されてしまい、

方法2では、単なる文字列として認識されてしまう様です。


2018年3月27日火曜日 4:02 | 1 票

こんな感じかな…?

file1.bat

set bat2="""""%~dp0bat2.bat"""""
PowerShell -Command "Start-Process -Verb RunAs cmd.exe '/c %bat2% ""%1"" ""%2"""""'"

file2.bat

copy %1 %2

2018年3月27日火曜日 4:12 | 1 票

順に説明します。

「copy %1 %2」の引数 %1、%2が正しく分割されるためにはここで渡されるパス文字列は "" で括られている必要があります。つまり

.\file2.bat "%~1" "%~2"

でコマンドが起動される必要があります。次にPowerShellのコマンドレットStart-Processでこのようなプロセスを起動するには '' か "" で括られている必要があります。つまり

Start-Process .\file2.bat '"%~1" "%~2"'
Start-Process .\file2.bat "`"%~1`" `"%~2`""

どちらかですが、""で括る場合、 " を ` でエスケープする必要が生じるので '' の方が楽です。次にPowerShellのコマンドライン引数で上記コマンドレットを実行する方法ですが、コマンドライン引数解析で分割されてしまわないよう "" で括る必要があります。つまり

powershell.exe -Command Start-Process .\file2.bat "'\"%~1\" "%~2\"'"

とします。"" で括った場合の " を \ でエスケープする必要があります(コマンドライン引数のエスケープであり通常の ` エスケープとは異なります)。質問では通常のプロセス起動でなくRunAsとのことで、HKEY_CLASSES_ROOT\batfile\shell\runas\commandには

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

と登録されています。%*なので引数がそのまま引き継がれるはずなのですが、手元の環境ではなぜかbatファイルが起動されませんでした。仕方がないので cmd /c をもう一段はさみます。最終的に

powershell.exe -Command Start-Process cmd "'/c C:\path\to\file2.bat \"%~1\" \"%~2\"'" -Verb Runas

こうなります。カレントディレクトリが引き継がれないので file2.bat はフルパスで記述する必要があります。


2018年3月27日火曜日 8:34

このままですと、file2.bat に空白を含める事が出来ないので

powershell.exe -Command Start-Process cmd "'/c,\"C:\path\t o\file2.bat\" \"%~1\" \"%~2\"'" -Verb Runas

これでよろしいかと。


2020年12月9日水曜日 10:14

二つのバッチを一つにして

@echo off

:check_admin
openfiles >nul 2>&1
if errorlevel 2 goto :got_admin
if not errorlevel 1 goto :got_admin

:get_admin
setlocal
set args=/c call "%~f0" %*
set args=%args:'=''%
powershell.exe -Command Start-Process cmd.exe '%args:"=\"%' -Verb Runas
endlocal
exit

:got_admin
copy %1 %2

とか。


2020年12月18日金曜日 12:21

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2020

cmd と powershell は引用符の相性が悪いので、

file1.cmd

file2.lnk "%~f1" "%~f2"

file2.lnk ショートカットのリンク先

C:\Windows\System32\cmd.exe /c copy

プロパティで「管理者として実行」

使い方

file1.bat 相対パス可 相対パス可

または

file2.lnk フルパス必須 フルパス必須 


2020年12月18日金曜日 12:58

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2020 無理するなら、

file1.bat

powershell.exe -Command Start-Process cmd.exe  '/c copy \"%~f1\" \"%~f2\" '  -Verb Runas

バッチのrunasは関連付けに問題があるので、避けたほうがいい。