|
現在vb.net Framework 4.5.2にてVBAで使えるクラスライブラリを作成しています。
そこでShell.Execの拡張機能を作成しようとしたところ非同期で「イベント」を発生させることができず
困っております。
原因がわからない為様々な方法を試したのですがやはり「イベント」を発生させることができませんでした。
まことに申し訳ないのですが、よろしくお願いします。
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Text
<Guid(Shell.EventsId)>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
<ComVisible(True)>
Public Interface IShellEvents
<Description("標準出力にデータが記載された時のイベント。")>
<DispId(1)> Sub OutputDataReceived(ByVal data As Object)
End Interface
<Guid(Shell.InterfaceId)>
<InterfaceType(ComInterfaceType.InterfaceIsDual)>
<ComVisible(True)>
Public Interface IShell
<Description("子コマンドシェルでアプリケーションを実行します。")>
Function Exec() As Integer
End Interface
<Guid(Shell.ClassId)>
<ComVisible(True)>
<ClassInterface(ClassInterfaceType.None)>
<ComSourceInterfaces(GetType(IShellEvents))>
<ComDefaultInterface(GetType(IShell))>
Public Class Shell : Implements IShell
Public Const ClassId As String = "11A6BA24-E5C6-47FB-AF64-4FD635D14B95"
Public Const InterfaceId As String = "88B16B14-0BA8-45A3-8F4A-BA56DB7C1CCE"
Public Const EventsId As String = "A4FC31AA-D01D-449E-A6E6-AFC1BED947E2"
Friend _proc As System.Diagnostics.Process '実行プロセス
''' <summary>
''' 非同期読込情報
''' </summary>
Friend Class AsyncReadObject
Friend _proc As System.Diagnostics.Process
Friend _esd As EventSeparaterDelegate
Friend _rld As ReadLineDelegate
Friend Property data As String
Public Sub New(ByVal proc As System.Diagnostics.Process, ByVal esd As EventSeparaterDelegate, ByVal rld As ReadLineDelegate)
Me._proc = proc '実行プロセス
Me._esd = esd 'イベント振り分けデリケード
Me._rld = rld '出力読み取りデリケード
Me.data = "" '読込データ
End Sub
End Class
''' <summary>
''' Exec
''' 子コマンドシェルでアプリケーションを実行します。
''' </summary>
Public Function Exec() As Integer Implements IShell.Exec
_proc = New System.Diagnostics.Process()
Dim psi As New System.Diagnostics.ProcessStartInfo()
'----- ファイルパスと引数を設定
psi.FileName = "C:\WINDOWS\system32\cmd.exe"
psi.Arguments = " /c dir c:\ /w"
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden
psi.CreateNoWindow = True
psi.RedirectStandardInput = True
psi.RedirectStandardOutput = True
psi.RedirectStandardError = True
psi.UseShellExecute = False
_proc.StartInfo = psi
'----- 実行
Call _proc.Start()
'----- 非同期での出力とエラーの読み取り設定
Dim esd As EventSeparaterDelegate = New EventSeparaterDelegate(AddressOf EventSeparater) 'イベント振り分け(イベント発生用)
esd.Invoke("イベントテスト") '※正常にイベントが発生される
Dim orld As ReadLineDelegate = New ReadLineDelegate(AddressOf ReadLine) '出力読み取り
Dim oaro As AsyncReadObject = New AsyncReadObject(_proc, esd, orld) '非同期読取情報
orld.BeginInvoke(oaro, New AsyncCallback(AddressOf ReadEnd), oaro) '出力読み取りを非同期で実行
Return _proc.Id
End Function
''' <summary>
''' ReadLine
''' 出力読み取り
''' </summary>
''' <param name="aro">非同期読込情報</param>
Friend Delegate Sub ReadLineDelegate(ByVal aro As AsyncReadObject)
Friend Sub ReadLine(ByVal aro As AsyncReadObject)
aro.data = aro._proc.StandardOutput.ReadLine()
End Sub
''' <summary>
''' ReadEnd
''' 出力読み取り完了
''' </summary>
''' <param name="iar">非同期ステータス</param>
Friend Sub ReadEnd(ByVal iar As IAsyncResult)
Dim aro As AsyncReadObject = CType(iar.AsyncState, AsyncReadObject)
aro._rld.EndInvoke(iar) '出力読み取りの終了
aro._esd.Invoke(aro.data) 'イベント振り分け実行
If Not aro._proc.StandardOutput.EndOfStream Then
aro._rld.BeginInvoke(aro, New AsyncCallback(AddressOf ReadEnd), aro) '出力読み取り再実行
End If
End Sub
''' <summary>
''' EventSeparater
''' イベント振り分け
''' </summary>
''' <param name="data">データ</param>
Friend Delegate Sub EventSeparaterDelegate(ByVal data As Object)
Friend Sub EventSeparater(ByVal data As Object)
RaiseEvent OutputDataReceived(data) '※イベントが取得できない
End Sub
''' <summary>
''' OutputDataReceived
''' 標準出力にデータが記載された時
''' </summary>
''' <param name="data">データ</param>
Friend Delegate Sub outputDataReceivedDelegate(ByVal data As Object)
Friend Event OutputDataReceived As outputDataReceivedDelegate
End Class
|