2010年07月18日

VB.net のイベントを COM へ公開する(2)。つまり、WSH や HTA で VB.net で書いたコードを実行すると言う事。

VB.net のイベントを COM へ公開する(1)。
つまり、WSH や HTA で VB.net で書いたコードを実行すると言う事。

前記事で登録した COM を使います。まず、イベントを明示的に定義できる WSH で
以下のようにして使います。WSH は、メモリ上に存在しないといけないので、利用
時は注意する必要がありますが、以下はイベント側で停止するので、イベントが終
わるまで本体が終了する事はありません
Set obj = Wscript.CreateObject("lboxTool.lbox", "my_")

Call obj.URLDownloadToFile( _
	"http://lightbox.on.coocan.jp/image/zero_night_logo.png", _
	"logo.png" _
)

Sub my_EndDownload() 

	Wscript.Echo "終了イベント"

End Sub

Sub my_EndDownload2( str ) 

	Wscript.Echo "終了イベント:"&str

End Sub

HTA では、IE を使うのと同じように利用しますが、オブジェクトは OBJECT
要素で定義されたものが暗黙的に利用されます。

※ classid は、レジストリの lboxTool.lbox より取得して下さい。
※ あるいは、regasm lboxCom.dll /regfile:lboxCom.reg で定義情報を取得
※ します
<SCRIPT type="text/vbscript" language="vbscript">

Function TestAction()

	Call document.GetElementById("test") _
		.URLDownloadToFile("http://lightbox.on.coocan.jp/image/zero_night_logo.png", "logo.png")

End Function

Function test_EndDownload()

	alert("ダウンロード終了")

End Function

Function test_EndDownload2( str )

	alert("ダウンロード終了:"&str)

End Function

</SCRIPT>
<INPUT type="button" value="OK" onClick="Call TestAction()">

<OBJECT id="test" classid="clsid:8F064F33-ED02-39E7-ACB4-D4800EB217AB"></OBJECT>



---
posted by lightbox at 02:17 | Comment(0) | サンプル | このブログの読者になる | 更新情報をチェックする

VB.net のイベントを COM へ公開する(1)。つまり、WSH や HTA で VB.net で書いたコードを実行すると言う事。

