« 2006年12月 | トップページ | 2007年2月 »

2007年1月31日 (水)

任意のフォルダで「写真の印刷ウィザード」を開始するレジストリ定義

普通、「写真の印刷ウィザード」は、特定のイメージファイルの「印刷」に関連付けられていて、
関連付けが異なるイメージファイルで「写真の印刷ウィザード」を開始するのはとても面倒です。
一方、マイピクチャフォルダでは「画像のタスク」メニューから起動できます。
そこで、一般に、ディレクトリに「写真の印刷ウィザード」を関連付けるとよいでしょう。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\photowiz]
@="画像を印刷する(&P)"

[HKEY_CLASSES_ROOT\Directory\shell\photowiz\droptarget]
"clsid"="{60fd46de-f830-4894-a628-6fa81bc0190d}"

2007年1月30日 (火)

非表示で残った多数のExcelやWordをすべて終了させる。

StopAllExcels.VBS
StopAllWords.VBS

Option Explicit
Dim Application
Dim CountFrom,CountTo,Count
Dim k,Sec

Const ProgID="Excel.Application"
Const FileName="EXCEL.EXE"

'Const ProgID="Word.Application"
'Const FileName="WINWORD.EXE"

CountFrom=GetObject("winmgmts:root\CIMV2").ExecQuery("SELECT * FROM Win32_Process WHERE Name='"&FileName&"'").Count
CountTo=CountFrom
For k=1 To CountFrom
  Set Application=GetObject(,ProgID)
  If Err=0 Then
    Application.Visible=True
    Application.Quit
    Set Application=Nothing
    For Sec=1 To 10
      Count=GetObject("winmgmts:root\CIMV2").ExecQuery("SELECT * FROM Win32_Process WHERE Name='"&FileName&"'").Count
      If CountTo>Count Then Exit For
      WScript.Sleep 1000
    Next
    If CountTo>Count Then
      CountTo=Count
    Else
      Exit For
    End If
  ElseIf Err=429 Then
    MsgBox ProgID&" is not found.",vbInformation,WScript.ScriptName
  Else
    MsgBox Err.Description & " (" & Err.Number & ")",vbCritical,WScript.ScriptName
  End If
Next
If CountTo Then
  MsgBox ProgID&" can not be stopped. " & CountTo,vbCritical,WScript.ScriptName
ElseIf CountFrom Then
  MsgBox ProgID&" stopped. " & CountFrom,vbExclamation,WScript.ScriptName
Else
  MsgBox ProgID&" is not found.",vbInformation,WScript.ScriptName
End If
WScript.Quit

2007年1月29日 (月)

URLが分っていて、開かずにダウンロードするには?

リンク(アンカ)を右クリックして、「対象をファイルに保存」すればよい訳ですが、そのためにいちいち、リンク(アンカ)だけのHTMLファイルを作るのも、なんです。

「ファイル名を指定して実行」に、
about:<a href='http://...'>download</a>

コマンドプロンプトで、
start IExplore.exe "about:<a href='http://...'>download</a>"
start "" "about:<a href='http://...'>download</a>"

アドレスバーは駄目です。

※about:HTMLはIE7(?)/IE8では使えなくなりました。MSHTAなら使えます。

「ファイル名を指定して実行」に、
mshta about:<a href='http://...'>download</a>

コマンドプロンプトで、
start mshta.exe "about:<a href='http://...'>download</a>"

また、about:HTMLでなく、javascript:"HTML"なら使えます。

アドレスバーなどで、

javascript:"<a href='http://...'>download</a>"

ただし、javascript:"HTML"はスクリプトが有効でないと使えません。

2007年1月28日 (日)

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

引数を省略すると現プロセスIDを表示します。

GetProcessID.CMD [プロセスID]

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
if(WScript.Arguments.Count()==0) WScript.Echo(GetPPID(GetPID()));
else if(WScript.Arguments.Count()==1) WScript.Echo(GetPPID(WScript.Arguments.Item(0)));
else WScript.Echo("Usage: GetProcessID.CMD [PID]");

function GetPID(){
var wShell=new ActiveXObject("WScript.Shell");
var oExec=wShell.Exec('cmd.exe');
var PID=GetPPID(oExec.ProcessID);
return PID;
}

