コマンドラインで、サスペンド(スリープ)、ハイバネーション(休止)する。(その7)
sleep.vbs
CreateObject("WScript.Shell").SendKeys "^{esc}{tab}{tab}{right}{right}s"
その他は、
W sWitch user
L Logoff
O lOck
R Reboot
S Sleep
H Hibanate
U shUtdown
« 2009年8月 | トップページ | 2009年10月 »
sleep.vbs
CreateObject("WScript.Shell").SendKeys "^{esc}{tab}{tab}{right}{right}s"
その他は、
W sWitch user
L Logoff
O lOck
R Reboot
S Sleep
H Hibanate
U shUtdown
suspend.vbs
CreateObject("Shell.Application").ShutdownWindows
Set wShell=CreateObject("WScript.Shell")
Do While Not wShell.AppActivate("Windows のシャットダウン")
WScript.Sleep 100
Loop
wShell.SendKeys "%w{end}{up}{up}%k"
hibernate.vbs
CreateObject("Shell.Application").ShutdownWindows
Set wShell=CreateObject("WScript.Shell")
Do While Not wShell.AppActivate("Windows のシャットダウン")
WScript.Sleep 100
Loop
wShell.SendKeys "%w{end}{up}%k"
日本語が送れるSendKeysならもっと確実に選択できるのですが、WScript.ShellのSendKeysは駄目なのです。英語圏は楽にできていいなぁ。
というか、ドロップダウンリストにはユニークなショートカットキーを付けてほしいものです。
スクリプトからExcel経由でWin32APIを呼び出します。
Set Application=CreateObject("Excel.Application")
hwnd=Application.ExecuteExcel4Macro("CALL(""user32"",""FindWindowA"",""JCJ"",""ConsoleWindowClass"",0)")
pid=Application.ExecuteExcel4Macro("CALL(""user32"",""GetWindowThreadProcessId"",""2JN"","& hwnd &","& pid &")")
Call Application.ExecuteExcel4Macro("CALL(""kernel32"",""AttachConsole"",""JJ""," & pid & ")")
hConsole=Application.ExecuteExcel4Macro("CALL(""kernel32"",""CreateFileA"",""JCJJJJJJ"",""CONOUT$"",-1073741824,3,0,3,0,0)")
Echo 12,"赤"
Echo 9,"青"
Echo 14,"黄"
Echo &Hca,"赤"
Echo &H9a,"青"
Echo &Hea,"黄"
Echo 7,""
Call Application.ExecuteExcel4Macro("CALL(""kernel32"",""CloseHandle"",""JJ""," & hConsole & ")")
Sub Echo(wAttribute,Text)
Call Application.ExecuteExcel4Macro("CALL(""kernel32"",""SetConsoleTextAttribute"",""JJJ""," & hConsole & "," & wAttribute & ")")
WScript.StdOut.Write Text
End Sub
xcolor.exeを使います。
文字列「赤青黄」をその文字色と緑の背景色で出します。
cscript cecho.vbs
cecho 10*16+12,"赤"
cecho &Ha9,"青"
cecho "&Hae","黄"
cecho 7,""
sub cecho(color,text)
createobject("wscript.shell").exec("xcolor.exe " & color).stdout.readall
wscript.stdout.write text
end sub
VB.NETからWin32APIのSetConsoleTextAttribute()を呼び出します。
XColor.exe 属性
属性は、文字色(0~15)、背景色(&H00~&Hf0)、下線(&H8000)など。Color/?参照。
10進数または16進数(&H~)で。CMDでのエスケープは、"&H~" か ^&H~ で。
vbc XColor.VB
Public Class Class1
Private Const GENERIC_READ As Int32 = &H80000000
Private Const GENERIC_WRITE As Int32 = &H40000000
Private Const FILE_SHARE_READ As Int32 = &H00000001
Private Const FILE_SHARE_WRITE As Int32 = &H0000002
Private Const OPEN_EXISTING As Int32 = 3
Private Declare Auto Function CreateFile Lib "kernel32.dll" ( _
ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, _
ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, _
ByVal hTemplateFile As IntPtr) As IntPtr
Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean
Private Declare Function SetConsoleTextAttribute Lib "kernel32" (ByVal hConsoleOutput As Integer, ByVal wAttributes As Integer) As Integer
Public Shared Sub Main(ByVal Args() As String)
Dim wAttributes As Integer
If Args.Length=1 AndAlso IsNumeric(Args(0)) Then
wAttributes = CInt(Args(0))
Else
Console.WriteLine("Usage: XColor Attribute")
Exit Sub
End If
Dim hConsoleOutput As Integer = CreateFile("CONOUT$", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero)
SetConsoleTextAttribute(hConsoleOutput, wAttributes)
CloseHandle(hConsoleOutput)
End Sub
End Class
使用例、文字列「赤青黄」をその文字色で出します。
@echo off
xcolor 12
set <NUL /p x=赤
xcolor 9
set <NUL /p x=青
xcolor "&he"
set <NUL /p x=黄
xcolor 7
Colorコマンドはコンソール全体の文字色や背景色を変えますが、部分的に変えることはできません。
そこで、部分的に文字色や背景色を変えるColorXコマンドを、OS(Vista)標準搭載のVB.NETで作ります。
ColorX.exe 文字色 [背景色]
文字色や背景色は、数字(0~15)か色の名前(Black~White)で指定します。
vbc ColorX.vb
Public Class Class1
Public Shared Sub Main(ByVal Args() As String)
If Args.Length = 0 OrElse Args.Length > 2 Then
Console.WriteLine("Usage: ColorX ForegroundColor [BackgroundColor]")
For Each ColorName As String In ConsoleColor.GetNames(GetType(ConsoleColor))
Console.WriteLine("{0,2} {1}", [Enum].Format(GetType(ConsoleColor), CType([Enum].Parse(GetType(ConsoleColor), ColorName), ConsoleColor), "d"), ColorName)
Next
Exit Sub
End If
Try
If Args.Length = 1 Then
Console.ForegroundColor = CType([Enum].Parse(GetType(ConsoleColor), Args(0), True), ConsoleColor)
Else
Console.ForegroundColor = CType([Enum].Parse(GetType(ConsoleColor), Args(0), True), ConsoleColor)
Console.BackgroundColor = CType([Enum].Parse(GetType(ConsoleColor), Args(1), True), ConsoleColor)
End If
Catch
Console.Error.WriteLine("Source" & vbTab & vbTab & Err.Source & vbLf & "Number" & vbTab & vbTab & Err.Number & vbLf & "Description" & vbTab & Err.Description & vbLf & "DLL Error" & vbTab & vbTab & Err.LastDLLError)
End Try
End Sub
End Class
使用例、文字列「赤青黄」をその文字色で出します。
@echo off
colorx red
set <NUL /p x=赤
colorx blue
set <NUL /p x=青
colorx yellow
set <NUL /p x=黄
colorx 7
ファイル1にあって、ファイル2にない行を標準出力に出します。
comm1.cmd ファイル1 ファイル2
@echo off
findstr /X /L /V /G:%2 %1
unixのcommは入力がsortされている必要がありますが、こちらは必要ありません。
ただし、ファイル1は重複がないように、uniqされてる必要があります。もし、重複があると、重複します。
ファイル1とファイル2に共通な行を標準出力に出します。
comm3.cmd ファイル1 ファイル2
@echo off
findstr /X /L /G:%2 %1
unixのcommは入力がsortされている必要がありますが、こちらは必要ありません。
ただし、ファイル1は重複がないように、uniqされてる必要があります。もし、重複があると、重複します。
重複行を削除します。
uniq.cmd 入力ファイル 出力ファイル
@echo off
type nul >%2
for /f "delims=" %%I in (%1) do findstr /X /C:"%%I" %2 >NUL || (echo;%%I)>>%2
unixのuniqは、入力がsortされている必要がありますが、こちらはsortは必要ありません。
※読者氏の指摘で訂正。/L→/C
バッチファイルで、
@echo off
for /L %%L in (0 0 1) do for /F "delims== tokens=2" %%I in ('wmic cpu get LoadPercentage /value') do title %%I%% & timeout 1 >NUL
ショートカットファイルで、
cmd.exe /q /c for /L %L in (0 0 1) do for /F "delims== tokens=2" %I in ('wmic cpu get LoadPercentage /value') do title %I% & timeout 1 >NUL
これらを最小化します。
Vistaでは、HomeBasicにも、wmicがあります。sleepは相変わらずありませんが、代わりに、timeoutやwaitforが使えます。
ファイルへのリダイレクションは、BOM付きUnicodeLEです。こちらの改行文字は正常です。CR+LF
一方、パイプは、シフトJISです。こちらの改行文字が変です。CR+CR+LF
ところで、for /F で読めるのは、シフトJISです。Unicodeは読めません。
なので、wmicの出力をファイルに出して、for /F %I in (ファイル) では読めません。
for /F %I in ('type ファイル') なら、シフトJISに変換されるので、読めます。改行文字の問題もありません。
また、for /F %I in ('コマンド') はパイプなので、wmicの出力がそのまま読めます。ただし、改行文字が。。。
pingやwmicなどのコマンドの出力は改行文字がおかしい。CR+CR+LFになってます。
これをforコマンドで処理しようとすると、余分なCRがいろいろ悪さをします。
例えば、
wmic CPU GET LoadPercentage
の出力、
---
LoadPercentage
2
---
からCPU負荷を環境変数に取り出そうと、
for /F %%I in ('wmic CPU GET LoadPercentage') do set X=%%I
echo;%X%
のようにすると、取れないはずの空行が、余分なCRのために、余計に取れて邪魔をします。
面倒ですが、callを噛ましてCRを消し、ifで空行を除外します。
for /F %%I in ('wmic CPU GET LoadPercentage') do (call set J=%%I) & if defined J (call set X=%%I)
echo;%X%
あるいは、forをもう一段噛ます方法もあります。
for /F %%I in ('wmic cpu get LoadPercentage') do for /F %%J in ("%%I") do set X=%%J
echo;%X%
pingやwmicなどのコマンドの出力は改行文字がおかしい。CR+CR+LFになってます。
見た目では分からないので、コマンドプロンプトで以下を試してみると、
for /f "delims=" %i in ('ping') do @echo;`%i'
行末の'が行頭の`を上書きして見えます。
あるいは、ファイルに書き出して、
(for /f "delims=" %i in ('ping') do @echo;`%i')>a.txt
メモ帳で見ると、行末の'の前でカーソル移動が1回停滞します。
さて、一度、ファイルに出力してから、改行文字を補正するには、以下を参照。
改行文字変換フィルタをバッチファイルで作る。(その2)
http://scripting.cocolog-nifty.com/blog/2008/11/post-8809.html
直接、コマンド出力を補正するには、callを噛まします。
for /f "delims=" %i in ('ping') do @call echo;%i
あるいは、コマンド出力を補正してファイルに書き出すには、
(for /f "delims=" %i in ('ping') do @call echo;%i)>a.txt
FSOの旧版(~5.6)では、共有名に日本語などを使うと、~.Pathが文字化けします。
文字化けパターンからすると、共有名がUnicodeLEなのに、シフトJISだと思って、シフトJIS→Unicode変換しているようです。
そこで、~.Pathの代替関数を作って、~.Path の代わりに GetPathName(~) を使います。
ここで、~はFileまたはFolderオブジェクトです。
Dim fso
Set fso=CreateObject("Scripting.FileSystemObject")
MsgBox GetPathName(fso.GetFolder("\\サーバ名\共有名"))
Function GetPathName(fObject)
If fObject.Attributes And 16 Then
If fObject.IsRootFolder Then
GetPathName=fObject.Drive.Path & "\"
Else
GetPathName=fso.BuildPath(GetPathName(fObject.ParentFolder),fObject.Name)
End If
Else
GetPathName=fso.BuildPath(GetPathName(fObject.ParentFolder),fObject.Name)
End If
End Function
メモ帳では、CTRL+BS や ALT+(numキーの)127 で入力できますが、見た目では見えないので、環境変数に割り当てて使うとよいでしょう。
for /f %%I in ('cmd/u /cecho 使') do set DL=%%I
set DL=%DL:~0,1%
echo %DL%