メソッドを公開するだけならば、わりと簡単です。イベントも欲しい場合、というか
当然欲しいので、多少面倒ですがインターフェイス定義をしてやると何でもありにな
ります。
' GUID は、guidgen.exe で取得しました
' 以下のどれでも同じです
' C:\Program Files\Microsoft Visual Studio 8\Common7\Tools
' C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin
' C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools
' C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
' ※ VB.net のイベントを COM へ公開する為のインターフェイス定義
<Guid("5FB047A1-0662-4fe6-B79E-552D08FCC7BA"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface ILboxToolEvents
    <DispId(1)> _
    Sub EndDownload()
    <DispId(2)> _
    Sub EndDownload2( str As String )
End Interface

イベントの数だけ、DispId とイベントの型の定義をする必要があります。
VB.net の中では、ユーザーイベントを作成して呼び出すだけです。ポイ
ントは、クラス定義の属性として、ComSourceInterfaces を定義するだけ
です。
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices	' DllImport

' Framework2.0 用の記述
'<Assembly: AssemblyKeyFile("lightbox.snk")>
' Framework3.5 では、vbc.exe のコマンドラインに /keyfile:lightbox.snk を追加します
Namespace lboxTool

	' GUID は、guidgen.exe で取得しました
	' 以下のどれでも同じです
	' C:\Program Files\Microsoft Visual Studio 8\Common7\Tools
	' C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin
	' C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools
	' C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
	' ※ VB.net のイベントを COM へ公開する為のインターフェイス定義
	<Guid("5FB047A1-0662-4fe6-B79E-552D08FCC7BA"), _
	InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
	Public Interface ILboxToolEvents
	    <DispId(1)> _
	    Sub EndDownload()
	    <DispId(2)> _
	    Sub EndDownload2( str As String )
	End Interface

	' VB.net のイベントを COM へ公開する
	<ComSourceInterfaces(GetType(ILboxToolEvents))> _
	Public Class lbox

		' Win32 API を使う為の定義
		<DllImport("urlmon.dll", CharSet:=CharSet.Unicode)> _
		Private Shared Function URLDownloadToFile( _
		  ByVal pCaller As Integer, _
		  ByVal szURL As String, _
		  ByVal szFileName As String, _
		  ByVal dwReserved As Integer, _
		  ByVal lpfnCB As Integer _
		) As Integer
		End Function

		' ******************************************************
		' COM へ公開するメソッド
		' ******************************************************
		Public Function URLDownloadToFile( target As String, _
			Optional local As String = Nothing ) As Boolean

			Dim ret As Integer
			Dim data As String()
			Dim result As Boolean = True

			if local is Nothing then
				data = target.Split("/")
				local = data(data.Length-1)
			end if

			ret = URLDownloadToFile( 0, target, local, 0, 0 )
			if ret = 0 then
				' ***********************
				' イベントを発生させる
				' ***********************
				RaiseEvent EndDownload()
				RaiseEvent EndDownload2( target )
			else
				result = False
			end if

		End Function

		' ******************************************************
		' COM へ公開するイベント
		' ******************************************************
		Public Event EndDownload()
		Public Event EndDownload2( URL As String )

	End Class

End Namespace

サンプルとしては、本来はスレッド使って非同期なイベントを作りたい
ところですが、複雑になるので同期のファイルダウンロードの終了イベ
ントを二通り作成しています。これを後で、WSH の VBScript と HTA で
利用するわけです。

ビルドの前に lightbox.snk 

sn.exe -k lightbox.snk 

sn.exe は、C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin にある
ので、これは Visual Studio 等がインストールされていないと作成できない
と思いますが、内容が内容なので、たぶんこの辺は OK でしょう。


ビルド

Framework2.0 と Framework3.5 で違いがありました。詳細はソースコードに
書いてありますが、以下のコマンドラインは 3.5 用です。

vbc.exe /target:library /keyfile:lightbox.snk lboxCom.vb

これで dll が作成されるので、問題が無ければシステムに登録します。


システムに登録

regasm lboxCom.dll /tlb:lboxComLib.tlb /codebase

カレントに dll を置いて実行すると、この場所でレジストリに登録され
ます。タイプライブラリ(lboxComLib.tlb)は、この時作成されます。
もし元の dll の内容を変更した場合は、一旦登録を削除して下さい。

regasm lboxCom.dll /unregister

問題なければ、以上で、lboxTool.lbox が登録された事になります。


次の記事(WSH&HTAで使用)

VB.net のイベントを COM へ公開する(2)。
つまり、WSH や HTA で VB.net で書いたコードを実行すると言う事。



タグ:イベント com
---
posted by lightbox at 02:07 | Comment(0) | サンプル | このブログの読者になる | 更新情報をチェックする

2010年07月17日

VB.net やるのに、Visual Studio は必要ありません

Vbc_console


ブラウザでダウンロード
今時は、Framework SDK は Windows の一部だと思いますが、仮に無くても Microsoft から
ダウンロードしてインストールするのは一般的なフリーソフトを使う事よりはるかに容易で
す。とにかく、以下のディレクトリがあって、中に vbc.exe があれば VB.net のビルドは
いとも簡単にできてしまいます
%windir%\Microsoft.NET\Framework\v2.0.50727
%windir%\Microsoft.NET\Framework\v3.5

極端な話、hello.vb があったとすれば、vbc hello.vb でビルドは完了して hello.exe
が出来上がります。この事を考えれば、PowerShell を使うよりこちらのほうが楽かもし
れないと思えるほどです。

しかし、それなりに使いやすくするには工夫が必要なのでこのパッケージをお使い下さい。

※ 以下は、同梱してあるサンプルソースコードです
' Imports System.Windows.Forms
' Imports System.IO

Module MyModule

' ********************************************************
' エントリポイント
' ********************************************************
Sub Main()

	' バイト配列( バイナリ )
	Dim ByteCrLf As Byte() = New Byte() { 13,10 } 
	' 文字列としての CrLf 
	Dim CrLf As String = System.Text.Encoding.ASCII.GetString(ByteCrLf) 

	Console.WriteLine( "---------------------------------" )

	' 文字列の配列
	Dim argv As String()

	' コマンドラインの取得
	argv = System.Environment.GetCommandLineArgs()

	' コマンドライン上のトークンの数
	Console.WriteLine( "■ コマンドライン上のトークンの数" )
	Console.WriteLine( argv.Length )

	Dim i As Integer

	Console.WriteLine( CrLf + "■ コマンドライン上のトークン" )
	' 引数のトークンを全て表示します
	For i = 0 TO argv.Length - 1

		Console.WriteLine( argv(i) )

	Next

	Dim FullPath As String

	' このプログラムのフルパス
	' GetFullPath に渡すファイルは存在する必要はありません
	' カレントディレクトリを使用してパスを作成します
	FullPath = System.IO.Path.GetFullPath( argv(0) )

	Console.WriteLine()
	Console.WriteLine( "■ このプログラムのフルパス" + CrLf + FullPath )

	' このプログラムが存在するディレクトリ
	' 単純な文字列処理である事に注意
	Console.WriteLine()
	Console.WriteLine( "■ このプログラムのディレクトリ" )
	Console.WriteLine( System.IO.Path.GetDirectoryName( FullPath ) )

	' Imports System.Windows.Forms を記述すると、
	' System.Windows.Forms. を省略できます
	System.Windows.Forms.MessageBox.Show( "処理が終了しました" )

End Sub

End Module



---
posted by lightbox at 02:59 | Comment(0) | サンプル | このブログの読者になる | 更新情報をチェックする