« 2009年7月 | トップページ | 2009年9月 »

2009年8月31日 (月)

ファイル名にDEL文字が使える!

意外なことに、ファイル名にDEL文字()(0x7F、127)が使えます。それも短いファイル名に使えます。ということは、DOS時代からの仕様?
エクスプローラではCTRL+BSで入力できますが、コマンドプロンプトでは入力できません。
しかし、エクスプローラでは見えません。コマンドプロンプトでは見えます。

他の制御文字(0x00~0x1F)が使えないのに、DEL文字だけが使えるのは「一貫性のない仕様」です。

また、入力できるのに表示されない「仕様の非対称性」はセキュリティ上の脆弱性の懸念があります。

2009年8月30日 (日)

IEの特定のタブをアクティブにする。(その2)

VB.NETに移植。

Function TabActivate(URL As String) As String
Dim Shell As Object=CreateObject("Shell.Application")
Dim ie As Object=Nothing
For Each ie In Shell.Windows()
  If ie.LocationURL=URL Then Exit For
  ie=Nothing
Next
If ie Is Nothing Then
  TabActivate="Not Found 1"
  Exit Function
End If
Dim wShell As Object=CreateObject("WScript.Shell")
If wShell.AppActivate(ie.Document.title) Then
  TabActivate=True
  Exit Function
