C# から VBScript を実行する C# ソースコードを自動生成する
こんにちは。
仕事の自動化にやりがいと達成感を感じるガッくんです。
この記事の目次
目的
リンクの記事で既存の VBScript から VBScript ファイルの作成、実行、削除する関数を作成する事に成功しました。
既存の VBScript を関数化する VBScript を作成する - 解析エンジニアの自動化 blog
せっかくなんで既存の VBScript から VBScript ファイルの作成、実行、削除する C# のソースコードを生成する VBScript を作成します。
関数
ソースコード
ForReading = 1 ' OpenTextFile 引数用変数
ForWriting = 2 ' OpenTextFile 引数用変数
ForAppending = 8 ' OpenTextFile 引数用変数
'-------------------------------------------------------------------------------------------------------
' 引数が無かった時の処理
If WScript.Arguments.count = 0 then
WScript.Echo "引数が無いため、実行できません。" & vbNewLine & _
"ファイルをドロップしてください。"
WScript.Quit
End If
'-------------------------------------------------------------------------------------------------------
' ファイルシステムオブジェクト作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")
'-------------------------------------------------------------------------------------------------------
' ドロップされた引数がファイル以外ならアラートして終了する
For each args In WScript.Arguments
'----------------------------------------------------------------------------------------------------
' ドロップされた引数がフォルダかファイルかを判定する
If objFileSys.FolderExists(args) then
'-------------------------------------------------------------------------------------------------
' is folder.
' ファイルシステムオブジェクトの破棄
Set objFileSys = Nothing
WScript.Echo "フォルダがドロップされました。" & vbNewLine & _
"処理を終了します。"
WScript.Quit
ElseIf objFileSys.FileExists(args) then
'-------------------------------------------------------------------------------------------------
' is file.
If Instr(1, args, ".vbs") = 0 Then
'----------------------------------------------------------------------------------------------
' is not VBScript file.
' ファイルシステムオブジェクトの破棄
Set objFileSys = Nothing
WScript.Echo "VBScript では無いファイルがドロップされました。" & vbNewLine & _
"処理を終了します。"
WScript.Quit
End If
Else
'-------------------------------------------------------------------------------------------------
' is unknown.
' ファイルシステムオブジェクトの破棄
Set objFileSys = Nothing
WScript.Echo "フォルダ 及び ファイル とも認識できないデータがドロップされました。" & vbNewLine & _
"処理を終了します。"
WScript.Quit
End If
Next
'-------------------------------------------------------------------------------------------------------
' VBScript ファイルを作成するパスの作成
WrapperVBSDir = SelfPath()
'-------------------------------------------------------------------------------------------------------
' ファイルシステムオブジェクト作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")
'-------------------------------------------------------------------------------------------------------
' 引数の VBScript ファイルの読み込み
For each args In WScript.Arguments
' 引数の VBScript ファイルオープン
Set InputFile = objFileSys.OpenTextFile(args, ForReading, False)
' ファイル名のみ抽出
InputFileName = objFileSys.getFileName(args)
' コード格納用変数
code = ""
' 引数の VBScript ファイルを最終行まで読み込む
Do Until InputFile.AtEndOfStream
' 1行読み込む
strLine = InputFile.ReadLine
' 「\」を「\\」に置換する
strLine = Replace(strLine, "\", "\\")
' 「"」を「\"」に置換する
strLine = Replace(strLine, """", "\""")
' 読み込んだ文字列を「"」で囲む
strLine = """" & strLine & """"
' コード格納用変数が空なら
If code = "" Then
' 配列変数の文字列と合わせて代入する
code = " string[] arrCode = new string[] {" & """" & "Wrapped" & InputFileName & """" & ", " & strLine
' コード格納用変数が既に代入済みなら
Else
' 「, 」文字列で区切って代入する
code = code & ", " & strLine
End If
Loop
' 配列変数の最後の「)」を代入する
code = code & "};" & vbcrlf & vbcrlf
' Function コードの追加
code = "// using System.Diagnostics;" & vbcrlf & "private int Wrapper_" & Left(InputFileName, InstrRev(InputFileName, ".") - 1) & "()" & vbcrlf & "{" & vbcrlf & code
' パス取得コードの追加
code = code & " //自分自身の実行ファイルのパスを取得する" & vbcrlf
code = code & " string appPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;" & vbcrlf & vbcrlf
' VBScript 作成コードの追加
code = code & " // VBScript 作成コード" & vbcrlf
code = code & " // ストリームライターのオープン(第二引数 => true:追記 false:削除・上書き)" & vbcrlf
code = code & " StreamWriter swVBS = new StreamWriter(appPath + arrCode[0], false, Encoding.GetEncoding(""Shift_JIS""));" & vbcrlf
code = code & " // コード書き込み" & vbcrlf
code = code & " for (int i = 1; i < arrCode.Length; i++)" & vbcrlf
code = code & " {" & vbcrlf
code = code & " swVBS.WriteLine($""{arrCode[i]}"");" & vbcrlf
code = code & " }" & vbcrlf
code = code & " // ストリームライターのクローズ" & vbcrlf
code = code & " swVBS.Close();" & vbcrlf & vbcrlf
' 作成した VBScript ファイルの実行コードの追加
code = code & " // VBScript の実行" & vbcrlf
code = code & " Process proc = new Process();" & vbcrlf
code = code & " proc.StartInfo.FileName = arrCode[0];" & vbcrlf
code = code & " proc.Start();" & vbcrlf
code = code & " proc.WaitForExit();" & vbcrlf
code = code & " int ret = proc.ExitCode;" & vbcrlf & vbcrlf
' 作成した VBScript ファイルの削除コードの追加
code = code & " //作成した VBScript を削除する" & vbcrlf
code = code & " File.Delete(appPath + arrCode[0]);" & vbcrlf
' 戻り値を返すコードの追加
code = code & " // 戻り値を返す" & vbcrlf
code = code & " return ret;" & vbcrlf
' Function コードの追加
code = code & "}"
' 出力ファイルオープン
Set OutputFile = objFileSys.OpenTextFile(WrapperVBSDir & "\C#Wrapper-" & InputFileName, ForWriting, True)
' 出力
OutputFile.WriteLine code
' 引数の VBScript ファイルクローズ
InputFile.Close
' 出力ファイルクローズ
OutputFile.Close
Next
'-------------------------------------------------------------------------------------------------------
' ファイルシステムオブジェクトの破棄
Set objFileSys = Nothing
Function SelfPath()
' ファイルシステムオブジェクト作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")
' 自分のパスの取得
SelfPath = objFileSys.getParentFolderName(WScript.ScriptFullName)
' ファイルシステムオブジェクトの破棄
Set objFileSys = Nothing
End Function
使い方
既存の VBScript ファイルをドラッグ&ドロップすると、『C#Wrapper-[ドロップしたファイル名].vbs』という VBScript ファイルを作成します。ファイルの中身は『Wrapper_ [ドロップしたファイル名]』という関数名の C# コードが記述されています。
この関数を C# にコピペして、関数を使用すればドラッグ&ドロップした VBScript が実行出来ます。
ソースコード
〜ドロップした VBScript 〜
msg = "c:\test\test.txt"
msg = msg & "これは Sample2.vbs です。"
MsgBox msg
WScript.Quit(101) ' 戻り値
ソースコード
〜関数化した VBScript 〜
C#Wrapper-Sample2.vbs
// using System.Diagnostics;
private int Wrapper_Sample2()
{
string[] arrCode = new string[] {"WrappedSample2.vbs", "msg = \"c:\\test\\test.txt\"", "msg = msg & \"これは Sample2.vbs です。\"", "MsgBox msg", "WScript.Quit(101) ' 戻り値"};
//自分自身の実行ファイルのパスを取得する
string appPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
// VBScript 作成コード
// ストリームライターのオープン(第二引数 => true:追記 false:削除・上書き)
StreamWriter swVBS = new StreamWriter(appPath + arrCode[0], false, Encoding.GetEncoding("Shift_JIS"));
// コード書き込み
for (int i = 1; i < arrCode.Length; i++)
{
swVBS.WriteLine($"{arrCode[i]}");
}
// ストリームライターのクローズ
swVBS.Close();
// VBScript の実行
Process proc = new Process();
proc.StartInfo.FileName = arrCode[0];
proc.Start();
proc.WaitForExit();
int ret = proc.ExitCode;
//作成した VBScript を削除する
File.Delete(appPath + arrCode[0]);
// 戻り値を返す
return ret;
}
コメント
VBScript を C# の関数化する事が出来ましたが、引数を必要とする VBScript には対応出来ません。
完全に関数化出来るようにしたいです。
まぁ、 Excel の操作とか引数のいらない簡単な設定の処理を VBScript で書いて C# に組み込めれば良いのかなと思っています。
以上