メモ帳やコマンドプロンプトで制御文字(RS/US)を入力する。
メモ帳(などのGUI)では、右クリック、「Unicode制御文字の挿入」で、RSとUSが入力可能です。
RS ^^ ALT+30 001e{F5}
US ^_ ALT+31 001f{F5}
メモ帳やコマンドプロンプトでは、日本語キーボードでは、CTRL+^ やCTRL+_ では、^^や^_が入力できません。
代わりに、
^^ CTRL + SHIFT + 6/&
^_ CTRL + SHIFT + -/=
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 |
« 2009年12月 | トップページ | 2010年2月 »
メモ帳(などのGUI)では、右クリック、「Unicode制御文字の挿入」で、RSとUSが入力可能です。
RS ^^ ALT+30 001e{F5}
US ^_ ALT+31 001f{F5}
メモ帳やコマンドプロンプトでは、日本語キーボードでは、CTRL+^ やCTRL+_ では、^^や^_が入力できません。
代わりに、
^^ CTRL + SHIFT + 6/&
^_ CTRL + SHIFT + -/=
^[ や 001b{F5} などの特別な入力法を知らなくても使えます。
for /f %i in ('cmd /k prompt $e^<nul') do set {ESC}=%i
echo %{ESC}%
メモ帳で普通に見ると、制御文字が見えません。それはフォントのせいです。
以下のフォントにすると見えます。
FixedSys
System
Terminal
MS UI Gothic
これを設定で行うのは困難なようです。
なので、HTAでIEを監視して、IEを常に全画面表示(F11)で開きます。
IeMaximizer.hta
<head><title>IE Maximizer</title>
<script language=vbscript>
resizeTo 210,10
Set ies=CreateObject("Shell.Application").Windows()
setInterval "proc",1000
Sub proc
For Each ie In ies
If InStr(LCase(ie.FullName),"iexplore.exe") Then If ie.Left>0 Then ie.TheaterMode=True
Next
End Sub
</script>
</head>
これなら複数タブ状態でも効きます。
全画面表示(F11)=(ie.TheaterMode=True)≠(ie.Fullscreen=True)=(iexplore.exe -k)
HTAでIEを監視して、少なくとも1つは開くようにします。
IeOneOpener.hta
<head><title>IE 1 Opener</title>
<script language=vbscript>
resizeTo 210,10
Set ies=CreateObject("Shell.Application").Windows()
setInterval "proc",1000
Sub proc
For Each ie In ies
If InStr(LCase(ie.FullName),"iexplore.exe") Then Exit Sub
Next
open
End Sub
</script>
</head>
これを設定で行うのは困難なようです。
なので、HTAでIEを監視して、IEを常に疑似最大化(最大化の位置とサイズ)で開きます。
IeMaximizer.hta
<head><title>IE Maximizer</title>
<script language=vbscript>
resizeTo 210,10
Set ies=CreateObject("Shell.Application").Windows()
setInterval "proc",1000
Sub proc
For Each ie In ies
If InStr(LCase(ie.FullName),"iexplore.exe") Then
If ie.Left>0 Then
ie.Left=0
ie.Top=0
ie.Width=screen.availWidth
ie.Height=screen.availHeight
End If
End If
Next
End Sub
</script>
</head>
ただし、複数タブ状態では効かないようです。
代わりに、ExcelのOffice Clipboardを使う。
Clipbrd.vbs
Set Application=CreateObject("Excel.Application")
Application.Visible=True
Application.DisplayClipboardWindow=True
Application.UserControl=True
ファイルからファイルへ、例えば、UTF-8からUTF-7へ。
powershell "get-content utf8.txt -encoding utf8|set-content utf7.txt -encoding utf7"
powershell "get-content utf8.txt -encoding utf8|add-content utf7.txt -encoding utf7"
powershell "get-content utf8.txt -encoding utf8|out-file utf7.txt -encoding utf7"
フィルタで、例えば、UTF-8からUTF-7へ。
powershell "[console]::inputencoding=[text.encoding]::getencoding('utf-8');[console]::outputencoding=[text.encod
ing]::getencoding('utf-7');$input" < utf8.txt >utf7.txt
schtasksコマンドではできませんが、スクリプトからは可能です。
タスクの引数に、仮引数を、$(Arg0),$(Arg1),$(Arg2)...などと書いておけば、実引数に置き換えられます。
実引数に置き換わらなかった仮引数はそのまま残ります。
Set TaskService=CreateObject("Schedule.Service")
TaskService.Connect
Set Folder=TaskService.GetFolder("\")
Set Task=Folder.GetTask("hoge")
Task.Run "引数0"
VBScriptでは、String型の配列が作れないので渡せるのは1個の文字列です。
PowerShellなら、複数の文字列が渡せます。
$TaskService=New-Object -ComObject schedule.service
$TaskService.Connect()
$Folder=$TaskService.GetFolder("\")
$Task=$Folder.GetTask("hoge")
[String[]]$a="引数0","引数1","引数2"
$Task.Run($a)
Set TaskService=CreateObject("Schedule.Service")
TaskService.Connect
Set Folder=TaskService.GetFolder("\")
Set Task=Folder.GetTask("hoge1")
Task.Run Empty
schtasksコマンドとの違いは、
コンソールウィンドウが出ない。
引数が渡せる。
「ユーザーがログオンしているかときのみ実行する」場合は、表示して対話が可能です。
「ユーザーがログオンしているかどうかにかかわらず実行する」場合は、表示しての対話ができません。
標準入出力のコンソールアプリならリモートshellもどきで疑似的な対話処理が可能です。
shelld.cmdをタスクスケジューラで実行します。
call >"%~dp00"
tail -f "%~dp00"|(cmd 1>"%~dp01"
echo !!! enter CTRL+Z to terminate input service !!!>&2) 2>"%~dp02"
shell.cmdをコンソールから実行します。
@echo off
start /b tail -f "%~dp01"
start /b tail -f "%~dp02"
copy /y con "%~dp00"
echo exit>>"%~dp00"
sleep 2
echo exit>>"%~dp00"
sleep 2
call >"%~dp00" 1>"%~dp01" 2>"%~dp02"
sleep 2
for /f %%I in ('del "%~dp00" "%~dp01" "%~dp02"') do echo !!! enter CTRL+BREAK to terminate output srvices !!!
同じカレントディレクトリで2つのコマンドプロンプトを開き、
サーバ側で、
call >0
tail -f 0|cmd 1>1 2>2
クライアント側で、
start /b tail -f 1
start /b tail -f 2
copy /y con 0
ここでコマンドを入力すると、サーバ側で実行されて、結果がクライアント側に表示されます。
終了は、
exitでサーバのcmdを止める。
exitのエコーを確認したら何か入力してサーバのtailを止める。
^Zでcopyを閉じる。
^breakでtailの2つを止める。
ファイルシステムの更新日時は秒まであるのに、dirコマンドは分まで。:-(
仕方がないので、FSOかShellを使います。
fdir [ファイルまたはディレクトリ...]
@if(0)==(0) ECHO OFF
setlocal
set x=%*
if not defined x set x=*
FOR %%I IN (%x%) DO FOR /F "delims=" %%J IN ('CScript.exe //NoLogo //E:JScript %0 "%%~fI"') DO ECHO %%~aI %%J
GOTO :EOF
@end
var fso=new ActiveXObject('Scripting.FileSystemObject');
if(fso.FileExists(WScript.Arguments.Item(0))){
var File=fso.GetFile(WScript.Arguments.Item(0));
WScript.Echo(File.DateLastModified,File.Size,File.Name);
}
else if(fso.FolderExists(WScript.Arguments.Item(0))){
var Folder=fso.GetFolder(WScript.Arguments.Item(0));
WScript.Echo(Folder.DateLastModified,Folder.Size,Folder.Name);
}
sdir [ファイルまたはディレクトリ...]
@if(0)==(0) ECHO OFF
setlocal
set x=%*
if not defined x set x=*
FOR %%I IN (%x%) DO FOR /F "delims=" %%J IN ('CScript.exe //NoLogo //E:JScript %0 "%%~dpI" "%%~nxI"') DO ECHO %%~aI %%J
GOTO :EOF
@end
var Shell=new ActiveXObject('Shell.Application');
var Folder=Shell.NameSpace(WScript.Arguments.Item(0));
var FolderItem=Folder.Items().Item(WScript.Arguments.Item(1));
WScript.Echo(FolderItem.ModifyDate,FolderItem.Size,FolderItem.Name);
Shellだと、ディレクトリのサイズやショートカットの拡張子が出ません。
なのでFSOを推奨。
別のユーザーの「管理者として実行」するには、「別のユーザーとして実行」してから「管理者として実行」する必要があります。
ユーザ名をハードコードして、パスワードをプロンプトで与える場合、
RunAsUserAdmin0.cmd コマンド [引数...]
set x=%*
runas /user:user "powershell -command \"start-process 'cmd' '/c %x:"=\\\"%' -verb 'runas'\""
ユーザ名をハードコードして、パスワードをダイアログで与える場合、
RunAsUserAdmin1.cmd コマンド [引数...]
set x=%*
powershell -command "start-process 'powershell' '-command \"start-process ''cmd'' ''/c %x:"=\\\"%'' -verb ''runas''\"' -credential (get-credential 'user')"
ユーザ名とパスワードをダイアログで与える場合、
RunAsUserAdmin2.cmd コマンド [引数...]
set x=%*
powershell -command "start-process 'powershell' '-command \"start-process ''cmd'' ''/c %x:"=\\\"%'' -verb ''runas''\"' -credential $null"
ユーザ名とパスワードをハードコードする場合、
RunAsUserAdmin3.cmd コマンド [引数...]
set x=%*
powershell -command "start-process 'powershell' '-command \"start-process ''cmd'' ''/c %x:"=\\\"%'' -verb ''runas''\"' -credential (new-object Management.Automation.PSCredential 'user', (ConvertTo-SecureString -AsPlainText -Force 'password'))"
いずれの場合も、UACダイアログは出ます。
RunAsコマンドは引数でユーザ名を与えねばならず、エクスプローラから起動してユーザを選択することができません。:-(
PowerShellを使えば、GUIでユーザを選択することができます。
例えば、コマンドラインでは、
RunAsUser.cmd コマンド [引数...]
set x=%*
powershell "start-process -credential $null 'cmd' '/c %x:"=\""%'"
これをコンテキストメニューから利用するには、関連付けに、
HKCR\ファイルタイプ\shell\RunAsUser\command
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "start-process -credential $null 'cmd' '/c \"%1\" %*'"
「送る」から利用するには、ショートカット RunAsUser.lnk のリンク先に、
cmd.exe /v:on /c for /l %n in (1,1,2) do if %n==2 (for %y in (!x!) do powershell "start-process -credential $null 'cmd' '/c \""%~y\""'") else set x=
このとき、コンソール画面が開きますが、それが煩わしいときは、-windowstyle hidden を追加します。
関連付け
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden "start-process -credential $null 'cmd' '/c \"%1\" %*'"
ショートカット
cmd.exe /v:on /c for /l %n in (1,1,2) do if %n==2 (for %y in (!x!) do powershell -windowstyle hidden "start-process -credential $null 'cmd' '/c \""%~y\""'") else set x=
それでも、コンソール画面が一時開きます。そこで、ショートカットの「ウィンドウの大きさ」を「最小化」にしておきます。
第1は、!環境変数!
第2は、call %%環境変数%%
第3は、for
for /f "delims== tokens=1*" %%i in ('set 環境変数') do echo %%j
数字限定でよければ、
for /f %%i in ('set /a 環境変数') do echo %%i
第2の方法は、ifやforに使えませんが、第3の方法なら使えます。
(rem これは駄目。
set x=1
call if %%x%%==1 echo %%x%%
)
(rem これはおk。
set x=1
for /f "delims== tokens=1*" %%i in ('set x') do if %%j==1 echo %%j
)
また、第3の方法ならバッチファイル外でも使えます。
SchTasksコマンドを使えば、「標準ユーザ」に降格できます。
schtasks /create /tn hoge /tr "cmd" /sc once /st 00:00 /it /rl limited
schtasks /run /tn hoge
/rl limited は省略可。
IsIL.cmd
for /f "tokens=3 delims=\ " %%i in ('whoami /groups^|find "Mandatory"') do set LEVEL=%%i
echo %LEVEL%
ここで、
High 管理者として実行
Medium 標準ユーザ
Low 「整合性レベル:低」 (「保護モード:有効」)
timeoutは標準入力がリダイレクトされているとエラーになるので使わない方がよい。
waitfor hoge /t 秒
ただし、以下のようにすれば標準入力がリダイレクトされていても大丈夫です。
start /min /wait timeout 秒
timeout 0 >nul 2>nul
if errorlevel 1 (echo redirected) else echo console
color 0f
if errorlevel 1 (echo redirected) else echo console
引数なしのcolorでもよさそうですが、cmd /cで実行するとエラーなので。
if !errorlevel! == %errorlevel% (echo enable) else echo disable
if "!" == "" でも判定できそうですが、これはバッチファイル内限定なので。
RunAsコマンドは、.NETではありませんが、RunAs.exeをメモ帳で開くと、CommandLineToArgvWという文字列が見えます。なので標準シンタクスです。
例えば、cmd /k title "a b"なら、
RunAs ... "cmd /k title \"a b\""
か、
RunAs ... "cmd /k title """a b""""
と書けますが、cmd /k title "a < b"ならどうするか?
cmd.exeの遅延展開を使っても、cmd.exeの制御文字をエスケープできます。
set "x=RunAs ... ""cmd /k title \""a < b\"""""
if !errorlevel! == %errorlevel% (!x:""^=^"!) else cmd /v:on /c !x:""^^="!
set "x=コマンドライン"の中の"を2倍個します。外側の"で制御文字は無効です。
遅延展開で、""を半減して実行します。遅延展開後の制御文字は無効です。
遅延展開が有効なら、その場で実行し、無効ならサブシェルで有効にして実行します。
.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の標準シンタクスです。
そこで、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"""";"
のように書けます。
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の制御文字は、奇数個目の"~偶数個目の"でエスケープされ、偶数個目の"~奇数個目の"でエスケープされません。
最近のコメント