2010年1月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
無料ブログはココログ

最近のトラックバック

最近のコメント

2010年1月 6日 (水)

.NETなどのコマンドラインの引数で引用符をエスケープする。(その2)

RunAsコマンドは、.NETではありませんが、RunAs.exeをメモ帳で開くと、CommandLineToArgvWという文字列が見えます。なので標準シンタクスです。

例えば、notepad "a b"なら、

RunAs ... "notepad \"a b\""

か、

RunAs ... "notepad """a b""""

と書けますが、notepad "a < b"ならどうするか?

cmd.exeの遅延展開を使っても、cmd.exeの制御文字をエスケープできます。

set "x=RunAs ... ""notepad \""a < b\"""""
if !errorlevel! == %errorlevel% (!x:""^=^"!) else cmd /v:on /c !x:""^^="!

set "x=コマンドライン"の中の"を2倍個します。外側の"で制御文字は無効です。
遅延展開で、""を半減して実行します。遅延展開後の制御文字は無効です。
遅延展開が有効なら、その場で実行し、無効ならサブシェルで有効にして実行します。

2010年1月 5日 (火)

.NETなどのコマンドラインの引数で引用符をエスケープする。

.NETのエスケープ法は、\"(\と1個の")または"""(3個の")ですが、cmd.exeのエスケープ法は""(偶数個の")なので、合いません。

そこで、.NETとcmd.exeの両方でエスケープする方法ですが、これは、PowerShell.exeのように簡単には行きません。

しかし、PowerShell.exeを使えば、なんとか可能です。

PowerShell ".\ファイル '引数...';"

ここで、'引数...'内の、

"の左に隣接する\を2倍個の\でエスケープします。

"を\""(\と2個の")または"""(3個の")でエスケープします。ただし、奇数のときは、cmd.exeのエスケープのため、+1して偶数にします。

\"によるエスケープはC以来の伝統。"""によるエスケープはundocumented。

このエスケープ法は共に、.NETというより、Win32APIのCommandLineToArgvW()の仕様です。つまり、MSの標準シンタクスです。

2010年1月 3日 (日)

PowerShell.exe -command "スクリプト" で引用符をエスケープする。(その2)

そこで、PowerShell.exeとcmd.exeの両方でエスケープする方法です。

"スクリプト"内では、

"の左に隣接する\を2倍個の\でエスケープします。

"を\""(\と2個の")でエスケープします。

あるいは、

"を"""(3個の")でエスケープします。ただし、奇数のときは、cmd.exeのエスケープのため、+1して偶数にします。

PowerShell.exeは、"スクリプト"を評価するときに、3n個の"をn個の"に変換して、端数個の"を切り捨てるようです。
ただし、最初の端数2個の"は、例外的に1個の"に切り上げて変換するようです。

単純さで、\""がお勧めです。

例えば、write-host "a""b";というスクリプトは、

PowerShell "write-host \""a\""\""b\"";"

PowerShell "write-host """"a""""""b"""";"

のように書けます。

2010年1月 2日 (土)

PowerShell.exe -command "スクリプト" で引用符をエスケープする。

PowerShell "スクリプト"で、PowerShellのone linerがバッチファイル内に書けます。

ただ、PowerShellスクリプトをそのまま"スクリプト"内に書くと、引用符が悪さします。

エスケープしようにも、簡単には行きません。

PowerShell.exeのエスケープ法は、\"(\と1個の")または"""(3個の")ですが、cmd.exeのエスケープ法は""(偶数個の")なので、合いません。

例えば、"a;b"という文字列は、

PowerShell "write-host \"a;b\";"

PowerShell "write-host """a;b""";"

で、うまく行きますが、"a<b"という文字列は、

PowerShell "write-host \"a<b\";"

PowerShell "write-host """a<b""";"

で、失敗します。

<>|&などのcmd.exeの制御文字は、奇数個目の"~偶数個目の"でエスケープされ、偶数個目の"~奇数個目の"でエスケープされません。

2009年12月29日 (火)

バッチファイルで、「管理者として実行」されているか?を判定する。

もし、Vista以降か、.NET Framework が入っていれば、

vbc IsUserAnAdmin.vb

Module Module1
Declare Function IsUserAnAdmin lib "shell32.dll" () As Integer
Public Function Main() As Integer
Return IsUserAnAdmin
End Function
End Module

IsUserAnAdmin.cmd

IsUserAnAdmin.exe
if %errorlevel%==0 echo「管理者として実行」されている
if %errorlevel%==1 echo「管理者として実行」されていない

もし、Windows7以降か、PowerShell 2.0 が入っていれば、

IsUserAnAdmin.ps1

Add-Type -Language VisualBasic @"
Public Class Shell32
Declare Function IsUserAnAdmin Lib "shell32.dll" () As Integer
End Class
"@
Exit [Shell32]::IsUserAnAdmin()

あるいは、バッチファイル内の1行で

PowerShell "Add-Type -Language VisualBasic 'Public Class Shell32:Declare Function IsUserAnAdmin Lib ""shell32.dll"""" () As Integer:End Class';Exit [Shell32]::IsUserAnAdmin();"

2009年12月27日 (日)

バッチファイルからコンソールウィンドウのサイズを変える。

もし、PowerShellが入っていれば、

PowerShell "$host.UI.RawUI.WindowSize=New-Object System.Management.Automation.Host.Size 1,1"

2009年12月22日 (火)

長いファイル名を用いた Start コマンドの使用

http://support.microsoft.com/kb/186613/ja

start "長いファイル名" [引数...]

が失敗する話は、

start "" "長いファイル名" [引数...]

が定石ですが、あまり好きになれません。

これだと、コンソールアプリの場合に、タイトルが空になります。

そこで、新案。

start \\.\"フルパス" [引数...]

start \\?\"フルパス" [引数...]

start file://"フルパス" [引数...]

\\.\はネットワークに接続してないときはよいが、していると遅いので、非推奨です。

file://でも引数が使えるんですね。推奨します。

バッチの中では、

start %~d1"%~pnx1" [引数...]

コマンドプロンプトでは、

for %1 in ("長いファイル名") do start %~d1"%~pnx1" [引数...]

2009年12月21日 (月)

コマンドラインから、UACダイアログを出して「管理者として実行」する。

以下のショートカットファイルを作成します。

RunAsAdmin.lnk
リンク先 : %SystemRoot%\system32\cmd.exe /c start "コマンド プロンプト"
作業フォルダ : なし
実行時の大きさ: 最小化
詳細設定 : 管理者として実行

使用法は、

RunAsAdmin.lnk アプリ [引数...]

ショートカットファイルなどをRunAsAdmin.lnkにドロップしてもおk。

ところで、「管理者として実行」すると、作業フォルダが %SystemRoot%\system32 に勝手に変更されます。

そんなときは、

RunAsAdmin.lnk /d 作業フォルダ アプリ [引数...]

例えば、作業フォルダを引き継いでコマンドプロンプトを開くなら、

RunAsAdmin.lnk /d "%cd%" cmd

デスクトップでコマンドプロンプトを開くなら、

RunAsAdmin.lnk /d "%HOMEDRIVE%%HOMEPATH%\Desktop" cmd

あるいは、作業フォルダを指定したショートカットファイルなどをRunAsAdmin.lnkにドロップしてもおk。

作業フォルダを決め打ちにするなら、RunAsAdmin.lnkのリンク先に指定します。

%SystemRoot%\system32\cmd.exe /c start "コマンド プロンプト" /d 作業フォルダ

2009年12月20日 (日)

バッチファイルで現プロセスIDを調べる。

もし、PowerShellが入っていれば、

for /f %%i in ('powershell "foreach($p in (get-wmiobject win32_process -filter processid=$pid)){$ppid=$p.parentprocessid;}foreach($p in (get-wmiobject win32_process -filter processid=$ppid)){$p.parentprocessid;}"') do set PID=%%i
echo %PID%

コマンドプロンプトで現プロセスIDを調べるだけなら、

powershell "get-wmiobject win32_process -filter processid=$pid | foreach-object {$_.parentprocessid;}"

2009年12月19日 (土)

バッチファイルからコンソールウィンドウのタイトルを取得する。

titleコマンドでは、変更・設定はできても、取得ができません。

もし、PowerShellが入っていれば、

for /f %%i in ('powershell "$Host.UI.RawUI.WindowTitle"') do set title=%%i
echo %title%

より以前の記事一覧