2022年5月
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        
無料ブログはココログ

« 2009年4月 | トップページ | 2009年6月 »

2009年5月31日 (日)

バッチファイルから「ファイルを開く」ダイアログを使う。

バッチファイルの場合は、mshta.exeが便利です。

<input type=file>では、初期値、フィルタ、タイトルが固定です。

for /f "delims=" %%I in ('mshta.exe "about:<input type=file id=FILE><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(FILE.value);close();resizeTo(0,0);</script>"') do echo %%I

HtmlDlgHelperのopenfiledlg()なら、初期値、フィルタ、タイトルが変えられます。

@echo off
set "File=C:\Program Files\*.txt"
set "Filter=テキスト (*.txt)|*.txt|すべてのファイル (*.*)|*.*|"
set "Title=ファイルの選択"
for /f "delims=" %%I in ('MSHTA.EXE "about:<object id=HtmlDlgHelper classid=CLSID:3050f4e1-98b5-11cf-bb82-00aa00bdce0b></object><script>resizeTo(0,0);function window.onload(){var Env=new ActiveXObject('WScript.Shell').Environment('Process');new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(HtmlDlgHelper.object.openfiledlg(Env('File'),null,Env('Filter'),Env('Title')).replace(/\0.*/,''));close();}</script><hta:application caption=no showintaskbar=no />"') do echo %%I

2009年5月28日 (木)

IE8で、<input type=file>の.valueがc:\fakepath\filenameを返す。(その2)

IEでも頑張ればできます。<input type=file>の.valueを見る代わりに、<input type=file>の編集ボックスをクリップボードにコピーして、それを<textarea>に張り付けて、<textarea>の.valueを見ます。

Option Explicit

MsgBox ieFileOpen("C:\Program Files\*.txt")

Function ieFileOpen(FileName)
Dim ie
Dim wShell
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
  WScript.Sleep 100
Loop
ie.Document.body.innerHTML="<input type=file id=FILE><textarea id=TEXT></textarea>"
ie.Document.parentWindow.setTimeout "FILE.click();"
Set wShell=CreateObject("WScript.Shell")
Do While Not wShell.AppActivate("ファイルの選択")
  WScript.Sleep 100
Loop
wShell.SendKeys "%n"&FileName&"%o"
Do While ie.Busy
  WScript.Sleep 100