End If
Dim ix As Object=Nothing
Dim LocationURL As String
For Each ix In Shell.Windows()
  If ix.HWND=ie.HWND Then
    If ix.Document.title<>"" Then If wShell.AppActivate(ix.Document.title) Then Exit For
    LocationURL=ix.LocationURL
    If Left(LocationURL,8)="file:///" Then
      LocationURL=Replace(Uri.UnescapeDataString(Mid(LocationURL,9)),"/","\")
    End If
    If wShell.AppActivate(LocationURL) Then Exit For
  End If
  ix=Nothing
Next
If ix Is Nothing Then
  TabActivate="Not Found 2"
  Exit Function
End If
For Each ix In Shell.Windows()
  If ix.HWND=ie.HWND Then
    wShell.SendKeys("^{tab}")
    Threading.Thread.Sleep(100)
    If wShell.AppActivate(ie.Document.title) Then
      TabActivate=True
      Exit Function
    End If
  End If
Next
TabActivate="Not Found 3"
End Function

2009年8月29日 (土)

バッチファイルで文字色と背景色を変えて文字列をECHOする。

cecho.cmd

@echo off
setlocal
if not defined color set color=c
md ___
pushd ___
<nul >"%*" cmd /k prompt $h
findstr /a:%color% "." "%*" nul
popd
rd /s /q ___

使用法

set color=背景色文字色
call cecho.cmd テキスト

「背景色文字色」は、color /? 参照。
「テキスト」にはファイル名に使えない文字は使えません。

使用例

「青赤黄」をその色で出します。続けて背景色で出します。

@echo off
setlocal
set color=9
call cecho 青
set color=c
call cecho 赤
set color=e
call cecho 黄
set color=90
call cecho 青
set color=c0
call cecho 赤
set color=e0
call cecho 黄
set color=a0
call cecho 緑

2009年8月27日 (木)

名前でもってwindowオブジェクトを捕捉する。

これならShellWindowsを使わずにできます。

msgbox typename(win)

function getwin(name)
nop="javascript:void(0)"
set getwin=open(nop,name)
if getwin.location.href<>nop then exit function
getwin.close
set getwin=nothing
end function

2009年8月25日 (火)

同じ名前のウィンドウを(もしあれば)閉じて、常に新しく開く。

例えば、

set win=open("about:blank","hoge","resizable=no")
win.close
set win=open("about:blank","hoge","resizable=no")

は、うまく行きません。

closeが非同期なので、遅延して、時間軸上で、

set win=open("about:blank","hoge","resizable=no")
set win=open("about:blank","hoge","resizable=no")
win.close

のように動いて失敗します。

set win=open("about:blank","hoge","resizable=no")
win.close
do while not win.closed
' wscript.sleep 100 ' WSHならsleepがありますが、HTMLにはないので。
loop
set win=open("about:blank","hoge","resizable=no")

のように待ち合わせれば回避できますが、スピンループなので避けましょう。

set win=open("about:blank","hoge","resizable=no")
win.name=""
win.close
set win=open("about:blank","hoge","resizable=no")

あるいは、さらに、

set win=open("about:blank","hoge","resizable=no")
win.name=""
win.close
set win=open("about:blank","_blank","resizable=no")
win.name="hoge"

とすれば、非同期に耐えられます。

2009年8月24日 (月)

window.open()やwindow.close()は非同期です。

忘れてると、タイミング障害が思い出させてくれます。

例えば、以下で、非同期であることが分かります。

set win=open("about:blank","hoge","resizable=no")
win.close
msgbox win.closed

2009年8月21日 (金)

window.focus()とwindow.document.focus()の違い。

window.focus()は複数タブで効かないが、window.document.focus()は複数タブのアクティブタブでは効く。

逆に、シングルタブでwindow.blurした後、window.focusは効くが、window.document.focusは効かない。

同様に、シングルタブで最小化した状態で、window.focusは効くが、window.document.focusは効かない。

2009年8月20日 (木)

IE7/IE8で、window.open()で作った子ウィンドウから親ウィンドウを.focus()でアクティブにする。(その3)

MsgBox(vbSystemModal)を利用します。
親ウィンドウがバックグラウンド タブの場合は、そのタブバーが点滅します。

child msg.htm

<html>
<head>
<script language=vbscript>
Sub MsgActivate
opener.focus
opener.document.focus
If opener.document.hasFocus() Then Exit Sub
opener.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"
End Sub
</script>
</head>
<body>
<button onclick="opener.focus">opener.focus</button>
<button onclick="opener.document.focus">opener.document.focus</button>
<button onclick='opener.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"'>MsgBox</button>
<button onclick="MsgActivate">MsgActivate</button>
</body>
</html>

2009年8月19日 (水)

IE7/IE8で、window.open()で作った子ウィンドウを.focus()でアクティブにする。(その3)

IE7/IE8では、「常に新しいタブでポップアップを開く」等の設定により、window.open()が新しいタブで開かれます。
そのような場合は、子ウィンドウを.focus()でアクティブにするのは困難です。
外部オブジェクトを使えば、なんとかなりますが、それも大変です。

そこで、スクリプトだけの簡便な方法です。MsgBox(vbSystemModal)を利用します。

<html>
<head>
<script language=vbscript>
Dim win
Sub MsgActivate
win.focus
win.document.focus
If win.document.hasFocus() Then Exit Sub
win.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"
End Sub
</script>
</head>
<body>
<button onclick='Set win=window.open("child msg.htm")'>open new tab</button>
<button onclick='Set win=window.open("child msg.htm","_blank","resizable=no")'>open new window</button>
<button onclick="win.focus">win.focus</button>
<button onclick="win.document.focus">win.document.focus</button>
<button onclick='win.setTimeout "MsgBox ""focus moving..."",vbSystemModal",0,"vbscript"'>MsgBox</button>
<button onclick="MsgActivate">MsgActivate</button>
</body>
</html>

子ウィンドウがバックグラウンド タブの場合は、そのタブバーが点滅します。

2009年8月18日 (火)

IE7/IE8で、window.open()で作った子ウィンドウから親ウィンドウを.focus()でアクティブにする。(その2)

もし、複数タブのケースを除外するなら、比較的簡単です。WScript.ShellのAppActivateを使用します。

child app.htm

<html>
<head>
<script language=vbscript>
Sub Activate
opener.focus
opener.document.focus
If opener.document.hasFocus() Then Exit Sub
Dim wShell
Set wShell=CreateObject("WScript.Shell")
If wShell.AppActivate(opener.document.title) Then Exit Sub
Dim LocationURL
LocationURL=opener.location.href
If Left(LocationURL,8)="file:///" Then LocationURL=Replace(UnEscape(Mid(LocationURL,9)),"/","\")
If LocationURL="about:blank" Then LocationURL="空白のページ"
If wShell.AppActivate(LocationURL) Then Exit Sub
End Sub
</script>
</head>
<body>
<button onclick="opener.focus">opener.focus</button>
<button onclick="opener.document.focus">opener.document.focus</button>
<button onclick='CreateObject("WScript.Shell").AppActivate opener.document.title'>AppActivate</button>
<button onclick="Activate">Activate</button>
</body>
</html>

親ウィンドウのタイトルはユニークにしておきます。
ただし、タイトルがタイトルバーに出ないで、URLのままのときがあります。

親ウィンドウが複数タブであっても、それがアクティブタブなら効きます。

2009年8月17日 (月)

IE7/IE8で、window.open()で作った子ウィンドウを.focus()でアクティブにする。(その2)

もし、複数タブのケースを除外するなら、比較的簡単です。WScript.ShellのAppActivateを使用します。

<html>
<head>
<title>opener</title>
<script language=vbscript>
Option Explicit
Dim win
Sub Activate
win.focus
win.document.focus
If win.document.hasFocus() Then Exit Sub
Dim wShell
Set wShell=CreateObject("WScript.Shell")
If wShell.AppActivate(win.document.title) Then Exit Sub
Dim LocationURL
LocationURL=win.location.href
If Left(LocationURL,8)="file:///" Then LocationURL=Replace(UnEscape(Mid(LocationURL,9)),"/","\")
If LocationURL="about:blank" Then LocationURL="空白のページ"
If wShell.AppActivate(LocationURL) Then Exit Sub
End Sub
</script>
</head>
<body>
<button onclick='Set win=window.open("child app.htm")'>open new tab</button>
<button onclick='Set win=window.open("child app.htm","_blank","resizable=no")'>open new window</button>
<button onclick="win.focus">win.focus</button>
<button onclick="win.document.focus">win.document.focus</button>
<button onclick='CreateObject("WScript.Shell").AppActivate win.document.title'>AppActivate</button>
<button onclick="Activate">Activate</button>
</body>
</html>

子ウィンドウのタイトルはユニークにしておきます。
ただし、タイトルがタイトルバーに出ないで、URLのままのときがあります。

2009年8月16日 (日)

IE7/IE8で、window.open()で作った子ウィンドウから親ウィンドウを.focus()でアクティブにする。

IE7/IE8では、「常に新しいタブでポップアップを開く」等の設定により、window.open()が新しいタブで開かれます。
そうでなくても、親ウィンドウが複数タブの場合があります。
そのような場合、子ウィンドウから親ウィンドウを.focus()でアクティブにするのは困難です。

child.htm

<html>
<head>
<object id=ShellWindows classid=clsid:9BA05972-F6A8-11CF-A442-00A0C90A8F39></object>
<object id=wShell classid=clsid:72C24DD5-D70A-438B-8A42-98424B88AFB8></object>
<script language=vbscript>
Option Explicit
Dim n
Sub TabActivate
Dim ie,ix
For Each ie In ShellWindows
  If TypeName(ie.Document)<>"HTMLDocument" Then
  ElseIf ie.Document.parentWindow Is opener Then
    Exit For
  End If
Next
If IsEmpty(ie) Then
  MsgBox "Not Found 1"
  Exit Sub
End If
opener.focus
opener.document.focus
If opener.document.hasFocus() Then Exit Sub
If AppActivate(ie) Then Exit Sub
For Each ix In ShellWindows
  If ix.HWND=ie.HWND Then
    ix.Document.focus
    If ix.Document.hasFocus() Then Exit For
    If AppActivate(ix) Then Exit For
  End If
Next
If IsEmpty(ix) Then
  MsgBox "Not Found 2"
  Exit Sub
End If
n=0
NextTab
End Sub
Sub NextTab
If opener.document.hasFocus() Then Exit Sub
If n<ShellWindows.Count Then
  n=n+1
  wShell.SendKeys "^{tab}"
  setTimeout "NextTab",100
  Exit Sub
End If
MsgBox "Not Found 3"
End Sub
Function AppActivate(ie)
AppActivate=True
If wShell.AppActivate(ie.Document.title) Then Exit Function
Dim LocationURL
LocationURL=ie.LocationURL
If Left(LocationURL,8)="file:///" Then LocationURL=Replace(UnEscape(Mid(LocationURL,9)),"/","\")
If LocationURL="about:blank" Then LocationURL="空白のページ"
If wShell.AppActivate(LocationURL) Then Exit Function
AppActivate=False
End Function
</script>
</head>
<body>
<button onclick="opener.focus">opener.focus</button>
<button onclick="opener.document.focus">opener.document.focus</button>
<button onclick="TabActivate">TabActivate</button>
</body>
</html>

2009年8月15日 (土)

IE7/IE8で、IEオブジェクトがアクティブなタブか?を判定する。

IE7/IE8で、IEオブジェクトがアクティブなタブか?の判定

Function TabIsActive(ie)
ie.StatusText=CStr(ie.HWND)
TabIsActive=(ie.StatusText=CStr(ie.HWND))
ie.StatusText=""
End Function

ie.StatusTextを変更可能なのは、アクティブなタブだけなので、試しに変更してみる。
変更文字列には、ie.HWNDを乱数代わりに使います。

判定できるのは、そのIEウィンドウ内でアクティブなタブか、であって、そのIEウィンドウがアクティブかどうかは不明です。

2009年8月14日 (金)

IE7/IE8で、window.open()で作った子ウィンドウを.focus()でアクティブにする。

IE7/IE8では、「常に新しいタブでポップアップを開く」等の設定により、window.open()が新しいタブで開かれます。
そのような場合は、子ウィンドウを.focus()でアクティブにするのは困難です。

<html>
<head>
<object id=ShellWindows classid=clsid:9BA05972-F6A8-11CF-A442-00A0C90A8F39></object>
<object id=wShell classid=clsid:72C24DD5-D70A-438B-8A42-98424B88AFB8></object>
<script language=vbscript>
Option Explicit
Dim win
Dim n
Sub TabActivate
Dim ie,ix
For Each ie In ShellWindows
  If TypeName(ie.Document)<>"HTMLDocument" Then
  ElseIf ie.Document.parentWindow Is win Then
    Exit For
  End If
Next
If IsEmpty(ie) Then
  MsgBox "Not Found 1"
  Exit Sub
End If
win.focus
win.document.focus
If win.document.hasFocus() Then Exit Sub
If AppActivate(ie) Then Exit Sub
For Each ix In ShellWindows
  If ix.HWND=ie.HWND Then
    ix.Document.focus
    If ix.Document.hasFocus() Then Exit For
    If AppActivate(ix) Then Exit For
  End If
Next
If IsEmpty(ix) Then
  MsgBox "Not Found 2"
  Exit Sub
End If
n=0
NextTab
End Sub
Sub NextTab
If win.document.hasFocus() Then Exit Sub
If n<ShellWindows.Count Then
  n=n+1
  wShell.SendKeys "^{tab}"
  setTimeout "NextTab",100
  Exit Sub
End If
MsgBox "Not Found 3"
End Sub
Function AppActivate(ie)
AppActivate=True
If wShell.AppActivate(ie.Document.title) Then Exit Function
Dim LocationURL
LocationURL=ie.LocationURL
If Left(LocationURL,8)="file:///" Then LocationURL=Replace(UnEscape(Mid(LocationURL,9)),"/","\")
If LocationURL="about:blank" Then LocationURL="空白のページ"
If wShell.AppActivate(LocationURL) Then Exit Function
AppActivate=False
End Function
</script>
</head>
<body>
<button onclick='Set win=window.open("child.htm")'>open new tab</button>
<button onclick='Set win=window.open("child.htm","_blank","resizable=no")'>open new window</button>
<button onclick="win.focus">win.focus</button>
<button onclick="win.document.focus">win.document.focus</button>
<button onclick="TabActivate">TabActivate</button>
</body>
</html>

2009年8月13日 (木)

IEの特定のタブをアクティブにする。

AppActivate()では、バックグラウンドのタブはアクティブにできません。

そこで、指定されたURLのタブをアクティブにします。

Function TabActivate(URL)
TabActivate=True
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows()
  If ie.LocationURL=URL Then Exit For
Next
If IsEmpty(ie) Then
  TabActivate="Not Found 1"
  Exit Function
End If
Set wShell=CreateObject("WScript.Shell")
If AppActivate(wShell,ie) Then Exit Function
For Each ix In Shell.Windows()
  If ix.HWND=ie.HWND Then If AppActivate(wShell,ix) Then Exit For
Next
If IsEmpty(ix) Then
  TabActivate="Not Found 2"
  Exit Function
End If
For Each ix In Shell.Windows()
  If ix.HWND=ie.HWND Then
    wShell.SendKeys "^{tab}"
    WScript.Sleep 100
    ie.StatusText=CStr(ie.HWND)
    If ie.StatusText=CStr(ie.HWND) Then Exit Function
  End If
Next
TabActivate="Not Found 3"
End Function

Function AppActivate(wShell,ie)
AppActivate=True
If ie.Document.title<>"" Then If wShell.AppActivate(ie.Document.title) Then Exit Function
LocationURL=ie.LocationURL
If Left(LocationURL,8)="file:///" Then LocationURL=Replace(UnEscape(Mid(LocationURL,9)),"/","\")
If LocationURL="about:blank" Then LocationURL="空白のページ"
If wShell.AppActivate(LocationURL) Then Exit Function
AppActivate=False
End Function

2009年8月12日 (水)

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

XP SP3 + IE8 で、mhtmlファイルを開くと、Tempフォルダにゴミファイル(wbk*.tmp)がいっぱい残りました。
http://scripting.cocolog-nifty.com/blog/2009/05/ie8-mhtml-ae86.html

Vista+IE8の場合は、Temp\Lowフォルダにゴミファイル(wbk*.tmp)がいっぱい残ります。

%Temp%\Low

C:\Users\%username%\AppData\Local\Temp\Low

Vista用ごみ掃除ショートカットは、

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

ところで、Temp\Low の整合性レベルは低なので、Vistaでは、一応、セキュリティは考えられているようです。

というか、Vista用に作られたIE8をそのままXPに持って行ったため、XPでは穴になっているのかも知れません。

※ Vista+IE8 の場所がいつの間にか変わってますね。

C:\Users\%username%\AppData\LocalLow

※ 修正されたみたいですね。残っているゴミファイルの日付は2010年4月10日なので、その頃かな。

2009年8月 8日 (土)

バッチファイルを暗号化する。(その2)

暗号化と言っても英字を半角カタカナにするだけですが。。。

ただし、全角文字は使えません。また、英小文字は英大文字に変換されます。

encrypt.vbs バッチファイル...

Set fso=CreateObject("Scripting.FileSystemObject")
For Each File In WScript.Arguments
  Text=fso.OpenTextFile(File).ReadAll
  If Right(Text,1)<>vbLf Then Text=Text & vbCrLf
  Text=Text & "chcp 932"
  Set oFile=fso.CreateTextFile(File & ".cmd")
  oFile.WriteLine "chcp 20127"
  For k=1 To Len(Text)
    c=Mid(Text,k,1)
    If 32<Asc(c) And Asc(c)<96 Then
      oFile.Write Chr(Asc(c)+128)
    ElseIf 96<Asc(c) And Asc(c)<123 Then
      oFile.Write Chr(Asc(c)+96)
    Else
      oFile.Write c
    End If
  Next
  oFile.Close
Next

例えば、aaa.cmd

echo abc
pause

は、aaa.cmd.cmd

chcp 20127
ナテネマ チツテ
ミチユモナ
テネテミ ケウイ

に暗号化されます。

2009年8月 5日 (水)

IEのFullScreen、ToolBar、AddressBar、MenuBar、StatusBarをトグル。

IE7/IE8のメニューには、アドレスバーの表示切り替えがありません。
IEのメニューには、そもそもフルスクリーンの切り替えがありません。
そこで、以下のhtmファイルをお気に入りバーに入れて使います。

ToggleBar.htm

<html>
<head>
<script language=vbscript>
Dim ie
Sub window_onload
For Each ie In ShellWindows
  If TypeName(ie.Document)<>"HTMLDocument" Then
  ElseIf ie.Document.parentWindow Is window Then
    Exit For
  End If
Next
End Sub
</script>
</head>
<body>
<object id=ShellWindows classid=clsid:9BA05972-F6A8-11CF-A442-00A0C90A8F39></object>
<button onclick="ie.FullScreen=Not ie.FullScreen">FullScreen</button>
<button onclick="ie.ToolBar=ie.ToolBar-1">ToolBar</button>
<button onclick="ie.AddressBar=Not ie.AddressBar">AddressBar</button>
<button onclick="ie.MenuBar=Not ie.MenuBar">MenuBar</button>
<button onclick="ie.StatusBar=Not ie.StatusBar">StatusBar</button>
</body>
</html>

アドレスバーとツールバーは、他にタブがあると、効きません。
フルスクリーンは、他にタブがあると、他のタブが見えなくなります。

2009年8月 4日 (火)

IE7/IE8で、現在または最後にアクティブなIEを捕捉する。

Win32APIのFindWindow()を併用すれば、正確に捕捉できます。

hwnd=CreateObject("Excel.Application").ExecuteExcel4Macro("CALL(""user32"",""FindWindowA"",""JCJ"",""IEFrame"",0)")
For Each ie In CreateObject("Shell.Application").Windows()
  If hwnd=ie.HWND Then
    ie.StatusText=CStr(hwnd)
    If ie.StatusText=CStr(hwnd) Then Exit For
  End If
Next
If IsEmpty(ie) Then
  MsgBox "Not Found"
Else
  MsgBox ie.LocationURL
End If

アクティブなIEウィンドウはFindWindow("IEFrame",0)で分かりますが、アクティブなタブは分かりません。
しかし、StatusTextが変更可能なのはアクティブなタブだけなようなので、それで区別できます。

2009年8月 3日 (月)

Vista+IE8(IE7?)で、制限付きサイトゾーンのフォルダが使える。

以前(XP+IE6)から、shell:cookiesフォルダは、制限付きサイトゾーンで、ここに作ったフォルダやファイルも制限付きサイトゾーンになりましたが、残念なことに、クッキーの削除で消されてしまいました。
なので、あまり実用にならなかったのですが、Vista+IE8(IE7?)では、消されなくなりました。
これで、shell:cacheのインターネットゾーンのフォルダと同様に使えます。

エクスプローラで、shell:cookies を開いて、新しいフォルダを作成し、そのショートカットをお気に入りリンクやデスクトップに入れて使います。

shell:cacheの場合は、エクスプローラで、shell:cache\content.ie5 を開いて、そこでコマンドプロンプトを開き、
md ..\新しいフォルダ名
で、親フォルダに新しいフォルダを作ります。
エクスプローラで、shell:cache\新しいフォルダ名 を開いて、アドレスバーのアイコンをお気に入りリンクやデスクトップにドラッグ&ドロップしてショートカットを作成して使います。

2009年8月 2日 (日)

Vista以降で、現在または最後にアクティブなシェルを捕捉する。

Win32APIのFindWindow()を併用すれば、正確に捕捉できます。

hwnd=CreateObject("Excel.Application").ExecuteExcel4Macro("CALL(""user32"",""FindWindowA"",""JCJ"",""CabinetWClass"",0)")
For Each ie In CreateObject("Shell.Application").Windows()
  If ie.hwnd=hwnd Then Exit For
Next
If IsEmpty(ie) Then
  MsgBox "Not Found"
Else
  MsgBox ie.Document.Folder.Self.Path
End If

« 2009年7月 | トップページ | 2009年9月 »