function GetPPID(PID){
var SWbemObjectSet=GetObject("winmgmts:root/CIMV2").ExecQuery("SELECT * FROM Win32_Process WHERE ProcessID=" + PID);
if(SWbemObjectSet.Count!=1){
  WScript.StdErr.WriteLine("ID " + PID + " のプロセスがありません。");
  WScript.Quit(1);
}
var Processes=new Enumerator(SWbemObjectSet);
for(;!Processes.atEnd();Processes.moveNext()){
  var Process=Processes.item();
  return Process.ParentProcessID;
}
}

2007年1月23日 (火)

コマンドラインからスクリプトとDDEを使ってPDFファイルをページ指定で開く。

コマンドラインからPDFファイルをページ指定で開けるか?

7.0以降なら、コマンドラインで可能です。

Start AcroRD32.exe /a "page=ページ" ファイル

6.0以前なら、スクリプトとDDEを使えば可能です。

PdfOpen.VBS ファイル ページ-1

Set wShell=CreateObject("WScript.Shell")
Path="C:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe"
wShell.RegWrite "HKCR\*\shell\PdfOpen\command\",""""&Path&"""","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfOpen\extended","","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfOpen\ddeexec\","[DocOpen(""%1"")][DocGoTo(NULL,""%2"")]","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfOpen\ddeexec\application\","Acroview","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfOpen\ddeexec\topic\","Control","REG_SZ"
Set Shell=CreateObject("Shell.Application")
Shell.ShellExecute WScript.Arguments.Item(0),WScript.Arguments.Item(1),,"PdfOpen"

2007年1月22日 (月)

コマンドラインでショートカット(.lnkと.url)のアイコンを変更する。

以前は、Shortcut.exeがありましたが、最近は、入手困難です。

以下は、コマンドラインでショートカット(.lnk)とインターネットショートカット(.url)のアイコンを変更します。

アイコン変更.CMD "ショートカットファイル" "アイコンファイル" インデクス

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" "%~dp1" "%~nx1" %2 %3
GOTO :EOF
@end
var Link=new ActiveXObject('Shell.Application').NameSpace(WScript.Arguments.Item(0)).Items().Item(WScript.Arguments.Item(1)).GetLink;
Link.SetIconLocation(WScript.Arguments.Item(2),WScript.Arguments.Item(3));
Link.Save();

ショートカット(.lnk)だけなら、WScript.Shellを使っても出来ます。
WScript.Shellは、インターネットショートカット(.url)のアイコン変更に使えません。

以下は、コマンドラインでショートカット(.lnk)のアイコンを変更します。

アイコン変更.CMD "ショートカット.lnk" "アイコンファイル" 番号

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %1 %2 %3
GOTO :EOF
@end
var Link=new ActiveXObject('WScript.Shell').CreateShortCut(WScript.Arguments.Item(0));
Link.IconLocation=WScript.Arguments.Item(1)+','+WScript.Arguments.Item(2);
Link.Save();

2007年1月21日 (日)

コマンドラインで壁紙を変更する。

壁紙変更.CMD ファイル

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" "%~dp1" "%~nx1"
GOTO :EOF
@end
//var ie=new ActiveXObject('InternetExplorer.Application');//ie6
var ie=WScript.GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}");//ie7
ie.Navigate(WScript.Arguments(0));
while(ie.Busy||ie.ReadyState!=4) WScript.Sleep(100);
ie.Document.CurrentViewMode=5;
var FolderItem=ie.Document.Folder.Items().Item(WScript.Arguments(1))
FolderItem.InvokeVerb('デスクトップの背景に設定(&B)');
ie.Quit();

※ie7以降、ieとshellが分離されたので。

2007年1月20日 (土)

エラー時の資源解放

一般のオブジェクトは参照の解放で終了するのでよいのですが、
中には参照の解放では終了しないものがあります。
そういうものはエラー時に終了指示ルートを通らないと、残ります。
エラーリカバリで頑張る方法もありますが、
Classにラップして、参照の解放で終了するようにできます。

原理を理解するために以下のクラスを作って、

Class Class1
Sub Class_Terminate()
MsgBox "資源解放"
End Sub
End Class

Set oClass1=New Class1
'処理をここに記述。↓正常/異常終了のシミュレート。
If MsgBox("Yes:正常終了 No:異常終了",vbYesNo)=vbNo Then Err.Raise 100

を実行すると、正常/異常終了のどちらの場合も、正常/異常終了後に
MsgBox "資源解放"
が実行されます。