Loop
ieFileOpen=ie.Document.all.FILE.value
If InStr(ieFileOpen,":\fakepath\")=2 Then
  Const OLECMDID_COPY = 12
  Const OLECMDID_PASTE = 13
  Const OLECMDID_SELECTALL = 17 '(&H11)
  Const OLECMDEXECOPT_DODEFAULT = 0
  ie.Document.all.FILE.focus
  ie.ExecWB OLECMDID_SELECTALL,OLECMDEXECOPT_DODEFAULT
  ie.ExecWB OLECMDID_COPY,OLECMDEXECOPT_DODEFAULT
  ie.Document.all.TEXT.focus
  ie.ExecWB OLECMDID_PASTE,OLECMDEXECOPT_DODEFAULT
  ieFileOpen=ie.Document.all.TEXT.value
End If
ie.Quit
End Function

2009年5月27日 (水)

IE8で、<input type=file>の.valueがc:\fakepath\filenameを返す。

WSHからIEを使って、ファイル選択ダイアログを出す方法が使えなくなりました。

これは、IE8でセキュリティが強化されたせいです。なので、セキュリティを緩めれば回避できますが。

[インターネットオプション][セキュリティ][インターネット][レベルのカストマイズ]
「サーバにファイルをアップロードするときにローカルディレクトリのパスを含める」
を「有効にする」。

セキュリティを緩めないで回避することができるか?

IEでも頑張ればできます。が、HTAならセキュリティ制約を受けません。なので、WSHからmshta.exeを使用する方法が簡単です。

Set wShell=CreateObject("WScript.Shell")
Set oExec=wShell.Exec("mshta.exe ""about:<input type=file id=FILE><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);</script>""")
MsgBox oExec.StdOut.ReadAll

バッチファイルでも、

for /f "delims=" %%I in ('mshta.exe "about:<input type=file id=FILE><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);</script>"') do echo %%I

2009年5月26日 (火)

AcroPDFでPDFファイルを開く、閉じるには?

PDFファイルを開くには、
AcroPDF.Src=ファイルパス または URL
または、
成否=AcroPDF.LoadFile(ファイルパス)
LoadFile()でURLは使えない。

AcroPDFには、PDFファイルを閉じるClose()メソッドがない。
別のファイルを開けば、先のファイルが閉じるので、
AcroPDF.Src="NUL"
または、
失敗=AcroPDF.LoadFile("NUL")
で代替する。

2009年5月25日 (月)

IE8では、PDFファイルを続けてNavigateしないほうがよい。

でないと、PDFファイルがIE終了時まで解放されなくなる。

続けてでなく、間にWebページを挟むとよい。それは、about:blankでもよい。(※1)(※2)

あるいは、PDFファイルを続けて開くときは、後続の
ie.Navigate PDFファイル
の代わりに、
ie.Document.Src=PDFファイル
または、
ie.Document.LoadFile PDFファイル
とするとよいかも。

ここで、TypeName(ie.Document)="AcroPDF" です。

※1 IEでなく、.NETのWebBrowserコントロールの場合は、さらに CoFreeUnusedLibraries()を呼び出す必要があるようです。

※2 最初にPDFファイルを開くと、Webページを開いても解放されない。なので、最初は、about:blankなどで避けたほうがよい。

※※ 6月のMSとAdobeの修正のどれかで直ったみたいです。

2009年5月20日 (水)

ウィンドウタイトルが数字文字列のウィンドウをAppActivateする。

WScript.ShellのAppActivate()では、数字文字列がプロセスIDに解釈されて、ウィンドウタイトルが数字文字列のウィンドウをAppActivateすることができません。

例えば、123という名前のフォルダを開いて、AppActivate("123")とやっても駄目です。
エクスプローラは、複数インスタンスが1プロセスに同居するので、プロセスIDも指定できません。
IE6以前であればIEでフォルダを開いて、AppActivate("123 - Microsoft Internet Explorer")とすることができたのですが、IE7以降はそれもできません。

しかし、タイトル文字列をUnicodeのバイト配列で指定するとよいようです。

Set Stream=CreateObject("ADODB.Stream")
Stream.Open
Stream.Type=2
Stream.WriteText "123"
Stream.Position=0
Stream.Type=1
Stream.Position=2
TitleBytes=Stream.Read(-1)
Set wShell=CreateObject("WScript.Shell")
r=wShell.AppActivate(TitleBytes)
WScript.Echo CStr(r),TitleBytes

2009年5月19日 (火)

IEを使って、UTF-8 の BOM を除去する。

拡張子は .txt 限定ですが、IEで開いて、上書き保存すれば、UTF-8 の BOM を削除できます。

ie-utf8-bom.vbs ファイル...

Option Explicit
Const OLECMDID_SAVE=3
Const OLECMDEXECOPT_DODEFAULT=0
Dim ie
Dim Path

Set ie=CreateObject("InternetExplorer.Application")
For Each Path In WScript.Arguments
  ie.Navigate Path
  Do While ie.Busy Or ie.ReadyState<>4
    WScript.Sleep 100
  Loop
  if ie.Document.Charset="utf-8" Then ie.ExecWB OLECMDID_SAVE,OLECMDEXECOPT_DODEFAULT
Next
ie.Quit

2009年5月18日 (月)

ADODB.Streamを使って、UTF-8 の BOM を除去する。

UTF-8 に BOM があれば、削除して、書き戻します。

utf8-bom.vbs ファイル...

Option Explicit
Const adTypeBinary=1
Const adTypeText=2
Const adSaveCreateOverWrite=2
Dim Path
Dim Src
Dim BOM
Dim Buf

Set Src=CreateObject("ADODB.Stream")
Src.Open
Src.Type=adTypeText
Src.Charset="utf-8"
Src.WriteText ""
Src.Position=0
Src.Type=adTypeBinary
BOM=CStr(Src.Read(3))

For Each Path In WScript.Arguments
  Src.LoadFromFile Path
  Buf=CStr(Src.Read(3))
  If Buf=BOM Then
    Buf=Src.Read(-1)
    Src.Position=0
    Src.Write Buf
    Src.SetEos
    Src.SaveToFile Path,adSaveCreateOverWrite
  End If
Next
Src.Close
Set Src=Nothing

2009年5月17日 (日)

バッチファイルだけで、UnicodeLE や UTF-8 の BOM を除去する。

UnicodeLE の BOM を除去する。

cmd /u /c type BOMありUnicodeファイル > BOMなしUnicodeファイル

これを利用して、

UTF-8 の BOM を除去する。

utf8-bom.cmd BOMありUTF-8ファイル BOMなしUTF-8ファイル

start /min /wait cmd /c chcp.com 65001 ^& cmd /u /c type %1 ^>$$$ ^& cmd /c type $$$ ^>%2 ^& del $$$

こちらは上書き保存も可。

さらに、複数のBOMあり/なし不定のUTF-8ファイルをワイルドカードやドロップで、BOMがあれば削除して上書きする。

for-utf8-bom.cmd BOMあり/なしUTF-8ファイル...

for %%1 in (%*) do start /min /wait cmd /v:on /c chcp.com 65001 ^& cmd /u /c type %%1 ^>$$$ ^& set /p x=^<$$$ ^& ^( if "!x:~0,2!"=="" cmd /c type $$$ ^>%%1 ^) ^& del $$$

2009年5月15日 (金)

forコマンドの憂鬱。ファイルセットのリカージョン

例えば、ファイル名の先頭に文字列を付加しようと、

for %%I in (*.txt) do rename "%%I" "hoge_%%I"

なんてやると、リカージョンを起こします。hoge_hoge_aaa.txt みたいに。

この問題を避けるために、

for /f "delims=" %%I in ('dir /b *.txt') do rename "%%I" "hoge_%%I"

なんてやると、今度は、非シフトJIS文字を含むファイル名が扱えなくなります。

まぁ、そういうケースはあまりないと思いますが。。。

そこで、ファイルセットをいったん環境変数に溜めて、そこから再び取り出します。

setlocal enabledelayedexpansion
set LF=^

set BUF=
for %%I in (*.txt) do set BUF=!BUF!!LF!%%I
for /f "delims=" %%I in ("!BUF!") do rename "%%I" "hoge_%%I"

遅延展開でLF文字を使って結合すると、「複数行の文字列」が作れます。
for /f in ("文字列")を使うと、「複数行の文字列」から1行ずつ順次取り出せます。

2009年5月14日 (木)

フォルダの表示モードを切り替える。

フォルダの表示モードを[写真]→[縮小版]→[並べて表示]→[アイコン]→[一覧]→[詳細]の順に切り替えます。

ToggleViewMode.vbs を「リンク」などに入れて使います。

Set ie=CreateObject("Shell.Application").Windows().Item()
ie.Document.CurrentViewMode=Array(5,3,2,4,7,6,1)(CLng(ie.Document.CurrentViewMode) Mod 7)

あるいは、以下のショートカットファイルをデスクトップなどに作成し、ショートカットキーを割り当てて使います。

mshta vbscript:execute("Set ie=CreateObject(""Shell.Application"").Windows().Item():ie.Document.CurrentViewMode=Array(5,3,2,4,7,6,1)(CLng(ie.Document.CurrentViewMode) Mod 7):close")

※ .Windows().Item()は、XPまではアクティブシェル、Vista以降はデスクトップシェル。

2009年5月10日 (日)

バッチファイルで英大文字チェック

文字が英大文字かどうか、をチェックするには、どうするか?

setlocal enabledelayedexpansion
set x=A
set y=a
set z=ABCDEFGHIJKLMNOPQRSTUVWXYZ
if not %z%==!z:%x%=! echo %x%は英文字ですが、大文字か小文字かは不明です。
if not %z%==!z:%y%=! echo %y%は英文字ですが、大文字か小文字かは不明です。

if not %z%==!z:%x%=! if %z%==!z:%x%=%x%! echo %x%は英大文字です。
if not %z%==!z:%y%=! if %z%==!z:%y%=%y%! echo %y%は英大文字です。

setの置換は大文字小文字を区別しません。
ifの比較は大文字小文字を区別します。

2009年5月 9日 (土)

バッチファイルで文字列の長さチェック

文字列の長さが、例えば、8文字かどうか、をチェックするには、どうするか?

まず、文字列の長さが、例えば、9文字以上かどうか、をチェックします。

set x=12345678
set y=%x:~8%
if defined y echo 9文字以上

同様に、8文字以上か、チェックすれば、8文字かどうか、判定できます。

set x=12345678
set y=%x:~8%
if defined y echo 9文字以上
set z=%x:~7%
if defined z echo 8文字以上
if defined z if not defined y echo 8文字

2009年5月 8日 (金)

IE8 で、mhtmlファイルを開くと、ゴミファイルが残る。(その2)

Cacheフォルダにも、サイズ=0のファイルが残ります。:-(

C:\Documents and Settings\user\Local Settings\Temporary Internet Files\Content.IE5\????????\????????

???????? はランダムな英大文字、数字の8文字。

こちらも、ときどき掃除したほうがよいと思いますが、どうしましょう?

@echo off
setlocal enabledelayedexpansion
set A=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
cd /d "%homepath%\Local Settings\Temporary Internet Files\Content.IE5"
for /F "delims=" %%I in ('dir /b /ad') do (
  for %%J in ("%%I\????????") do (
    if %%~zJ==0 (
      set x=%%~nxJ
      set y=!x:~8!
      if not defined y (
        set n=0
        for /L %%K in (0,1,7) do (
          for /F %%C in ("!x:~%%K,1!") do (
            if NOT !A!==!A:%%C=! if !A!==!A:%%C=%%C! set /a n+=1
          )
        )
        if !n!==8 echo del %%J
      )
    )
  )
)

もし、これで問題なければ、echoを外して使います。(未テスト)

2009年5月 7日 (木)

IE8で、mhtmlファイルを開くと、ゴミファイルが増殖する。

XP SP3 + IE8 で、mhtmlファイルを開くと、ゴミファイルがいっぱい残ります。
一度、Tempフォルダを確認してみましょう。
エクスプローラのアドレスバーや「ファイル名を指定して実行」に %temp% と入れます。

C:\Documents and Settings\user\Local Settings\Temp\wbk???.tmp

??? は16進3桁の通番。

なので、次のショートカットを作成して、ときどき掃除しましょう。

cmd.exe /V:ON /C"COLOR F0 & TITLE %TEMP% & DIR "%TEMP%\wbk*.tmp" & SET /P RESPONSE=Delete ? y or Cancel & IF /I "!RESPONSE!"=="Y" DEL "%TEMP%\wbk*.tmp""

IE8は、mhtmlファイルを開くと、そのIEでの初回はCacheフォルダに、二回目以降はTempフォルダに、中身を展開します。
これらは、ページを閉じても残ります。そして、ページを開く度に増殖して行きます。
IEを終了するとき、サイズ>0のファイルは削除されます。
なので、ときどき、IEを終了しましょう。でないと、終了処理にとっても時間が掛ります。
しかし、サイズ=0のファイルはそのまま残ります。

ところで、Tempフォルダなんか使って、セキュリティが大丈夫なのか、ちょっと心配ですね。

2009年5月 5日 (火)

Temporary Internet Filesフォルダの開き方

エクスプローラのアドレスバー、「ファイル名を指定して実行」、startやexplorer.exeの引数に、

shell:cache では、仮想フォルダが開きます。

shell:cache\Content.IE5 で、物理フォルダが開きます。

※物理フォルダでは、フォルダオプション、「表示」で「すべてのファイルとフォルダを表示する」になってること。

2009年5月 4日 (月)

インラインMSHTAスクリプトはフォーカスが奪われる。

インラインMSHTAスクリプトは、とても便利なのですが、唯一、最大の問題は、フォーカスが奪われることです。:-(
例えば、「コマンドラインからクリップボードを使う。」の
http://scripting.cocolog-nifty.com/blog/2006/09/post_52b4.html

ToClip.CMD

@MORE | MSHTA.EXE vbscript:Execute("clipboardData.setData ""text"",CreateObject(""Scripting.FileSystemObject"").GetStandardStream(0).ReadAll():close:")

を実行すると、フォーカスが奪われてしまいます。:-(
なので、コンソールをクリックして、フォーカスを取り戻さなくてはなりません。:-(
これが、とても不便です。:-(

これは、htaファイルでも、同じです。
htaファイルを起動すると、フォーカスが奪われます。htaが終了すれば、戻って来ます。
しかし、ここで、もし、<hta:application windowstate=minimize >タグがあれば、いっとき奪われますが、すぐに戻ります。
そこで、<hta:application windowstate=minimize >タグをインラインMSHTAスクリプトに応用します。

ToClip.CMD

@MORE | MSHTA.EXE "about:<hta:application windowstate=minimize /><script>clipboardData.setData('text',new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(0).ReadAll());close();</script>"

2009年5月 3日 (日)

コマンドラインで、サスペンド(スタンバイ)、ハイバネーション(休止)する。(その5)

PowerShellがあれば、バッチファイルやショートカットやコマンドラインで、

サスペンド

powershell.exe ^& {[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');[void][System.Windows.Forms.Application]::SetSuspendState([System.Windows.Forms.PowerState]'Suspend',$false,$false);}

ハイバネーション

powershell.exe ^& {[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');[void][System.Windows.Forms.Application]::SetSuspendState([System.Windows.Forms.PowerState]'Hibernate',$false,$false);}

コマンドラインで、サスペンド(スタンバイ)、ハイバネーション(休止)する。(その4)

PowerShellのps1ファイルで、

Suspend.ps1

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Windows.Forms.Application]::SetSuspendState([System.Windows.Forms.PowerState]"Suspend",$false,$false)

Hibernate.ps1

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Windows.Forms.Application]::SetSuspendState([System.Windows.Forms.PowerState]"Hibernate",$false,$false)

コマンドラインで、サスペンド(スタンバイ)、ハイバネーション(休止)する。(その3)

Vistaなら標準環境で、VB.NETで、exeを作って、

vbc /t:winexe Suspend.vb

Imports System.Windows.Forms
Public Class Class1
Public Shared Sub Main()
Application.SetSuspendState(PowerState.Suspend,False,False)
End Sub
End Class

vbc /t:winexe Hibernate.vb

Imports System.Windows.Forms
Public Class Class1
Public Shared Sub Main()
Application.SetSuspendState(PowerState.Hibernate,False,False)
End Sub
End Class

2009年5月 2日 (土)

VB.NETで、モニターの電源を切る。入れる。

.NETがあれば、VB.NETで、exeを作って、モニターの電源を切れます。

vbc /t:winexe MonitorPowerOff.vb

Public Class Class1
Private Declare Function SendMessageA Lib "user32" (hWnd As Integer,  Msg As Integer, wParam As Integer, lParam As Integer) As Integer
Public Shared Sub Main()
SendMessageA(-1, 274, 61808, 2)
End Sub
End Class

vbc /t:winexe MonitorPowerOn.vb

Public Class Class1
Private Declare Function SendMessageA Lib "user32" (hWnd As Integer,  Msg As Integer, wParam As Integer, lParam As Integer) As Integer
Public Shared Sub Main()
SendMessageA(-1, 274, 61808, -1)
End Sub
End Class

PowerShellで、モニターの電源を切る。入れる。

PowerShellがあれば、PowerShellスクリプトで、モニターの電源を切れます。

MonitorPowerOff.ps1

[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$form=new-object System.Windows.Forms.Form
$message=[System.Windows.Forms.Message]::Create($form.Handle,274,61808,2)
$nativeWindow=new-object System.Windows.Forms.NativeWindow
$nativeWindow.DefWndProc([ref]$message)

MonitorPowerOn.ps1

[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$form=new-object System.Windows.Forms.Form
$message=[System.Windows.Forms.Message]::Create($form.Handle,274,61808,-1)
$nativeWindow=new-object System.Windows.Forms.NativeWindow
$nativeWindow.DefWndProc([ref]$message)

コマンドで、モニターの電源を切る。入れる。

Excelがあれば、コマンドでも、モニターの電源を切れます。

mshta vbscript:execute("CreateObject(""Excel.Application"").ExecuteExcel4Macro ""CALL(""""user32"""",""""SendMessageA"""",""""JJJJJ"""",-1,274,61808,2)"":close")

モニターの電源を入れる。

mshta vbscript:execute("CreateObject(""Excel.Application"").ExecuteExcel4Macro ""CALL(""""user32"""",""""SendMessageA"""",""""JJJJJ"""",-1,274,61808,-1)"":close")

バッチファイルで、モニターの電源を切る。入れる。

Excelがあれば、バッチファイルでも、モニターの電源を切れます。

MonitorPowerOff.cmd

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0"
GOTO :EOF
@end
new ActiveXObject("Excel.Application").ExecuteExcel4Macro('CALL("user32","SendMessageA","JJJJJ",-1,274,61808,2)');

MonitorPowerOn.cmd

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0"
GOTO :EOF
@end
new ActiveXObject("Excel.Application").ExecuteExcel4Macro('CALL("user32","SendMessageA","JJJJJ",-1,274,61808,-1)');

VBScriptで、モニターの電源を切る。入れる。

Excelがあれば、VBScriptで、モニターの電源を切れます。

MonitorPowerOff.vbs

CreateObject("Excel.Application").ExecuteExcel4Macro "CALL(""user32"",""SendMessageA"",""JJJJJ"",-1,274,61808,2)"

MonitorPowerOn.vbs

CreateObject("Excel.Application").ExecuteExcel4Macro "CALL(""user32"",""SendMessageA"",""JJJJJ"",-1,274,61808,-1)"

« 2009年4月 | トップページ | 2009年6月 »