ばんのしゃーによかばんた さん 2005年 07月 13日 18時 30分 15秒

迂闊にも知らなかったのですが、
スクリプトエンコードって日本語がスルーなんですね。常識でした?

しかし、嘘みたい。これじゃ英語圏外で使いものにならないじゃないですか。
一体、何を考えているんでしょうね。全く。ブツブツ。。。

>管理人むたぐち さん 2004年 07月 26日 16時 01分 08秒
>To: Perlすくりぷたー さん
>> VBSやJSだとVBEやJEに暗号化できるみたいですが、
>>Perlのコードを同様に暗号化することは出来ないでしょうか?
>おそらくScript EncoderはPerlScriptには対応していないので
>無理なんじゃないでしょうか。

vbscript.dllなどを見ると、スクリプトエンジンがエンコードを
ゴリゴリ意識してるみたいですね。ということはやっぱり無理かな。


ばんのしゃーによかばんた さん 2005年 07月 13日 18時 29分 52秒

>管理人むたぐち さん 2005年 07月 11日 18時 19分 27秒
>名前欄の文字化け訂正しておきました。

すみませんね。前があるのにまたやってしまいました。
スクリプトエンコード結果を貼ると、日時〜投稿者〜日時のあたりだけ
EUCになります。なんででしょう。EUCと誤解されそうな文字はないのに。

>つちや さん 2005年 07月 10日 21時 14分 27秒
>それよりも、xdoc2txtが便利なので、PDFからのテキスト抽出はxdoc2txtをWSHから利用しています。

中身は取り出せますが、タイトルは駄目みたいです。

※Acrobat.ReaderのCOMで、それぐらいサポートしたって損はないと思うんですが、
なんかAdobeは、けち臭いような。


のぽぽん さん 2005年 07月 13日 14時 13分 03秒

>ちゃっぴさん お返事ありがとうございます。

ちゃっぴさんのコード
>Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
の箇所でエラーが発生するのですが (*ソース null)何か新しいサービスを起動させないといけないのでしょうか。

WMICなら使用可の状態です。

ちゃっぴ さん 2005年 07月 13日 12時 49分 53秒

To のぽぽん さん 2005年 07月 13日 10時 52分 11秒

> tasklist /S ("PC名称") /FI "imagename eq ("検索文字列") >&2 ("ログ")

Windows の help で Redirector の使い方勉強しましょう。

tasklist /S ("PC名称") /FI "imagename eq ("検索文字列") > ("ログ") 2>&1

> 本来の処理は、処理対象端末で特定のタスクが実行されているかどうか、判定したいんです。

ということであれば、Error処理まで考慮するとWMI使ったほうがいいでしょうね。


strComputer = "hogehoge"
strProcess = "hogehoge.exe"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery( _
  "SELECT * FROM Win32_Process Where Name='" & strProcess & "'")

If colItems.Count > 0 Then
  WScript.Echo "あり"
Else
  WScript.Echo "なし"
End If

ちゃっぴ さん 2005年 07月 13日 11時 37分 37秒

> サンプルでは埋め込み型になっていますが、実際にはScriptを実行する
> VB.NETアプリからパラメタとして渡す予定です。

なんで、.NET使うのにそんな面倒なことをするのでしょうか?
素直にUser偽装させてやればいいのでは?

> しかし、随時起動の必要があり、予めスケジュール出来る利用形態ではないのです。

右クリックして「タスクの実行」で実行できます。
XP以降であれば、SCHTASKS.EXE という
CommandLine Toolも付属します。

のぽぽん さん 2005年 07月 13日 10時 52分 11秒

書き込みに追記します。

tasklistの結果をテキストファイルに吐き出す処理は出来ていました。すみません。
(*予想していたのと違うディレクトリに出来ていて・・・ 100以上もファイルが
作成されていたので驚きました)

本来の処理は、処理対象端末で特定のタスクが実行されているかどうか、判定したいんです。

コマンドラインのコマンド
tasklist /S ("PC名称") /FI "imagename eq ("検索文字列") >&2 ("ログ")
を利用したいと考えています。ところが下記のコードで &2というテキストファイルが作成されます。tasklist /FI の結果が出力されません。