なので、ここで資源を確実に解放するようにしておけばよいのです。
エラーリカバリを頑張るより簡単です。

2007年1月19日 (金)

DDEは多重処理に耐えません。

Windows2000の頃、Word/Excelの複数ファイルを選択して
右クリックして開いたり、印刷すると抜けが生じました。
またファイル数に応じて抜け殻のアプリが残りました。
WindowsXPでもShellExecute()やInvokeVerb()で続けて開くと駄目。

印刷をDDEで非同期に行っていることによる多重処理の設計障害です。

DDEの処理論理は、疑似コードで書くと、以下のようなものです。

if exists then
  [open]
  [print]
  [close]
else
  start
  [open]
  [print]
  [close]
  [stop]
  ※2
endif

この処理論理はシングルプロセスではOKです。しかし多重処理ではNGです。

多数(n)のインスタンスが生成されます。
  start
  start
  …

多数(n)のDDE要求はひとつのインスタンスにキューイングされます。
  [open]
  [print]
  [close]
  [stop]   <---※1
  [open]
  [print]
  [close]
  [stop]
  …

1つの処理をやってn-1の処理をキューに残したまま終了してしまいます。
n-1のゾンビが残ります。

正しくは、処理論理の全体をロックでシリアライズする必要があります。

回避方法は、先にWord/Excelアプリをひとつ立ち上げておくことです。

Windows XPやWord/Excel 2002は、取敢えず修正したようです。
Windows XPのシェルは、複数ファイルを逐次処理するように変えたようです。
Word 2002は複数のDDE要求を受け付けない/xオプションを作ったようです。
しかし、所詮弥縫策なのでは?

この修正が、なぜ駄目修正なのか?
シェルで複数選択したときだけにしか効かない。
スクリプトからShellExecute()やInvokeVerb()で続けて起動すると駄目。

複数ファイルをプリンタのドラッグ&ドロップしたときはまた別で駄目。
一応確認メッセージを出して、それで済まそうとしているようで姑息。

2007年1月18日 (木)

非表示で残ってしまったExcel/Wordなどを表示する。

Excel/Wordなどを非表示で実行していて、エラーなどで残ってしまったら、
まず表示に戻して、デバッグするなり、終了するなり、します。

Option Explicit
Show "Excel.Application"
'Show "Word.Application"

Sub Show(ProgID)
Dim Application
Set Application=GetExistingObject(ProgID)
If Err=0 Then
  Application.Visible=True
ElseIf Err=429 Then
  WScript.Echo ProgID,"Not Found"
Else
  WScript.Echo Err.Description & " (" & Err.Number & ")"
End If
End Sub

Function GetExistingObject(ProgID)
On Error Resume Next
Set GetExistingObject=Nothing
Set GetExistingObject=GetObject(,ProgID)
End Function

※IEの場合は、MenuBar.HTA、その他のアプリは、WordTasks.HTAを使う。

2007年1月17日 (水)

ExcelのApplication.ActivePrinterは「仕様障害」?

ActivePrinterにプリンタ名をそのまま代入してもエラーになります。
「プリンタ名 on ポート名」の形式でないと駄目なようです。
しかも、そのポート名が、USBポートのように:抜きで6文字以上の場合、
ユーザが設定し、プリンタのプロパティで表示されるポート名ではなく、
OSが勝手に割り当てたネットワークポート名のNe??:なのです。
ユーザはこれをどうやって指定すればよいのでしょうか?
全く困ったものです。

Ne??:に対応するだけなら、VBAだけで割り出せます。

Sub SetActivePrinter1(Name)
Dim n
Dim PortName
For n = 100 To 199
  PortName = Name & " on Ne" & Right(n, 2) & ":"
  TrySetActivePrinter PortName
  If Err = 0 Then Exit For
Next
If Err Then Err.Raise Err.Number
MsgBox Application.ActivePrinter
End Sub

Sub TrySetActivePrinter(Name)
On Error Resume Next
Application.ActivePrinter = Name
End Sub

LPTn:などのポートにも対応するには、レジストリを見るしかなさそう。

Sub SetActivePrinter2(Name)
Dim wShell
Const Key = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Devices\"
Set wShell = CreateObject("WScript.Shell")
Application.ActivePrinter = Name & " on " & Split(wShell.RegRead(Key & Name), ",")(1)
End Sub

Wordは、ActivePrinterにプリンタ名をそのまま代入しても、問題ないようです。

2007年1月16日 (火)

VBAからAdobe Reader 6.0でPDFファイルを印刷する。

Adobe Reader 7.0を使えば簡単ですが、どうしてもAdobe Reader 6.0なら。

Sub PdfPrint(File)
Dim PID

Const Path = "C:\Program Files\Adobe\Acrobat 6.0\Reader\AcroRd32.exe"
PID = Shell("""" & Path & """ /n /p /h """ & File & """")
Do
  AppActivateX PID
  If Err = 0 Then Exit Do
  Application.Wait Now + TimeSerial(0, 0, 1)
Loop
Do
  AppActivateX PID
  If Err Then Exit Do
  SendKeys "^q", True
  Application.Wait Now + TimeSerial(0, 0, 1)
Loop
End Sub

Sub AppActivateX(PID)
On Error Resume Next
AppActivate PID, False
End Sub

※On ErrorはVBAでもこんな風に使うとよいのでは?

2007年1月15日 (月)

WScript.NetworkのSetDefaultPrinter()を使うべからず。(障害)

WScript.NetworkのSetDefaultPrinter()でも、一応、デフォルトプリンタは、
変更はされるようですが、レジストリに設定する情報がちょっとおかしいです。
これはきっと「障害」です。

他にも、環境や条件によって、変更されなかったり、変更されたように見えても、
Excelなどから変更が見えなかったり、などと、トラブルが多いようです。
別コンポーネントの担当者間で仕様情報が遮断されている典型的な例です。

なので、SetDefaultPrinter()は、使わないほうがよいでしょう。

代わりに、
rundll32.exe printui.dll,PrintUIEntry /y /n "プリンタ名"

CreateObject("Shell.Application").NameSpace(4).Items().Item("プリンタ名").InvokeVerb "通常使うプリンタに設定(&F)"
が安全確実で、お勧めです。

あと、XP以降ならWMIでも出来るようです。Win32_PrinterクラスのSetDefaultPrinterメソッド。

2007年1月14日 (日)

WScript.ShellのPopup(,秒)の秒が効かない。(障害)

WScript.ShellのPopup()には、待ちが解けない障害があります。
HTMLでは、必ず、と言ってよいほど。ただし、これは原因が違って「仕様」かも?
WSHでも、ウィルススキャン中などCPUビジー状態で発生します。

インプリメントの予想(障害原因)
指定秒数でタイマ割り込みを掛けて、
割り込み出口で、「経過秒=指定秒」で判定しているため、
割り込みがCPUビジーで遅延すると、「経過秒>指定秒」になって抜ける。
そんな感じです。

2007年1月13日 (土)

配列よりVARIANT。多次元配列より配列の配列のVARIANT。

Dim Items(n)
より
Dim Items
Items=Array(...)

Dim Items(n,m)
hoge=Items(n,m)
より
Dim Items
Items=Array(Array(...),,,)
hoge=Items(n)(m)

のほうが扱い易いと思います。

例えば、
aaa(tab)bbb(tab)ccc(nl)
ddd(tab)eee(tab)fff(nl)
ggg(tab)hhh(tab)iii
のような、テキストを3x3の配列にすることを考えると、
Items=テキスト
Items=Split(Items,vbNewLine)
For k=0 To UBound(Items)
  Items(k)=Split(Items(k),vbTab)
Next
逆は、
For k=0 To UBound(Items)
  Items(k)=Join(Items(k),vbTab)
Next
Items=Join(Items,vbNewLine)
でテキストに戻ります。

※注
Split(string,delimiter)関数のdelimiterが、もし文字だと、
Split(,vbNewLine)が出来ないので、文字列になったのではないか、と想像。

因みに、正規表現の[.\n]が駄目なのも、.や\nがCr+Lfの関係で、
文字クラスでなくて文字列クラスになってるせいではないか、と想像。
なので、(.|\n)はOK。とは言え、これはやっぱり「障害」です。

2007年1月12日 (金)

文字列でSplitする。複数の文字でSplitする。

VBScriptのSplit(string,delimiter)関数のdelimiterは文字列です。
ヘルプには文字と書いてあるけど、違います。

Split(テキスト,区切り文字列)=Split(Replace(テキスト,区切り文字列,区切り文字),区切り文字)
みたいなものです。

なので、複数の文字でSplitするつもりで文字列を指定しても駄目です。
そういうときは、区切り文字をReplaceで集約してからSplitします。
つまり、
Split(Replace(Replace(テキスト,区切り文字3,区切り文字1),区切り文字2,区切り文字1),区切り文字1)
みたいに。

Join(list,delimiter)関数のdelimiterも文字列です。

2007年1月11日 (木)

スクリプトからDropTargetで「写真の印刷ウィザード」を開始する。

スクリプトから関連付けのDropTargetを利用するパラダイムです。

スクリプトからDropTargetを使って「写真の印刷ウィザード」を開始します。

写真の印刷ウィザード.VBS ファイル

Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows()
  If InStr(TypeName(ie.Document),"IShellFolderView") Then Exit For
Next
If IsEmpty(ie) Then
  WScript.Echo "No Explorer!"
  WScript.Quit
End If
Set Shell=ie.Document.Application
Set wShell=CreateObject("WScript.Shell")
wShell.RegWrite "HKCR\*\shell\photowiz\DropTarget\Clsid","{60fd46de-f830-4894-a628-6fa81bc0190d}","REG_SZ"
Set fso=CreateObject("Scripting.FileSystemObject")
Set File=fso.GetFile(WScript.Arguments.Item(0))
Shell.NameSpace(File.ParentFolder.Path).Items().Item(File.Name).InvokeVerb "photowiz"

2007年1月10日 (水)

エクスプローラで「元に戻す」の内容は?

バックグラウンドの右クリックで「元に戻す」にマウスを置いても、
「元に戻す」の内容が分りません。「移動」を戻す、と言っても、
ファイル名がないことには、判断の仕様がないではありませんか。

と思っていたら、編集メニューの「元に戻す」にマウスを置くと、
「元に戻す」の内容がステータスバーに表示されますね。
知らなかった。。。

2007年1月 9日 (火)

スクリプトからDDEを使ってPDFファイルを印刷する。

スクリプトからDDEを使うパラダイムです。

VBAならDDEExecute()などがあってDDEが使えますが、スクリプトからは?

関連付けで使える範囲なら、スクリプトからも関連付け経由で使えます。

PdfPrint.VBS ファイル

Set wShell=CreateObject("WScript.Shell")
Path="C:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe"
wShell.RegWrite "HKCR\*\shell\PdfPrint\command\",""""&Path&"""","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfPrint\extended","","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfPrint\ddeexec\","[FilePrintSilent(""%1"")]","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfPrint\ddeexec\application\","Acroview","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfPrint\ddeexec\ifexec\","[FilePrintSilent(""%1"")][AppExit]","REG_SZ"
wShell.RegWrite "HKCR\*\shell\PdfPrint\ddeexec\topic\","Control","REG_SZ"
Set Shell=CreateObject("Shell.Application")
Shell.ShellExecute WScript.Arguments.Item(0),,,"PdfPrint"

※DDEは多重処理に難があります。なので、上の例でも複数ファイルに対応できません。

2007年1月 7日 (日)

Adobe Reader 7.0のPDFファイルの関連付けを改善する。

Adobe Reader 7.0の関連付けにはいろいろ問題があります。

PDFファイルを印刷中に、他のPDFファイルを関連付けで開こうとしたり、
印刷しようとしても無視されます。

複数のPDFファイルを選択して関連付けで印刷しようとしても、
ひとつだけ印刷されて他は無視されます。

複数のPDFファイルを選択してプリンタにドロップして印刷すると、
アプリがひとつ開いたまま残ります。

関連付けは以下のようになっています。

デフォルト動詞はRead。

Read "Adobe Reader 7.0 で開く"
オプションなし  → /n

Open "開く"
オプションなし  → /o

Print "印刷"
/p /h → /cjs /n /p /h または /cjs /t

PrintTo
/t → /cjs /t

「開く」がOpenとReadと2つあるので、Openを/oオプションの「同じプロセスで開く」、
Readを/nオプションの「新しいプロセスで開く」に変えるとよいでしょう。

印刷は、/nオプションで新プロセスを起こして、/cjsオプションで閉じるとよいでしょう。
或いは、/cjs /tオプションでも同じです。

PrintToは、/cjsオプションで閉じるとよいでしょう。

※ /cjsオプションは、Adobe Reader 8.1で廃止されましたので、もう使えません。

2007年1月 6日 (土)

バッチファイルで行末の空白を削除する。

CALLと%*で行頭と行末の空白を削除します。

SET a=   aaa  bbb   
ECHO "%a%"
CALL :SUB %a%
ECHO "%a%"
GOTO :EOF
:SUB
SET a=%*

行末の空白を削除する正攻法は、

SET a=   aaa  bbb   
ECHO "%a%"
:LOOP
if "%a:~-1%"==" " (
SET a=%a:~0,-1%
GOTO LOOP
)
ECHO "%a%"

この場合、遅延展開は特に必要ありません。

2007年1月 5日 (金)

DATE/TIMEコマンドやDATE/TIME環境変数の形式は地域に依存します。

「地域と言語のオプション」の影響を受けないようにするには、DATE/TIMEコマンドやDATE/TIME環境変数を使わず、WSHスクリプトを使うのが一番です。

@if(0)==(0) ECHO OFF
FOR /F %%0 IN ('CScript.exe //NoLogo //E:JScript "%~f0"') DO SET yyyymmddhhmmss=%%0
ECHO %yyyymmddhhmmss%
GOTO :EOF
@end
var d=new Date();
WScript.Echo(d.getFullYear()*10000000000+(d.getMonth()+1)*100000000+d.getDate()*1000000+d.getHours()*10000+d.getMinutes()*100+d.getSeconds());

二番目は、CALLやFORの引数で、ファイルのタイムスタンプ「%~t0」を使えば、「地域と言語のオプション」の影響を受けずに済みます。ただし、秒が取れません。しかし、実際に秒の精度が必要なことはまずないので、形式的に必要なら00で埋めて代用すればよいのです。
※XPだけ?Vistaでは駄目。

TYPE NUL>$$$
FOR %%0 IN ($$$) DO FOR /F "tokens=1-5 delims=/: " %%1 IN ("%%~t0") DO SET yyyymmddhhmm=%%1%%2%%3%%4%%5
DEL $$$
ECHO %yyyymmddhhmm%

3番目は、固定位置で取り出すのではなく、FORで区切り文字で切り出せば、多少は影響を軽減できます。

SET d=%DATE%
SET t=%TIME%
IF NOT %d%==%DATE% (
SET d=%DATE%
SET t=%TIME%
)
FOR %%0 IN (%d%) DO FOR /F "tokens=1-3 delims=/-年月日" %%1 IN ("%%0") DO IF NOT "%%3"=="" (
SET yyyy=1%%1
SET /A mmdd=10%%200+1000%%3
)
IF %yyyy% LSS 130 (SET yyyy=20%yyyy:~-2%) ELSE IF %yyyy% LSS 200 (SET yyyy=19%yyyy:~-2%) ELSE SET yyyy=%yyyy:~-4%
SET mmdd=%mmdd:~-4%
SET PM=0
FOR %%0 IN (%t%) DO FOR /F "tokens=1-4 delims=:.時分秒" %%1 IN ("%%0") DO (
IF NOT "%%3"=="" (
SET /A hhmmss=10%%10000+1000%%200+100000%%3
) ELSE IF NOT "%%2"=="" (
SET /A hhmmss=10%%1*10000+1000%%200
) ELSE IF "%%1"=="PM" (SET PM=120000) ELSE IF "%%1"=="午後" (SET PM=120000)
)
SET /A hhmmss+=PM
SET hhmmss=%hhmmss:~-6%
ECHO %yyyy%%mmdd%%hhmmss%

曜日が左右いずれに有っても、年号が2桁でも、年月日の区切りが/でも-でも年月日でも、月日時分秒がゼロサプレスでも、秒がなくても、時分秒の区切りが時分秒でも、OKです。

2007年1月 4日 (木)

コマンドラインでPDFファイルを印刷する。(AdobeReader7.0/8.0)

Adobe Reader 7.0では、以下のオプションを追加されています。

/cjs       close just started ? 新規に起こしたときだけウィンドウを閉じる?
/l          cool                       非表示
/a 引数  Arguments              オープンパラメタ(page=nなど)
/u         URL protocol           acrobat:~で使われるようだが詳細は不明
/eo        ?                           CreateObjectで/o /eo /lが使われるが意味は不明

GetObjectでは-Embeddingが使われる。

コマンドラインでPDFファイルを印刷するには、
Adobe Reader 7.0の/cjsオプションを利用します。

START ACRORD32.EXE /cjs /n /p /h ファイル
START ACRORD32.EXE /cjs /t "ファイル" ["プリンタ"]

Adobe Reader 8.0でも同様です。

しかし、/cjsオプションはAdobe Reader 8.1で廃止されちゃいました。:-(

2007年1月 3日 (水)

現在の日時を何回も取り出さないこと!の実証実験

同じ行であっても%TIME%の値が変化します。

FOR /L %%i IN (1,1,1000) DO CALL :SUB
GOTO :EOF
:SUB
IF NOT %TIME%==%TIME% PAUSE

1/100秒の変化が、1000回中、2回くらい発生しました。
なので
秒なら5万回に一度
分なら300万回に一度
時なら1億8千万回に一度
日なら43億2千万回に一度
くらい発生しそうです。

%DATE%と%TIME%を併用するときは、ロック/逐次化が必要です。
:LOOP
SET d=%DATE%
SET t=%TIME%
IF NOT %d%==%DATE% GOTO :LOOP

或いは、簡便に、リトライを1回にして
SET d=%DATE%
SET t=%TIME%
IF NOT %d%==%DATE% (
SET d=%DATE%
SET t=%TIME%
)
でもよいでしょう。

2007年1月 2日 (火)

コマンドラインで印刷ジョブの状態を表示する。

横長に並べて表示します。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
START /W MSINFO32.EXE /categories +SWEnvPrint /report $$$.txt
SET PRINT=0
FOR /F "delims=" %%0 IN ('TYPE $$$.txt') DO (
IF !PRINT!==0 IF "%%0"=="[印刷ジョブ]" SET PRINT=1
IF !PRINT!==1 ECHO=%%0
)
DEL $$$.txt

縦長に並べて表示します。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
START /W MSINFO32.EXE /categories +SWEnvPrint /report $$$.txt
SET PRINT=0
FOR /F "tokens=1-18 delims= " %%a IN ('TYPE $$$.txt') DO (
IF !PRINT!==2 (
ECHO !Ha!  %%a
ECHO !Hb!   %%b
ECHO !Hc!   %%c
ECHO !Hd!   %%d
ECHO !He!   %%e
ECHO !Hf!  %%f
ECHO !Hg!  %%g
ECHO !Hh!  %%h
ECHO !Hi!  %%i
ECHO !Hj! %%j
ECHO !Hk!  %%k
ECHO !Hl!   %%l
ECHO !Hm!  %%m
ECHO !Hn!  %%n
ECHO !Ho!  %%o
ECHO !Hp! %%p
ECHO !Hq!  %%q
ECHO !Hr!   %%r
ECHO=
)
IF !PRINT!==1 (
SET Ha=%%a
SET Hb=%%b
SET Hc=%%c
SET Hd=%%d
SET He=%%e
SET Hf=%%f
SET Hg=%%g
SET Hh=%%h
SET Hi=%%i
SET Hj=%%j
SET Hk=%%k
SET Hl=%%l
SET Hm=%%m
SET Hn=%%n
SET Ho=%%o
SET Hp=%%p
SET Hq=%%q
SET Hr=%%r
SET PRINT=2
)
IF !PRINT!==0 IF "%%a"=="[印刷ジョブ]" (
ECHO=%%a
ECHO=
SET PRINT=1
)
)
DEL $$$.txt

2007年1月 1日 (月)

HTAでmoveTo/resizeToと<hta:application>タグの位置関係

<hta:application>タグに表示に関する属性があるので、
<hta:application>タグを読み込むまで、HTAは表示されません。

なので、もし、<hta:application>タグがないと、HTMLをすべて読み込むまで、
HTAは表示されず、HTMLをすべて読み込んだところで表示されます。
読み込み途中でclose()していると、最後に一瞬表示してから消えます。
これはclose()前にresizeTo(0,0)しておけば目立ちません。

<hta:application>タグより後でmoveTo/resizeToすると、
HTAを一旦、デフォルトのサイズと位置で表示してから、指定のサイズと位置に変わります。

最初から指定のサイズと位置で表示するには、
moveTo/resizeToを<hta:application>タグより前に記述します。

« 2006年12月 | トップページ | 2007年2月 »