ans = wshShell.Run ("tasklist.exe /s " & strHost & " /fi """imagename eq & """ & strTask """ >&2" & strTxt ,0,true)

よろしくお願いします。

KEN さん 2005年 07月 13日 09時 36分 32秒

To ちゃっぴ さん 2005年 07月 12日 23時 30分 27秒

> この手の質問は多いですが、ScriptにPasswordを埋め込むこと自体が
> Security Hole です。
その通りですね。
サンプルでは埋め込み型になっていますが、実際にはScriptを実行するVB.NETアプリからパラメタとして渡す予定です。また、VB.NETアプリでもパスワードをプログラム内に記述しないようにする予定です。(ややこしいので詳細は省略します)

> なので、そういう手段はScript側で実施せずに、OSの機能を
> 利用されることをお勧めします。
>
> 具体的には TaskScheduler がありますので、そこに通常と異なる
> Accountで登録して実行するようにしてやればよいでしょう。
定期的に実行されるような処理はこれで可能ですね。
しかし、随時起動の必要があり、予めスケジュール出来る利用形態ではないのです。

また、お知恵を拝借できませんでしょうか。

ちゃっぴ さん 2005年 07月 12日 23時 30分 27秒

> Scriptからrunasコマンドを投入し、パスワードを自動入力させてたいと考えています。

この手の質問は多いですが、ScriptにPasswordを埋め込むこと自体が
Security Hole です。

最低限、ばんのしゃーによかばんた さん が書いている Sample のように
暗号化してやらなければならないでしょうが、それを行うのもScript
でしたら、容易に解析されてしまうでしょう。

なので、そういう手段はScript側で実施せずに、OSの機能を
利用されることをお勧めします。

具体的には TaskScheduler がありますので、そこに通常と異なる
Accountで登録して実行するようにしてやればよいでしょう。

ちゃっぴ さん 2005年 07月 12日 23時 22分 46秒

To のぽぽん さん 2005年 07月 12日 19時 57分 42秒

> コマンドラインのコマンド tasklistの結果をテキストファイルに
> 出力したいのですがうまくいきません

こういった場合、どのようになってうまくいかなかったかを示すことが
必須となります。次回から気をつけましょう。

とりあえず、確認するところとしては、
Command Promptで実行した場合はうまくいくか?

うまくいくのであれば、Run Methodで渡す文字列を
事前に出力させ、Command Promptと異なっている箇所を見比べる。

ちなみにProcessの一覧でしたら、WMIをつかって取得できますね。
こちらのほうが細かい処理が可能ですので、Scriptには向いているでしょう。

Scriptomatic 2.0
http://www.microsoft.com/japan/technet/scriptcenter/tools/scripto2.mspx

これをDLして「Win32_Process」Classを調べてみてください。

KEN さん 2005年 07月 12日 22時 25分 08秒

Scriptからrunasコマンドを投入し、パスワードを自動入力させてたいと考えています。
過去ログで解説されているように、runメソッドで実行した場合は成功するのですが、execメソッドで実行すると失敗します。(runasコマンドが失敗した時のエラーを拾いたくて、execメソッドを使用しています)
事象としては、runasコマンド自体は起動されているものの、パスワードの入力を待つことなく、すぐに終了してしまうという状況です。
なぜ、そう判断しているかというと・・・
・下記のScriptを実行した際に、パスワードの入力を促すメッセージがStdOutに出力されている 
・タスクマネージャーを監視していると、runasが一瞬だけ表示されて消えてしまう 
という点からです。
runasコマンドの投入方法に問題があるのかと思い、cmd.exe経由で起動したりもしましたが結果は同じでした。
初心者なので知識不足な点はありますが、お知恵を拝借出来ませんでしょうか?

==================================================================
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExec = objShell.Exec("runas.exe /profile /user:administrator@myoffice notepad.exe")
'''テスト Set objExec = objShell.Exec("cmd.exe /c ""runas.exe /profile /user:administrator@myoffice notepad.exe""")

WScript.Sleep 1000

strLine = objExec.StdOut.ReadLine
WScript.Echo strLine
objExec.StdIn.WriteLine "admin"
==================================================================

のぽぽん さん 2005年 07月 12日 19時 57分 42秒

VBS初心者です。どなたかご存知でしたら教えてください。

コマンドラインのコマンド tasklistの結果をテキストファイルに出力したいのですがうまくいきません。

ans = wshShell.Run ("tasklist.exe /s " & strHost & " >> 20050712163001OUT1.txt" , 0, true )
もしくは・・
ans = wshShell.Run ("cmd.exe /C tasklist /s " & strHost & " >> 20050712163001OUT1.txt" , 0, true )

どなたかご存知でしたら教えてください。

管理人むたぐち さん 2005年 07月 11日 18時 19分 27秒

名前欄の文字化け訂正しておきました。
本文は化けているのかどうかよくわかりませんでした(汗

To: megu さん

同じ環境ですが、こちらでは動作します。
ばんのしゃーによかばんたさんのおっしゃるように
カレントディレクトリのチェックをしてみてください。

UIHelperオブジェクトのImportExportFavoritesメソッドは
XP SP2の環境では使えなくなっているようです。

ばんのしゃーによかばんた さん 2005年 07月 11日 14時 50分 08秒

■.VBSを.CMD/.BATに変えて実行する方法です。

/*<!--
ここに.VBSの中身を入れる。
-->*/

※これでやっとEchoなしのすっきり完成形。

VBS2JS.CMD Windows2000/XP用
――――――――――――――――――――――――――――――――――――――
@set @_=0//&CScript.EXE //E:JScript //NoLogo "%~f0" %*&GOTO :EOF
var fso=new ActiveXObject("Scripting.FileSystemObject");
var src=fso.OpenTextFile(WScript.ScriptFullName).ReadAll();
src=src.match(/\/\*<!--([\s\S]*)-->\*\//m)[1];//WScript.Echo(src);
var SC=new ActiveXObject('ScriptControl');SC.Language='VBScript';
SC.AllowUI=true;SC.TimeOut=-1;SC.AddObject('WScript',WScript,true);
try{SC.ExecuteStatement(src);}catch(e){
WScript.Echo(new Array("Error:\t"+e,"Number:\t"+SC.Error.Number,
"Description:\t"+SC.Error.Description,"Source:\t"+SC.Error.Source,
"Text:\t"+SC.Error.Text,"Line:\t"+SC.Error.Line,
"Column:\t"+SC.Error.Column).join('\n'));WScript.Quit(SC.Error.Number);}
/*<!--
Set wShell=CreateObject("WScript.Shell")
rows=Array(wShell.CurrentDirectory,"")
For Each arg In WScript.Arguments
 ReDim Preserve rows(UBound(rows)+1)
 rows(UBound(rows))="'"&arg&"'"
Next
WScript.Echo Join(rows,vbLf)
Err.Raise 100
-->*/
――――――――――――――――――――――――――――――――――――――

VBS2JS.BAT Windows98/ME用
――――――――――――――――――――――――――――――――――――――
@set @_=0/*
@ECHO OFF
IF '%1'==':' GOTO :SUB
SET ?=
IF EXIST %0 SET ?=%0
IF NOT '%?%'=='' GOTO :FOUND
IF EXIST %0.BAT SET ?=%0.BAT
IF NOT '%?%'=='' GOTO :FOUND
FOR %%0 IN (%PATH%) DO CALL %0 : %%0\%0
IF NOT '%?%'=='' GOTO :FOUND
FOR %%0 IN (%PATH%) DO CALL %0 : %%0\%0.BAT
IF NOT '%?%'=='' GOTO :FOUND
ECHO %0 NOT FOUND.
GOTO :EOF
:FOUND
CScript.EXE //E:JScript //NoLogo %?% %1 %2 %3 %4 %5 %6 %7 %8 %9
GOTO :EOF
:SUB
IF NOT '%?%'=='' GOTO :EOF
IF EXIST %2 SET ?=%2
GOTO :EOF */
var fso=new ActiveXObject("Scripting.FileSystemObject");
var src=fso.OpenTextFile(WScript.ScriptFullName).ReadAll();
src=src.match(/\/\*<!--([\s\S]*)-->\*\//m)[1];//WScript.Echo(src);
var SC=new ActiveXObject('ScriptControl');SC.Language='VBScript';
SC.AllowUI=true;SC.TimeOut=-1;SC.AddObject('WScript',WScript,true);
try{SC.ExecuteStatement(src);}catch(e){
WScript.Echo(new Array("Error:\t"+e,"Number:\t"+SC.Error.Number,
"Description:\t"+SC.Error.Description,"Source:\t"+SC.Error.Source,
"Text:\t"+SC.Error.Text,"Line:\t"+SC.Error.Line,
"Column:\t"+SC.Error.Column).join('\n'));WScript.Quit(SC.Error.Number);}
/*<!--
Set wShell=CreateObject("WScript.Shell")
rows=Array(wShell.CurrentDirectory,"")
For Each arg In WScript.Arguments
 ReDim Preserve rows(UBound(rows)+1)
 rows(UBound(rows))="'"&arg&"'"
Next
WScript.Echo Join(rows,vbLf)
Err.Raise 100
-->*/ /*
:EOF */
――――――――――――――――――――――――――――――――――――――
Windows98/MEのバッチファイルでリダイレクションパイプを使うときは、
Command/cVBS2JS.BAT
で。

※WindowsXPのCommand.comは、Windows98のCommand.comとも、
XPのCMD.EXEとも、互換がなくて困りますが、
バッチファイルでリダイレクションパイプが使えますね。
中間的なのかな。


つちや さん 2005年 07月 10日 21時 14分 27秒

ごぶさたしております。
■PDFからCOMを抽出するCOMの件
>そのCOMって、PDFからテキストが抽出できるって云う物でしょうか?
>それって、どうやるんでしょう? タイトルも取り出せます?
 以前PDFからテキストを抽出するCOMも作ってみましたが、抽出の部分はインターネットで見つけたソースを使ってましたので、詳細がわかってないです。そのソースも公開停止になりライセンスがよくわからないので、その後使ってないです。
 それよりも、xdoc2txtが便利なので、PDFからのテキスト抽出はxdoc2txtをWSHから利用しています。
http://www31.ocn.ne.jp/~h_ishida/xdoc2txt.html

>確かに従来は、そうでしたが、今となっては、むたぐちさんのSjisString.jsのように、
>.NETでちょろちょろっと作るのほうが、広範な環境で使えてよいのでは?
 これは意見のわかれる所と思うのですが、まだまだ私の周りは.NETが使える状態にないのです。標準装備となったOSが大部分ということになればそうすると思いますが、その時は、Delphi.NETの利用をまず考える可能性も。実は未だに.NETを試したことがないもので。

■137-29(2005年 07月 08日 14時 22分 28秒)の文字化けの件
 ここのタイトルが文字化けしていますが、これってもう訂正できませんか。wshbbs.vbsで保存しようとすると最近エラーが出てしまうのですが、ここのタイトル(というか時刻)が原因のような気がするのです。

ばんのしゃーによかばんた さん 2005年 07月 10日 15時 44分 34秒

>megu さん 2005年 07月 09日 20時 11分 12秒
>ダウンロードコーナーにある[IEのお気に入りをHTML化]を実行しましたが、
>done.と表示されて、ファイルが作成されませんでした。

どうやって実行されました?
カレントディレクトリが違うのでは?

「お気に入り」や「リンク」から実行したのではありませんか?

以下を同じところにおいて、同じように実行すれば、
カレントディレクトリや引数がどういう風に渡っているか、分かります。

Args.VBS or CurrentDirectory.VBS
――――――――――――――――――――――――――――――――――――――
Set wShell=CreateObject("WScript.Shell")
rows=Array(wShell.CurrentDirectory,"")
For Each arg In WScript.Arguments
 ReDim Preserve rows(UBound(rows)+1)
 rows(UBound(rows))="'"&arg&"'"
Next
WScript.Echo Join(rows,vbLf)
――――――――――――――――――――――――――――――――――――――

>ImportExportFavorites インターフェイスが使えないのかなぁ・・・。

あれ? 使ってないのでは?


ばんのしゃーによかばんた さん 2005年 07月 10日 15時 12分 50秒

こういう位置指定MsgBoxは如何でしょうか?

MsgBoxPosMSHTA.VBS (Modal)
――――――――――――――――――――――――――――――――――――――
Text="text"
Button=vbOkOnly
Title=WScript.ScriptName
ToLeft=45
ToUp=38
WScript.Echo MsgBoxPos(Text,Button,Title,ToLeft,ToUp)

Function MsgBoxPos(Text,Button,Title,ToLeft,ToUp)
CreateObject("WScript.Shell").Run "MSHTA.EXE vbscript:Execute(""T="""""&Title&""""":Set wShell=CreateObject(""""WScript.Shell""""):P:Sub P():If wShell.AppActivate(T) Then:setTimeout """"Q"""",100:Else:setTimeout """"P"""",100:End If:End Sub:Sub Q:wShell.SendKeys """"%( m){Left " & ToLeft & "}{Up " & ToUp & "}{Enter}"""":close():End Sub"")",0
MsgBoxPos=MsgBox(Text,Button,Title)
End Function

ToLeft=43
ToUp=37
――――――――――――――――――――――――――――――――――――――

MsgBoxPosIE.VBS (Modeless)
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
 WScript.Sleep 100
Loop
ie.Document.parentWindow.status=0
Call ie.Document.parentWindow.setTimeout("status=MsgBox(""なんとかかんとか"",vbSystemModal+vbQuestion+vbYesNo,"""&WScript.ScriptName&""")",10,"VBScript")

Set wShell=CreateObject("WScript.Shell")
Do While Not wShell.AppActivate(WScript.ScriptName)
 WScript.Sleep 100
Loop
wShell.SendKeys "%( m){Left " & ToLeft & "}{Up " & ToUp & "}{Enter}"

Do While ie.Document.parentWindow.status=0
 WScript.Sleep 1000
Loop
RC=ie.Document.parentWindow.status
ie.Quit
MsgBox RC
――――――――――――――――――――――――――――――――――――――


megu さん 2005年 07月 09日 20時 11分 12秒

ダウンロードコーナーにある[IEのお気に入りをHTML化]を実行しましたが、
done.と表示されて、ファイルが作成されませんでした。
OS:XP sp2
IE6 sp2

ImportExportFavorites インターフェイスが使えないのかなぁ・・・。

ばんのしゃーによかばんた さん 2005年 07月 09日 15時 19分 17秒

>つり さん 2005年 07月 06日 16時 46分 25秒
>Runメソッドを使い、アプリケーションを起動した後に、
>左右に並べて表示などではなく
>細かくウィンドウサイズの変更、ウィンドウを表示させる位置の変更
>をする方法はありませんでしょうか?

第3の方法として、こういうのもありました。

>ばんのしゃーによかばんた さん 2004年 05月 04日 16時 30分 44秒
>WSHからExcel経由でWin32APIを使う方法。改訂第3版。

しかし、時代は.NETなので、.NETでCOMオブジェクト化したほうがよいのでは
ありませんか? 使い回しが利いて無駄になりませんから。

詳細は過去記事参照。

>ばんのしゃーによかばんた さん 2005年 07月 02日 16時 25分 26秒
>VB.NETでちょこちょこっと作ってみました。
>今度はWin32APIのBeep()です。
>BeepWin32.VB

やりかたは同じ。それを繰り返すだけ。

で、やってみました。第4の方法。

Win32API.VB
――――――――――――――――――――――――――――――――――――――
Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices

Namespace Win32API

Public Class Win32

Private Declare Function xBeep Lib "Kernel32.DLL" Alias "Beep" (ByVal dwFreq As Integer, ByVal dwDuration As Integer) As Integer

Public Function Beep(ByVal dwFreq As Integer, ByVal dwDuration As Integer) As Integer
Beep=xBeep(dwFreq, dwDuration)
End Function

Private Declare Function xFindWindow Lib "User32.DLL" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

Public Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
If lpClassName = "" Then lpClassName = vbNullString
If lpWindowName = "" Then lpWindowName = vbNullString
FindWindow = xFindWindow(lpClassName, lpWindowName)
End Function

Private Declare Function xSetForegroundWindow Lib "User32.DLL" Alias "SetForegroundWindow" (ByVal hwnd As Integer) As Integer

Public Function SetForegroundWindow(ByVal hwnd As Integer) As Integer
SetForegroundWindow = xSetForegroundWindow(hwnd)
End Function

Private Declare Sub xSleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Integer)

Public Sub Sleep(ByVal dwMilliseconds As Integer)
Call xSleep(dwMilliseconds)
End Sub

Private Declare Sub xkeybd_event Lib "User32.DLL" Alias "keybd_event" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)

Public Sub keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Call xkeybd_event(bVk, bScan, dwFlags, dwExtraInfo)
End Sub

Private Declare Function xGetWindow Lib "User32.DLL" Alias "GetWindow" (ByVal hwnd As Integer, ByVal wCmd As Integer) As Integer

Public Function GetWindow(ByVal hwnd As Integer, ByVal wCmd As Integer) As Integer
GetWindow = xGetWindow(hwnd, wCmd)
End Function

Private Declare Function xGetWindowText Lib "User32.DLL" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As  System.Text.StringBuilder, ByVal cch As Integer) As Integer

Public Function GetWindowText(ByVal hwnd As Integer) As String
Dim lngBytes As Integer
Dim sb As New System.Text.StringBuilder(256)
lngBytes = xGetWindowText(hwnd, sb, sb.Capacity + 1)
Return sb.ToString()
End Function

Private Declare Function xIsWindowVisible Lib "User32.DLL" Alias "IsWindowVisible" (ByVal hwnd As Integer) As Integer

Public Function IsWindowVisible(ByVal hwnd As Integer) As Integer
IsWindowVisible = xIsWindowVisible(hwnd)
End Function

Private Declare Function xGetClassName Lib "User32.DLL" Alias "GetClassNameA" (ByVal hwnd As Integer, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer

Public Function GetClassName(ByVal hwnd As Integer) As String
Dim lngBytes As Integer
Dim sb As New System.Text.StringBuilder(256)
lngBytes = xGetClassName(hwnd, sb, sb.Capacity + 1)
Return sb.ToString()
End Function

Private Declare Function xGetTopWindow Lib "User32.DLL" Alias "GetTopWindow" (ByVal hwnd As Integer) As Integer

Public Function GetTopWindow(ByVal hwnd As Integer) As Integer
GetTopWindow = xGetTopWindow(hwnd)
End Function

Private Declare Function xGetDesktopWindow Lib "User32.DLL" Alias "GetDesktopWindow" () As Integer

Public Function GetDesktopWindow() As Integer
GetDesktopWindow = xGetDesktopWindow()
End Function

Private Declare Function xGetWindowThreadProcessId Lib "User32.DLL" Alias "GetWindowThreadProcessId" (ByVal hwnd As Integer, lpdwProcessId As Integer) As Integer

Public Function GetWindowThreadProcessId(ByVal hwnd As Integer, lpdwProcessId As Integer) As Integer
GetWindowThreadProcessId = xGetWindowThreadProcessId(hwnd, lpdwProcessId)
End Function

Private Declare Function xShowWindow Lib "User32.DLL" Alias "ShowWindow" (ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer

Public Function ShowWindow(ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer
ShowWindow = xShowWindow(hwnd, nCmdShow)
End Function

Private Declare Function xSetWindowPos Lib "User32.DLL" Alias "SetWindowPos" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer

Public Function SetWindowPos(ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
SetWindowPos = xSetWindowPos(hwnd, hWndInsertAfter, x, y, cx, cy, wFlags)
End Function

Private Declare Function xGetWindowLong Lib "User32.DLL" Alias "GetWindowLongA" (ByVal hwnd As Integer, ByVal nIndex As Integer) As Integer

Public Function GetWindowLong(ByVal hwnd As Integer, ByVal nIndex As Integer) As Integer
GetWindowLong = xGetWindowLong(hwnd, nIndex)
End Function

Public Function GetError() As Object
GetError = Err
End Function

End Class 'Win32

End NameSpace 'Win32API
――――――――――――――――――――――――――――――――――――――
vbc /t:library Win32API.VB

Win32API.DLLをC:\Windows\System32にコピーして、

regasm Win32API.DLL

SetWindowPos.VBS
――――――――――――――――――――――――――――――――――――――
Option Explicit

Dim Win32API
Set Win32API=CreateObject("Win32API.Win32")

Dim Title
Dim ClassName

ClassName=""
Title=WScript.Arguments(0)

Dim hWnd
Dim tid
Dim pid
Dim hInstance
Const GWW_HINSTANCE = (-6)
Const GWW_ID = (-12)
Const GWL_STYLE = (-16)

hWnd=Win32API.FindWindow(ClassName,Title)
'tid=Win32API.GetWindowThreadProcessId(hwnd,pid)
'ClassName=Win32API.GetClassName(hwnd)
'hInstance=Win32API.GetWindowLong(hwnd,GWW_HINSTANCE)
'WScript.Echo hInstance
'Title=Win32API.GetWindowText(hwnd)
'WScript.Echo hwnd,pid,ClassName,Title

Const HWND_BOTTOM = 1
Const HWND_BROADCAST = &HFFFF&
Const HWND_DESKTOP = 0
Const HWND_NOTOPMOST = -2
Const HWND_TOP = 0
Const HWND_TOPMOST = -1

Const SWP_DRAWFRAME = &H20     'SWP_FRAMECHANGED
Const SWP_FRAMECHANGED = &H20    ' The frame changed: send WM_NCCALCSIZE
Const SWP_HIDEWINDOW = &H80
Const SWP_NOACTIVATE = &H10
Const SWP_NOCOPYBITS = &H100
Const SWP_NOMOVE = &H2
Const SWP_NOOWNERZORDER = &H200   ' Don't do owner Z ordering
Const SWP_NOREDRAW = &H8
Const SWP_NOREPOSITION = &H200      'SWP_NOOWNERZORDER
Const SWP_NOSIZE = &H1
Const SWP_NOZORDER = &H4
Const SWP_SHOWWINDOW = &H40

Dim fSuccess
fSuccess=Win32API.SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 100, 200, 0)
If fSuccess=0 Then
 Dim Error
 Set Error=Win32API.GetError
 WScript.Echo "Source:",Error.Source,"Number:",Error.Number,Error.Description,"DLL Error:",Error.LastDLLError
End If
――――――――――――――――――――――――――――――――――――――



つり さん 2005年 07月 09日 14時 00分 49秒

管理人むたぐちさん、返信どうもありがとうございます。
教えていただいた事を参考に、色々弄ってみたいと思います。

せい さん 2005年 07月 09日 01時 04分 01秒

直前の記事は
>>魔界の仮面弁士 さん 2005年 07月 07日 00時 38分 35秒
宛てでした。コピペが先頭だけ切れてしまった。

せい さん 2005年 07月 09日 00時 56分 41秒

>>最初から、では無いと思いますよ。このような記事もありますし。
よく確かめず申し訳ありませんでした。仰る通りRegExpとExecuteは
5.0の時に同時に導入されています(SDKドキュメントのVbscript Version Informationで
確認)。
今後体調悪い時は自粛します。



>>すみません……いまだ、問題点を理解できていません。m(_ _;)m
体調が落ち着いたので なんですれ違ってるのか読み返し確認したところ根本的な
私の勘違いがありました。[ ]で囲んだ予約語のメンバを参照する実験でエラーを
出したことがあったので予約語メンバ名は出来ないものと思いこんでいたのです。
確かめもせず長々と変なこと言って本当にすいませんでした。


ちなみにVbscript.dllをOLEViewerで見てみるとステートメントとされているのは
以下の四つだけのようです。

Randomize
Erase
Execute
ExecuteGolbal

中を覗くと関数はおろか全てがVARIANTなことにちょっとがっかり(当然だけど)


>># 無理に名前を衝突させるなら、『Sub Execute()』のようなプロシージャを自分で実装したり、

ステートメントキーワードが必ずしも予約語で構成されていないのは理解してますが、
一般的にステートメントと同等の機能(普通は文とか呼ばれる)は書き換えできない
ように言語仕様で保護していると考えるのが通例だと思います。不作為に書き換えて
しまう可能性を考慮するとステートメントの機能はメソッドで提供すべきではなかった、
と言いたいところですが もうそうなってるからどうにもならん。



>>スコープの実験。クラス内で定義できないという点が異なりますね。

ClassブロックでConst定義できないことは知っていましたがドキュメントには
はっきり書いてなかったんですね。スクリプトレベルとプロシージャレベルで
使うとは書いてありますがClassブロックの記述がないから使えん、っつーのは
納得できないところです。



またちょっと笑わさせていただきました。[ ]で囲めばなんでもOK的なことが
ドキュメントには書いてありますが一部のコントロール文字や ] はやっぱり
ダメでした。括弧内に識別子を要求するVB.NETとは違うようです。

Dim []
[]=1
Msgbox []


ばんのしゃーによかばんた さん 2005年 07月 08日 14時 22分 28秒

こんなことも。VBScriptをバッチファイル化します。

VBSをCScript.EXEで簡単に起動したいときなどに使えます。

usage: args.cmd [args...]
――――――――――――――――――――――――――――――――――――――
:#@~^9gAAAA==jY~S?4+V^';.+mYnr(Ln^D`JqjmMkwD jtV^Jb@#@&.Khd'z.DmXcAUt+sscZ;DMn     Y9bDmYKDH'\(Z.S6#@#@&wWD,3l1tPm.LP&x,jm.raY bMLEs+UOk@#@&~~"+9ks~hDnk+M\+,DKA/vj$W!x[cMWhkb_8#@#@&~~DKhk`iAG;     NcDKA/*#xEEJ[C.T[EBr@#@&1nXY@#@&UmMrwDR3m4W~BKkxv.WS/~78/Dd0*@#@&oUwAAA==^#~@

@CScript.EXE //E:VBScript.Encode "%~f0" %*
@WScript.EXE //E:VBScript.Encode "%~f0" %*
――――――――――――――――――――――――――――――――――――――
注) 1行目(encoded vbscript)の末尾(==^#^@の後)にNUL文字を追加してください。

或いは、
――――――――――――――――――――――――――――――――――――――
:Set wShell=CreateObject("WScript.Shell")
:rows=Array(wShell.CurrentDirectory&vbLf)
:For Each arg In WScript.Arguments
: ReDim Preserve rows(UBound(rows)+1)
: rows(UBound(rows))="'"&arg&"'"
:Next
:WScript.Echo Join(rows,vbLf)
: ←ここにNUL文字を追加してください。

@CScript.EXE //E:VBS "%~f0" %*
@WScript.EXE //E:VBS "%~f0" %*
――――――――――――――――――――――――――――――――――――――

スクリプトエンジンは、null terminated stringを渡されるのが
インタフェース仕様のようです。
なので、スクリプトファイル中にNUL文字があると、
NUL文字以降が無視されるようです。


ばんのしゃーによかばんた さん 2005年 07月 08日 14時 22分 12秒

■二重起動防止サンプル

なんか需要があるみたいなので、
汎用ロック機構を二重起動防止専用に特化してみました。

甲案     一般向け
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim fso
Dim LockFilePath
Dim Lock

Set fso=CreateObject("Scripting.FileSystemObject")
LockFilePath=Join(Array(fso.GetSpecialFolder(0).Path,"Temp",WScript.ScriptName & ".LOCK"),"\")
On Error Resume Next
fso.DeleteFile LockFilePath
Err.Clear
Set Lock=fso.CreateTextFile(LockFilePath)
If Err Then Set Lock=Nothing
On Error GoTo 0
If Lock Is Nothing Then
 WScript.Echo "Failed."
 WScript.Quit
End If
WScript.Echo "OK."
' Main Process
WScript.Quit
――――――――――――――――――――――――――――――――――――――

乙案     簡略。勝手にエラーメッセージが出る。
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim fso
Dim Lock

Set fso=CreateObject("Scripting.FileSystemObject")
Set Lock=fso.OpenTextFile(WScript.ScriptFullName,8)
MsgBox "OK"
' Main Process
WScript.Quit
――――――――――――――――――――――――――――――――――――――
エラーメッセージはスクリプトから抑止できない。
WScript.EXE //Bで抑止できる。


ばんのしゃーによかばんた さん 2005年 07月 08日 14時 21分 49秒

>ばんのしゃーによかばんた さん 2005年 07月 06日 20時 47分 55秒
>早い話、
>ファイル名をhoge.JSEとして実行すればよい訳です。

/* */コメントを使っているので、中で/* */コメントを使っていると
構文エラーになります。

そこで、
VBE用は/* */で囲む。
JSE用は/* */で囲まない。
という使い分けが必要です。

しかし、スクリプトエンコードがこんなに簡単にデコード出来るなんて
ちょっと信じられませんね。これを知ったら、使う気がしなくなりそう。

デコードをスクリプトで作ってみようかなんて思ったりもしましたが、
作らなくてよかった。もし作ってたら地団駄踏んでますね。

これは、BASE64でエンコードするのと大して変わりませんね。
>ばんのしゃーによかばんた さん 2005年 07月 05日 16時 54分 14秒
>■情報を隠してスクリプトを実行する方法の別案。

UTF-7はエンコード時に英数字等、一部の文字をそのまま残すので、
スクリプトがほとんど丸見えになります。
すべての文字をBASE64でエンコ−ドしてやれば、スクリプトが見えなくなります。
UTF-7のデコードはエンコード時の文字の範囲に関係なく出来るので、
BASE64のエンコ−ド結果を+-で挟んものを、UTF-7だと言ってやればよいわけです。
改行くらいは、残したほうがよいかも。
ばんのしゃーによかばんた さん 2005年 07月 06日 20時 47分 55秒


管理人むたぐち さん 2005年 07月 08日 08時 13分 32秒

To: つり さん

> Runメソッドを使い、アプリケーションを起動した後に、
> 左右に並べて表示などではなく
> 細かくウィンドウサイズの変更、ウィンドウを表示させる位置の変更
> をする方法はありませんでしょうか?

残念ながらWSHの標準機能では、フォルダ/IEのウィンドウしかできません。
# その場合Shell.Application, Windowsメソッドをお調べください。

外部のCOMコンポーネントを使うならAutoItX(http://www.hiddensoft.com/AutoIt/)
等が使えるでしょう。ただしこれではウィンドウの位置は指定できても、
サイズは指定できないようです。

WSH+DynaCall(http://ourworld.compuserve.com/homepages/Guenter_Born/index0.htm)を使い、
SetWindowPos関数というWin32API関数を用いると、サイズも位置も
変更できます。

詳しくは、
http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list52.shtml
管理人むたぐち さん (mutaguchi@roy.hi-ho.ne.jp) 2001年 11月 18日 21時 10分 01秒
をどうぞ。

TAK さん 2005年 07月 07日 21時 35分 02秒

管理人むたぐち さま
お忙しい所、ありがとうございました。
SENDKEYS方式参考にさせていただきます。

WSHではAPIが使えないので、VBAにして
やろうかなと思っておりました。

魔界の仮面弁士 さん 2005年 07月 07日 00時 38分 35秒

》せい さん 2005年 07月 06日 02時 32分 48秒
> その開発目的はMicrosoft自身が開発したスクリプトへの
> 正規表現処理機能の付加だと思っています
でしょうね。

VBScriptにおける RegExp については、JScript 程スマートに書けないのは残念ですが、
Like演算子を持たない VBS には、それでも非常に便利な機能です。(^-^)


> スクリプトのような簡便さを求める言語に対して開発元が
> [ ]を使わなければ扱えないようなメンバ名を 新規導入する
> オブジェクトに設定することは開発元が取る行動では無いと
すみません……いまだ、問題点を理解できていません。m(_ _;)m

この場合の『[ ]を使わなければ扱えないようなメンバ名』とは、
具体的には、どのオブジェクト の 何というメソッドの事でしょうか?



> 識別子が衝突することを最初から想定していたから[ ]を
> 言語仕様に含めたのは理解できますが、これは例外的な
> 扱いのはずです。
そうですね。確かに角かっこ表現は、例外的な扱いだと思います。
実際に使用する必要があるのは、『予約語』や『空白を含むメンバ名』などですが、
こうした名前を必要になる事は、さほど多くありませんので。


ちなみに、角かっこの利用については、予約語 Loop がコントロール名として使われた場合の
  [Loop].Visible = True
という例文に対する説明として、VB6/VB.NET のヘルプに以下の記述を見る事ができます。

|
|[VB6]『コーディングの基礎』
|
| 予約キーワードと角かっこが使えるのは、予約キーワードと
| 同じ名前のフォームやコントロールを参照する場合です。ただし、
| 変数の宣言やプロシージャの名前には、角かっこを付けても、
| 予約キーワードと同じ名前を使うことはできません。角かっこは、
| ほかのタイプ ライブラリで定義されている予約キーワードと同じ名前を、
| Visual Basic で使用するときにも使います。
| メモ: 一般には、フォーム名やコントロール名に予約キーワードは
| 使いません。角かっこを使って参照する方法は、Visual Basic の
| 将来のバージョンで新しく定義されたキーワードが、既存の
| アプリケーションで使われているフォーム名やコントロール名と重複する
| 場合などに使うことができます。このことにより、新しいバージョンに
| 既存のアプリケーションを対応させることができます。
|

|
|[VB.NET]『コード内の要素名としてのキーワード』
|
| フォームやコントロールを参照するとき、予約キーワードと同じ名前の
| 変数を宣言するとき、または予約キーワードと同じ名前のプロシージャを
| 定義するときには角かっこを使用できます。修飾名を使用しなかったり、
| 名前を角かっこで囲むことを忘れると、コードにエラーが組み込まれたり、
| コードが読みにくくなったりします。このため、プログラム要素の名前と
| 同じ予約キーワードは使用しないことをお勧めします。ただし、既存の
| フォーム名またはコントロール名と競合する新規キーワードが将来の
| Visual Basic のバージョンで定義された場合は、新しいバージョンで
| 動作するようにコードを更新するときにこの技法を使用できます。
|

これを見る限り、VBScript における角かっこは、VB.NET の仕様に近いようです。
VB.NET や VBScript では、SubやDimで角かっこ表現を使えますが、VB6では使えないので。



> わざわざ予約語と衝突するメンバ名を
> 用いるのは「まずい」と考えます。…というかんじなのですが
> すれ違ってますか?
この『予約語と衝突する』という話については、私とは若干認識が異なるようです。

まず、先の投稿に関しては、Executeステートメントに対する話が出てきていましたが、
そもそも Execute は予約語では無いはずです。もしも予約語であるならば、
  Dim 予約語  '→ NG
  Dim [予約語] '→ OK
という動作になるはずですが、Executeは角かっこ無しで宣言できるというのが、その理由です。


また、「RegExpのExecuteメソッド」に関しても、文法上、Executeステートメントとの
混同はおきないので、これがメンバ名として問題があるようには感じていません。
たとえば、下記のようなコードがあったとしても、
  Search = "test"
  Set RE = New RegExp
  RE.Pattern = "[^,]+"
  Set X = RE.Execute(Search)  '★
  Execute "MsgBox TypeName(X)" '☆
この場合の ★ と ☆ の Execute が、混同される事はありませんからね。


# 無理に名前を衝突させるなら、『Sub Execute()』のようなプロシージャを自分で実装したり、
# RegExp オブジェクトを(ScriptControl.AddObject 等で)グローバルスコープに登録するなどの
# 手法が必要になりますが――それは「使い方に問題がある」のであって、メソッドの命名自体に
# 問題があるわけでは無いと思っています。

魔界の仮面弁士 さん 2005年 07月 07日 00時 37分 59秒

》魔界の仮面弁士 さん 2005年 07月 04日 04時 51分 39秒
> Dim と Const では、スコープが異なるのでしょうか。ちょっと不思議。

スコープの実験。クラス内で定義できないという点が異なりますね。

Const A = 1 'これはOK
Dim B 'これもOK
Sub C()
 Const D = 2 'これもOK
End Sub
Class E
''Const F = 3 '★これは構文エラー★
 Dim G 'これはOK
 Sub H()
  Const I = 4 'これはOK
 End Sub
End Class



》せい さん 2005年 07月 06日 02時 32分 48秒
>> RegExpはVBS初期から在ったのではなく途中から導入したもの
> Executeステートメントが後に導入したものです。RegExpは
> 最初から在りました。

最初から、では無いと思いますよ。このような記事もありますし。
http://www.microsoft.com/japan/msdn/columns/scripting/scripting051099.asp
上記記事の一番最後の部分に、「Scripting Engine 5.0 で、VBScript にも
正規表現が追加された」という意味の一文を見る事ができます。


で。手元に実機が無いので確認はできていませんが、RegExpが使えるようになったのは、
確か IE4の頃(Scripting 3.0)からだったような気がします。(JScriptのみでしたけど)
で、VBScript から RegExp を利用できるようになったのは、5.0 からだったと思います。
Execute ステートメントの実装も、VBScript 5.0 からだったはず。

ばんのしゃーによかばんた さん 2005年 07月 06日 20時 47分 55秒

>ばんのしゃーによかばんた さん 2005年 07月 06日 19時 17分 14秒
>ポイントは、JSE全体をdummyのfunction main(){〜}の中に押し込めたことです。
>さらに、
>SC.AddCode('function main(){/* \r\n'+file.ReadAll().replace(String.fromCharCode(0),'')+'\r\n*/\r\n}');
>と変えると、VBEもデコードできます。
>これは、予想外の大成果ですね。:-):-):-)

早い話、
――――――――――――――――――――――――――――――――――――――
function main(){/*

ここにエンコードされたスクリプト(VBEでもJSEでも)置く。

*/}
WScript.Echo(main);
――――――――――――――――――――――――――――――――――――――
ファイル名をhoge.JSEとして実行すればよい訳です。

ScriptControlは不要でした。


ばんのしゃーによかばんた さん 2005年 07月 06日 19時 17分 14秒

>ばんのしゃーによかばんた さん 2005年 07月 06日 17時 55分 51秒
>Script Encoderですが、JSEの場合、部分的にdecodeが可能です。
>functionのコードとglobalの変数は見えますが、globalのコードは見えません。
>それと実行されます。

ちょっと、ビッグニューズです。

JSE全体も見えました。実行もされません。これはまだミドルニューズ。

Usage: sc.js hoge.jse
――――――――――――――――――――――――――――――――――――――
var fso=new ActiveXObject("Scripting.FileSystemObject");
var file=fso.OpenTextFile(WScript.Arguments(0));
var SC=new ActiveXObject("ScriptControl");
SC.Language="JScript.Encode";
SC.AllowUI=true; //False
SC.TimeOut=-1;
SC.AddObject("WScript",WScript,true);
SC.AddCode('function main(){\r\n'+file.ReadAll().replace(String.fromCharCode(0),'')+'\r\n}');
var global=SC.CodeObject;
for(var p in global){
WScript.Echo(p+':'+typeof(global[p]));
if(typeof(global[p])=='function')WScript.Echo(global[p]);
}
if(SC.Error.Number){
WScript.StdOut.WriteLine("Number:" + SC.Error.Number);
WScript.StdOut.WriteLine("Description:" + SC.Error.Description);
WScript.StdOut.WriteLine("Source:" + SC.Error.Source);
WScript.StdOut.WriteLine("Text:" + SC.Error.Text);
WScript.StdOut.WriteLine("Line:" + SC.Error.Line);
WScript.StdOut.WriteLine("Column:" + SC.Error.Column);
}
――――――――――――――――――――――――――――――――――――――

ポイントは、JSE全体をdummyのfunction main(){〜}の中に押し込めたことです。

このアイデアは当初から考えていたのですが、何故か構文エラーになるため、
出来そうもないなと、半分諦め掛けていたのです。

ところが、JSEをバイナリで覘いてみると、末尾にNUL文字が付いていました。
これは、CreateObject("Scripting.Encoder").EncodeScriptFile()
の「障害」だと思います。NUL文字を除去すると成功しました。:-)

さらに、
SC.AddCode('function main(){/* \r\n'+file.ReadAll().replace(String.fromCharCode(0),'')+'\r\n*/\r\n}');
と変えると、VBEもデコードできます。
これは、予想外の大成果ですね。:-):-):-)


管理人むたぐち さん 2005年 07月 06日 19時 13分 46秒

To: TAK さん

Windows Script 5.6がインストールされていれば、
SendKeysメソッドを使って無理やり3枚目のタブを開く
ことができました。

Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "control.exe netcpl.cpl"
For I=1 To 100
If WshShell.AppActivate("ネットワーク") Then Exit For
Next
WScript.Sleep 100
WshShell.SendKeys "^{TAB}^{TAB}"
msgbox "done"

ばんのしゃーによかばんた さん 2005年 07月 06日 17時 55分 51秒

Script Encoderですが、JSEの場合、部分的にdecodeが可能です。

JScriptはfunction名でそのソースが見えますよね。
それを利用します。

Usage: sc.js hoge.jse
――――――――――――――――――――――――――――――――――――――
var fso=new ActiveXObject("Scripting.FileSystemObject");
var file=fso.OpenTextFile(WScript.Arguments(0));
var SC=new ActiveXObject("ScriptControl");
SC.Language="JScript.Encode";
SC.AllowUI=true;
SC.TimeOut=-1;
SC.AddObject("WScript",WScript,true);
SC.AddCode(file.ReadAll());
var global=SC.CodeObject;
for(var p in global){
WScript.Echo(p+':'+typeof(global[p]));
if(typeof(global[p])=='function')WScript.Echo(global[p]);
if(typeof(global[p])=='string')WScript.Echo(p+'='+global[p]);
if(typeof(global[p])=='number')WScript.Echo(p+'='+global[p]);
}
if(SC.Error.Number){
WScript.StdOut.WriteLine("Number:" + SC.Error.Number);
WScript.StdOut.WriteLine("Description:" + SC.Error.Description);
WScript.StdOut.WriteLine("Source:" + SC.Error.Source);
WScript.StdOut.WriteLine("Text:" + SC.Error.Text);
WScript.StdOut.WriteLine("Line:" + SC.Error.Line);
WScript.StdOut.WriteLine("Column:" + SC.Error.Column);
}
――――――――――――――――――――――――――――――――――――――
functionのコードとglobalの変数は見えますが、globalのコードは見えません。
それと実行されます。


ばんのしゃーによかばんた さん 2005年 07月 06日 17時 55分 30秒

>魔界の仮面弁士 さん 2005年 07月 06日 02時 11分 40秒
>.NET系言語から ActiveXコンポーネントを利用した場合は、使用後に
> System.Runtime.InteropServices.Marshal.ReleaseComObject( 変数 )
>を呼び出して、明示的にオブジェクトを破棄する必要があります。

重要な情報ありがとうございます。

なんか後付けの「仕様」みたいですね。

>JScriptやVBScriptやVBAのように、COMベースの言語であれば、使用した
>ActiveXオブジェクトは、null(VBSではNothing)の代入やスクリプトの終了後、
>即座に破棄されるのですが、.NET系の言語から呼び出した場合は、アプリが
>終了しても破棄されるとは限らず、メモリ上に残ってしまう事があります。

「障害」として直したほうが、みんな幸せだと思いますが、無理なのかなぁ。

というわけで、前出のFileRun.JS利用者は、直してください。:-p

ただし、直さなくても、たぶん大丈夫でしょう。

勝手な想像ですが、問題になるケースは、
IE、Excelなどのアウトプロセスサーバが残る。
ADODB.Streamなどのインプロセスサーバを繰り返し生成すると、溢れる。
の二つかと思います。

ところで、先の、
>ばんのしゃーによかばんた さん 2005年 07月 02日 16時 25分 05秒
>Clipboard.VB
ですが、クリックブック(CLICKBRD.EXE)が開いていると、

エラー:     要求されたクリップボード操作が失敗しました。
コード:     800401D0
ソース:      System.Windows.Forms

になります。「障害」だと思いますが、回避方法はないでしょうか。


つり さん 2005年 07月 06日 16時 46分 25秒

はじめまして、すいませんWSHで質問があります。

Runメソッドを使い、アプリケーションを起動した後に、
左右に並べて表示などではなく
細かくウィンドウサイズの変更、ウィンドウを表示させる位置の変更
をする方法はありませんでしょうか?

せい さん 2005年 07月 06日 03時 11分 21秒

>>せい さん 2005年 07月 06日 02時 32分 48秒

またやってしまった

>>RegExpはVBS初期から在ったのではなく途中から導入したもの

Executeステートメントが後に導入したものです。RegExpは
最初から在りました。

要は「開発元は例外的なことをユーザーに押し付けないだろうから
Executeステートメントをオーバーライドできる関数にしたのだろう」
と言いたかったのです。

歯痛くてボロボロだ…

せい さん 2005年 07月 06日 02時 32分 48秒

>>魔界の仮面弁士 さん 2005年 07月 04日 04時 51分 39秒

>>Dim と Const では、スコープが異なるのでしょうか。ちょっと不思議。

なんだかVBSって不思議な世界ですね。
VBSでは内部でデータの持ち方が定数と変数では違うようなのでそこらと
関係有るのかも。定数定義だけ構文解析1パスめでメモリ領域を取ってるんで
識別子のスコープを認識できない、等と勝手に考えてます。


>>う〜ん。「関数っぽい」ですかね?

すいません、単なる主観です。数値にまつわる物は関数と言う意識が
どこかで染み込んでいるのです。ちなみにこれもバグ出しで見つかった
やつでした。しかも完全な抜け ←抜けてんのはおまえだっ


>>> ですが、VBSは素の予約語は予約語としてしか扱えないので
>>これは、意味がわかりませんでした。(?_?)

言葉が足りなかったようで混乱させて申し訳在りません。
私が前回言った部分の解釈は仰るとおりです。

RegExpはVBS初期から在ったのではなく途中から導入したもの
ですが、その開発目的はMicrosoft自身が開発したスクリプトへの
正規表現処理機能の付加だと思っています
(他からも使えるのでどうなのかわかりませんが)。その場合
スクリプトのような簡便さを求める言語に対して開発元が
[ ]を使わなければ扱えないようなメンバ名を 新規導入する
オブジェクトに設定することは開発元が取る行動では無いと
考えています。識別子が衝突することを最初から想定していたから[ ]を
言語仕様に含めたのは理解できますが、これは例外的な
扱いのはずです。わざわざ予約語と衝突するメンバ名を
用いるのは「まずい」と考えます。…というかんじなのですが
すれ違ってますか?


最近VB.NETを勉強し始めてVBの言語仕様の断片がVBSのいろんな所に
出ていることを知りました。[ ]もべんりだなぁくらいにしか思って
無かったのですがVBSでもつかえるとわ…以前教えていただいた&h..&が
文字列表現になるとIsNumeric()ではじかれるのはVBSの仕様と
思ってたらVB.NETもそうなのね…マニュアルをよく読むと終端の
&は型指定なんですね。リテラルだけで型指定できてるわけではないのか。
VBSのマニュアルよりVB.NETのマニュアルのほうがVBSを理解しやすい
かもしれないとおもうきょうこのごろ。

魔界の仮面弁士 さん 2005年 07月 06日 02時 11分 40秒

WSH Lab.にも、.NET系のサンプルが増えてきたので、ひとつ注意点を。
JScript.NET 等から、ActiveX(COM/OLE)を利用する場合についてです。
# たとえば、InternetExplorer.Application、WScript.Shell、
# Shell.Application、ADODB.Stream……といったオブジェクトの事です。


.NET系言語から ActiveXコンポーネントを利用した場合は、使用後に
 System.Runtime.InteropServices.Marshal.ReleaseComObject( 変数 )
を呼び出して、明示的にオブジェクトを破棄する必要があります。


JScriptやVBScriptやVBAのように、COMベースの言語であれば、使用した
ActiveXオブジェクトは、null(VBSではNothing)の代入やスクリプトの終了後、
即座に破棄されるのですが、.NET系の言語から呼び出した場合は、アプリが
終了しても破棄されるとは限らず、メモリ上に残ってしまう事があります。

.NETでActiveXコンポーネントを利用する場合には、
ReleaseComObjectメソッドの呼び忘れに、十分注意しましょう。


-- 以下、ReleaseComObject関係の資料 --

Office連携時に、Officeが終了せずに居残ってしまう可能性について
http://support.microsoft.com/kb/317109/ja

ADOの利用時に、アクセス違反が発生する可能性について
http://support.microsoft.com/kb/321415/ja

For Eachによる列挙を利用する場合の参考例
http://www.divakk.co.jp/aoyagi/csharp_tips_vssenum.html

管理人むたぐち さん 2005年 07月 05日 16時 59分 31秒

To: TAK さん

Win98SEとMEで検証してみましたが、やはりどうやっても
一枚目のタブしか開かないようです。
二枚目以降のタブを開く方法はちょっとわかりません。

ばんのしゃーによかばんた さん 2005年 07月 05日 16時 55分 38秒

■異なるフォルダの2ファイルをアプリに送る方法の別案です。

Windows PowerToyに、(Send To) Command Line.CommandLineという
ツールがありますが、これはその機能をJScript.NETで作ったものです。
ドロップしたファイルのフルパス名など、引数に指定された文字列を
「ファイル名を指定して実行」に送ります。
WSHやVBAのSendKeysは日本語を通しませんが、
.NETのSendKeysは日本語を通すので、これを利用します。

FileRun.JS
――――――――――――――――――――――――――――――――――――――
import System.Windows.Forms;

new ActiveXObject("Shell.Application").FileRun();
var Arguments:String[]=System.Environment.GetCommandLineArgs();
if(Arguments.length>1){
 var args=new Array();
 for(var k=1;k<Arguments.length;k++){
  var arg=Arguments[k];
  arg.indexOf(' ')==-1?args.push(arg):args.push('"'+arg+'"');
 }
 var wShell=new ActiveXObject("WScript.Shell");
 while(!wShell.AppActivate("ファイル名を指定して実行")){
  System.Threading.Thread.Sleep(100);
 }
 System.Windows.Forms.SendKeys.SendWait(args.join(' ')+' ');
}
――――――――――――――――――――――――――――――――――――――
jsc /t:winexe FileRun.JS
でコンパイル。

そしてここからが本家PowerToyには出来ない応用です。

FileRun.EXEのショートカット(.LNK)を作り、ターゲットに
「FileRun.EXE コマンド 引数」
と書いておきます。

このショートカットはいろいろと使えます。

例えば、「FileRun.EXE コマンド 仮引数」なら、
仮引数を修正して実行することができます。

例えば、「FileRun.EXE コマンド 固定引数」であれば、
可変引数を追加して実行することができます。
「ファイル名を指定して実行」ダイアログにファイルをドロップして
引数に追加することもできます。

フォルダの異なる2ファイルをSendToに送ったり、ドラッグ&ドロップ
なんてことは、可能にするテクもありますが、一般にはなかなか出来ません。
例えば、「FileRun.EXE コマンド」のショートカットを作っておけば、
「ファイル名を指定して実行」ダイアログにフォルダの異なる2ファイルを
順次ドロップして実行することができます。

更に、そのショートカットをSendToなどに置いて、ファイル1を送るか、
ドロップすると、「ファイル名を指定して実行」ダイアログに、
「FileRun.EXE コマンド ファイル1」と入るので、更に、ファイル2を
ダイアログにドロップして追加します。


ばんのしゃーによかばんた さん 2005年 07月 05日 16時 55分 14秒

>管理人むたぐち さん 2005年 06月 24日 21時 42分 39秒
>To: 鈴木 さん
>JScript.NETなら簡単なんですけどね。
>以下は、じゃんぬさんのサイトにあるC#のコード
>JScript.NETに書き換えたものです。

それを更にCOMオブジェクトに書き換えたものです。

VersionInfo.JS
――――――――――――――――――――――――――――――――――――――
package VersionInfo{
 class VersionInfo{
  public var FileName:System.String;
  public var FileDescription:System.String;
  public var Comments:System.String;
  public var CompanyName:System.String;
  public var ProductName:System.String;
  public var LegalCopyright:System.String;
  public var LegalTrademarks:System.String;
  public var OriginalFilename:System.String;
  public var InternalName:System.String;
  public var Language:System.String;
  function Path(s:System.String){
   var FileVersionInfo:System.Diagnostics.FileVersionInfo=System.Diagnostics.FileVersionInfo.GetVersionInfo(s);
   FileName=FileVersionInfo.FileName;
   FileDescription=FileVersionInfo.FileDescription;
   Comments=FileVersionInfo.Comments;
   CompanyName=FileVersionInfo.CompanyName;
   ProductName=FileVersionInfo.ProductName;
   LegalCopyright=FileVersionInfo.LegalCopyright;
   LegalTrademarks=FileVersionInfo.LegalTrademarks;
   OriginalFilename=FileVersionInfo.OriginalFilename;
   InternalName=FileVersionInfo.InternalName;
   Language=FileVersionInfo.Language;
  }
 }
}
――――――――――――――――――――――――――――――――――――――
jsc /t:library VersionInfo.JS
VersionInfo.DLLをC:\Windows\System32にコピーして、
regasm VersionInfo.DLL

VersionInfo.VBS
――――――――――――――――――――――――――――――――――――――
Set VersionInfo=CreateObject("VersionInfo.VersionInfo")
VersionInfo.Path "C:\WINDOWS\System32\shell32.dll"
WScript.Echo _
Join(Array(Join(Array("ファイル名",VersionInfo.FileName),vbTab), _
Join(Array("ファイルの説明",VersionInfo.FileDescription),vbTab), _
Join(Array("コメント",VersionInfo.Comments),vbTab), _
Join(Array("会社名",VersionInfo.CompanyName),vbTab), _
Join(Array("製品名",VersionInfo.ProductName),vbTab), _
Join(Array("著作権",VersionInfo.LegalCopyright),vbTab), _
Join(Array("商標",VersionInfo.LegalTrademarks),vbTab), _
Join(Array("正式ファイル名",VersionInfo.OriginalFilename),vbTab), _
Join(Array("内部名",VersionInfo.InternalName),vbTab), _
Join(Array("言語",VersionInfo.Language),vbTab)),vbLf)
――――――――――――――――――――――――――――――――――――――


ばんのしゃーによかばんた さん 2005年 07月 05日 16時 54分 57秒

>ひで さん 2005年 06月 01日 23時 08分 38秒
>「マクロ'print_sheet'が見つかりません」が発生し、

最初に、マクロのセキュリティレベルの設定を疑って、試しましたが、
エラーにならなかったので、関係ないと除外してました。
でも、こんな記事があったので、ひょっとして関係するのかも知れません。

――――――――――――――――――――――――――――――――――――――
変更される文書番号: 262876
最終更新日: 2003/11/11
Microsoft Excel 2000 VERSIONS
概要
この資料は、マクロのセキュリティ レベル設定が「高」に変更される現象について説明しています。
詳細
ユーザー設定メニュー項目やツール バー ボタンをクリックすると、以下のメッセージが表示され、マクロが実行できない場合があります。
「マクロ '<マクロ名>' が見つかりません。」
原因
マクロ セキュリティのレベルが自動的に「高」に設定されているために発生します。
回避策
[ツール] メニューの [マクロ] より [セキュリティ] をクリックして、セキュリティ レベルを「中」または「低」に設定後、ファイルを開きなおしてください。
――――――――――――――――――――――――――――――――――――――


ばんのしゃーによかばんた さん 2005年 07月 05日 16時 54分 40秒

>管理人むたぐち さん 2004年 07月 26日 16時 01分 08秒
>To: Perlすくりぷたー さん
>> VBSやJSだとVBEやJEに暗号化できるみたいですが、
>>Perlのコードを同様に暗号化することは出来ないでしょうか?
>おそらくScript EncoderはPerlScriptには対応していないので
>無理なんじゃないでしょうか。

仮説ですが、
Script Encoderは拡張子やlanguage=の変換部分を除いて、
Script言語種に依存しない、
また、個別のScript言語側は何も知らない、
のではないでしょうか。
もし、そうなら、
.PLE、PLEFile、PerlScript.Encodeのレジストリは
.VBSか.JSを見て作る。
.PLSを.VBSか.JSに変えて、エンコードして、.PLEに戻す。
なんてやれば、動くのではないでしょうか。
私は環境がないので、試せませんが、
Perlすくりぷたー の方々は一度お試しください。


ばんのしゃーによかばんた さん 2005年 07月 05日 16時 54分 14秒

■情報を隠してスクリプトを実行する方法の別案。

current directoryとargs...を表示するだけのWSF。
Usage: args.wsf [args...]
――――――――――――――――――――――――――――――――――――――
<?xml version="1.0" encoding="utf-7"?>
<job>
<script language="vbscript"><![CDATA[
+AFMAZQB0ACAAdwBTAGgAZQBsAGwAPQBDAHIAZQBhAHQAZQBPAGIAagBlAGMAdAAoACIAVwBTAGMAcgBpAHAAdAAuAFMAaABlAGwAbAAiACkADQAKAHIAbwB3AHMAPQBBAHIAcgBhAHkAKAB3AFMAaABlAGwAbAAuAEMAdQByAHIAZQBuAHQARABpAHIAZQBjAHQAbwByAHkAJgB2AGIAQwByAEwAZgApAA0ACgBGAG8AcgAgAEUAYQBjAGgAIABhAHIAZwAgAEkAbgAgAFcAUwBjAHIAaQBwAHQALgBBAHIAZwB1AG0AZQBuAHQAcwANAAoAIAAgAFIAZQBEAGkAbQAgAFAAcgBlAHMAZQByAHYAZQAgAHIAbwB3AHMAKABVAEIAbwB1AG4AZAAoAHIAbwB3AHMAKQArADEAKQANAAoAIAAgAHIAbwB3AHMAKABVAEIAbwB1AG4AZAAoAHIAbwB3AHMAKQApAD0AIgAnACIAJgBhAHIAZwAmACIAJwAiAA0ACgBOAGUAeAB0AA0ACgBXAFMAYwByAGkAcAB0AC4ARQBjAGgAbwAgAEoAbwBpAG4AKAByAG8AdwBzACwAdgBiAEMAcgBMAGYAKQANAAo-
']]></script>
</job>
――――――――――――――――――――――――――――――――――――――
なんか不思議というか、変でしょう? 謎解きしてみてください。


TAK さん 2005年 07月 04日 19時 47分 08秒

管理人むたぐち 様
WSHのHP、いつも参考にさせてもらっております。
当方のOSは98です。
Netcpl.cpl ,2としても1枚目です。1でも3でも1枚目でした。
ご教示よろしくお願いします。

ばんのしゃーによかばんた さん 2005年 07月 04日 18時 22分 20秒

情報を隠してスクリプトを実行する方法の別案。

Excelで、
(1)例えば、sheet1.Cells(1, 1)にデータを入れて、
(2)ツール/保護/ブックの保護/ウィンドウ/パスワード
(3)ウィンドウ/非表示
で、データを隠す。

(4)ツール/マクロ/Visual Basic Editorで、
標準モジュールを追加して、
Sub auto_open()
Application.Quit
End Sub
Sub auto_close()
MsgBox Sheet1.Cells(1, 1)     'データを直に書かない。参照する。
End Sub
(5)ツール/VBAProjectのプロパティ/プロジェクトを表示用にロックする/パスワード
で、スクリプトを隠す。

これで、「普通」には、データもスクリプトもパスワ−ドで保護されて見えません。

普通にXLSファイルを開くと、マクロ警告が出るので、
Set xl=CreateObject("Excel.Application")
Set book=xl.WorkBooks.Open("hoge.xls")
xl.Quit
で起動するとよいでしょう。

ただし、
スクリプトはファイルをバイナリで覘けば見えます。
データはスクリプトで取り出せます。
なので完全ではありません。


魔界の仮面弁士 さん 2005年 07月 04日 04時 51分 39秒

>> 2.同名の関数を複数定義すると最後に定義した関数を
>> 有効にするってのも仕様なんだろうなぁ。強力バグ元

そういえば、Execute や Sin は 予約語ではありませんので、
 Dim Execute, Sin
のように、Dim や Class、Sub の名前などとして使う事が可能ですが、
それ自体はすでにグローバルで定義済みの名前になっていますので、
 Const Execute = 1
 Const Sin = 2
のように書く事はできず、二重定義エラーとなるようです。
Dim と Const では、スコープが異なるのでしょうか。ちょっと不思議。



》 せい さん 2005年 07月 03日 20時 23分 34秒
> ちなみに関数っぽいRandomizeもExecuteと同様の結果でした。
う〜ん。「関数っぽい」ですかね?
Randomize は値を返しませんので、関数とは呼べないのでは無いでしょうか。
やはりヘルプどおり、ステートメントとして分類される物だと思いますよ。

> 不思議なのはExecuteと同時期に導入したEval()は
> 関数とした点です。
Evalは値を返しますから、ステートメントではなく、関数として分類されるでしょう。

> Executeが式ではなくステートメントとして
> 認識するからステートメント…なのか?
Executeは値を返しませんから、ステートメントですね。



>>>その名前を [ ] で囲む事で、ある程度は利用可能になります。
> []が使えるとは知りませんでした。というよりこれを
> 知っている人はどれほどいるのでしょう?
ここの過去ログにもありますので、知っている人もそれなりに居るでしょうけど、
絶対数でいえば、知らない人の方が多いでしょうね。きっと。(^^;


> エラー解説に「だけ」文法書くとわ…MSおそるべし
VB.NET等では、ヘルプにもしっかり書いてあるのですけれどね。
VBScriptの場合、ヘルプに書かれていない事が少なからずあるので、
もう少し、ヘルプを整備して欲しいような気もします。まぁ、今更ですけど。


> ですが、VBSは素の予約語は予約語としてしか扱えないので
これは、意味がわかりませんでした。(?_?)

『素の予約語』が「予約語としてしか扱えない」のは、VBScriptに限った話では無く、
当然の動作のように思えるのですが……。

もし、『素の予約語』が予約語以外と認識されてしまうようであれば、その方が困ってしまうような。


> クラスを明示しても予約語として認識します。

「クラスを明示する」とは、下記のような事でしょうか?
少なくとも、A.For のような書き方をすれば、この場合の For が予約語として
認識される事は無いと思いますが……そういう事では無いのかな。

'------------
 Option Explicit
 Dim A
 Set A = New C
 A.For
 A.Sub "TEST"
 MsgBox A.Function()
'------------
 Class C
  Sub [For]()
   MsgBox "For"
  End Sub

  Sub [Sub](ByVal P)
   MsgBox P
  End Sub

  Function [Function]()
   [Function] = "Test Function"
  End Function
 End Class
'------------


> 私では実験出来ないのですが
> オートメーションのメンバ名にステートメントのキーワードを
> 使うとVBSでは素の識別子としては認識できないと思います。

この部分、意味が良く分からなかったので、別の表現で書いていただけないでしょうか。

私は、上記の「メンバ名にステートメントのキーワードを使う」とは、
たとえば、VBScriptで書くならば、
'------------
 'Do〜Loopステートメント、Exitステートメントのキーワードを使って、
 'Doプロパティ, Loopプロパティ、Exitメソッドを実装
 Class Class1
   Dim [Do], [Loop]
   Sub [Exit]

   End Sub
 End Class
'------------
のような状態を想像したのですが、そういう意味では無いのでしょうか?



> オートメーションのメンバ名にステートメントのキーワードを
> 使うとVBSでは素の識別子としては認識できないと思います。
> Executeが予約語ではまずいのです。

すみません。
なぜ、Executeが予約語だと問題になるのか、よくわかりませんでした。

そもそも、予約語をメンバ名として利用できないというルールは、VBScript側に
限った制約であって、オートメーション側の制約とは無関係だと思うのですが……。


もし、ステートメントのキーワードが、オブジェクトのメンバ名として使われていたとしても、
VBScriptからは、「Obj.For」のようにオブジェクト名を明示すれば問題なく利用できますよね。

あるいは、そのオブジェクトがグローバルに登録されていた(※)としても、角括弧表現を使う事で、
「ステートメントそのもの」と「メンバ名」とを区別して利用する事が可能なので、
言語仕様上は、特に問題は無いように思えますけれども。


> とどのつまりはVBSには予約語の定義がない、というのが
> 一番の問題点のようです。
確かに、「予約語の定義が(ヘルプに書かれてい)ない」のは困り物ですね。
それとも、どこかにホワイトペーパー等として公開されているのかな。。。

管理人むたぐち さん 2005年 07月 04日 01時 36分 38秒

To: TAK さん

> ここのサイトのWSHテクニック集に、コントロールパネルを直接開く方法
> が記載されており、それに習ってネットワークを開こうとしております。
> その3枚目のタブが開かせようとしていますが、上手くいきません。
> 何か方法があるのでしょうか?

試してみましたが、Win2000,XPでは駄目で、98SE,MEではOKでした。
Win2000,XPはNetcpl.cplがそもそもありません。
お使いのOSは何でしょうか?

せい さん 2005年 07月 03日 20時 23分 34秒

>>魔界の仮面弁士 さん 2005年 07月 03日 15時 52分 51秒

>>で。この点に関しては、クラスを利用する事である程度回避できると思います。

いっそグローバルレベルをclassで囲むとか考えましたが
これだとClass定義を外に出さなきゃいけない。また分割して
グローバルレベルを記述しにくいので結局エディタの検索だけが
頼みの綱でした。VBSでン千行も書くもんじゃあない、か。


>>初期のVBやそれ以前のBASIC言語において、値を返す処理=関数、
値を返さない処理=ステートメント と呼んでいたという、歴史的な経緯に
よるところが大きいと思われます。

やっぱりMS-BASICの名残なんですねぇ。
ちなみに関数っぽいRandomizeもExecuteと同様の結果でした。

Call Randomize(1)

不思議なのはExecuteと同時期に導入したEval()は
関数とした点です。Executeが式ではなくステートメントとして
認識するからステートメント…なのか?


>>その名前を [ ] で囲む事で、ある程度は利用可能になります。

[]が使えるとは知りませんでした。というよりこれを
知っている人はどれほどいるのでしょう?エラー解説に
「だけ」文法書くとわ…MSおそるべし


>>『あるクラスのメソッド名』として定義済みであったとしても、
グローバルまたは別のクラスのメソッド名として、同じ名前を使う事はできますしね

ですが、VBSは素の予約語は予約語としてしか扱えないので
クラスを明示しても予約語として認識します。私では実験出来ない
のですがオートメーションのメンバ名にステートメントのキーワードを
使うとVBSでは素の識別子としては認識できないと思います。
Executeが予約語ではまずいのです。

とどのつまりはVBSには予約語の定義がない、というのが
一番の問題点のようです。
(ステートメントキーワード<>予約語)なのは確かなようですが。

ちょい訂正。
>>今まで気づかなかったのは迂闊としか言いようが無い。
今読み直すとなんだかMSを責めてるような言い草ですが
これは私が気づかなかったことの自戒です。VBS->VB.NET変換
ツールを作っているときExecuteの扱いでバグを出して
しまったので。

管理人むたぐち さん 2005年 07月 03日 18時 16分 31秒

Beep"ド2レ2ミ2-2ド2レ2ミ2-2ソ2ミ2レ2ド2レ2ミ2レ2-2" & _
  "ド2レ2ミ2-2ド2レ2ミ2-2ソ2ミ2レ2ド2レ2ミ2ド2-2" & _
  "ソ2ソ2ミ2ソ2ラ2ラ2ソ2-2ミ2ミ2レ2レ2ド2-2"

こんな感じで休符も使えます。付点音符は忘れてました(汗

管理人むたぐち さん 2005年 07月 03日 18時 12分 14秒

ちょっと長くなりましたが、Beep音簡易MMLコンパイラを
作ってみました。たまにはこんなのも良いかな?

Beep "ソソラシソシラレ" & _
   "ソソラシソ2ファ♯レ" & _
   "ソソラシド↑シラソ" & _
   "ファ♯レミファ♯ソ2"

Sub Beep(ByVal MML)
     MML = Replace(MML, "ファ", "フ")
     MML = Replace(MML, "16", "6")
     Redim aSequence(1, -1)
     Set BeepWin32 = CreateObject("Beep.Win32")
     FreqB = CDbl(440)
     ScaleRatio = CDbl(1.059463094)
     BaseDuration = 70

     Set dicScale = CreateObject("Scripting.Dictionary")
     dicScale.Add "ド", FreqB * ScaleRatio ^ 3
     dicScale.Add "レ", FreqB * ScaleRatio ^ 5
     dicScale.Add "ミ", FreqB * ScaleRatio ^ 7
     dicScale.Add "フ", FreqB * ScaleRatio ^ 8
     dicScale.Add "ソ", FreqB * ScaleRatio ^ 10
     dicScale.Add "ラ", FreqB * ScaleRatio ^ 12
     dicScale.Add "シ", FreqB * ScaleRatio ^ 14
     dicScale.Add "-", -1

     For I = 1 To Len(MML)
          sTemp = Mid(MML, I, 1)
          If dicScale.Exists(sTemp) Then
               dPitch = dicScale(sTemp)
               iDuration = BaseDuration * 4
               bPitch = False : bDuration = False : bInterval = False
               For J = 1 To 3
                    If I + J <= Len(MML) Then
                         sMark = Mid(MML, I + J ,1)
                         If bPitch = False Then
                              Select Case sMark
                                   Case "♯","#" : dPitch = dPitch * ScaleRatio
                                   Case "♭" : dPitch = dPitch / ScaleRatio
                              End Select
                              bPitch = True
                         End If
                         If bInterval = False Then
                              Select Case sMark
                                   Case "↑","▲" : dPitch = dPitch * ScaleRatio ^ 12
                                   Case "↓","▼" : dPitch = dPitch / ScaleRatio ^ 12
                              End Select
                              bInterval = True
                         End If
                         If bDuration = False Then
                              Select Case sMark
                                   Case "全" : iDuration = BaseDuration * 16
                                   Case "2" : iDuration = BaseDuration * 8
                                   Case "4" : iDuration = BaseDuration * 4
                                   Case "8" : iDuration = BaseDuration * 2
                                   Case "6" : iDuration = BaseDuration * 1
                              End Select
                              bDuration = True
                         End If
                    End If
               Next
               ReDim Preserve aSequence(1, UBound(aSequence, 2) + 1)
               aSequence(0, UBound(aSequence, 2)) = dPitch
               aSequence(1, UBound(aSequence, 2)) = iDuration
          End If
     Next
    
     For I = 0 To UBound(aSequence, 2)
          If aSequence(0, I) < 0 Then
               WScript.Sleep aSequence(1, I)
          Else
               BeepWin32.Beep aSequence(0, I), aSequence(1, I)
          End If
     Next
End Sub

Return