C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

vb.netで作成したCOMのイベントをvbaで取得できない

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■93914 / inTopicNo.1)  vb.netで作成したCOMのイベントをvbaで取得できない
  
□投稿者/ kume (1回)-(2020/02/19(Wed) 19:08:15)

分類:[VB.NET/VB2005 以降] 

現在Visual Studio 2017
vb.net (.NET Framework 4.0)にてOffice Excel2013、Access2013使えるCOM.DLLを作成しています。
以下のHPを参考にvb.net用に変更して、VBAからCOMへの参照設定を行い実行する事ができました。
https://tutorialmore.com/questions-1891335.htm
しかしVBAでCOMからのイベントが取得できない状態で困っております。

引用返信 編集キー/
■93915 / inTopicNo.2)  Re[1]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ kume (2回)-(2020/02/19(Wed) 19:10:16)
2020/02/19(Wed) 19:13:18 編集(投稿者)
'----- vb.netのClass(COMVisibleEvents)-----
Imports System.EnterpriseServices
Imports System.IO
Imports System.Net
Imports System.Runtime.InteropServices
Imports System.Threading.Tasks

Namespace COMVisibleEvents

    <ComVisible(True)>
    <InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
    <Guid("B64928E8-1D07-4FE8-AD5D-E479CD75C6C4")>
    Public Interface IEvents
        <DispId(1)> Sub OnDownloadCompleted()
    End Interface

    <ComVisible(True)>
    <InterfaceType(ComInterfaceType.InterfaceIsDual)>
    <Guid("47A87A45-2B51-482F-ADF5-AF818A31F96D")>
    Public Interface IDemo
        <DispId(2)> Function DownloadFileAsync(address As String, filename As String) As Task
    End Interface

    <ComVisible(True)>
    <ClassInterface(ClassInterfaceType.None)>
    <ComDefaultInterface(GetType(IDemo))>
    <ComSourceInterfaces(GetType(IEvents))>
    <Guid("C58721B1-15B3-4eeb-9E1E-BCDA33D38EE6")>
    Public Class DemoEvents : Inherits ServicedComponent : Implements IDemo
        Public Delegate Sub OnDownloadCompletedDelegate()
        Public Event OnDownloadCompleted As OnDownloadCompletedDelegate

        Public Function DownloadFileAsync(address As String, filename As String) As Task Implements IDemo.DownloadFileAsync
            Try
                Using webClient As WebClient = New System.Net.WebClient()
                    webClient.Credentials = New NetworkCredential("user", "psw", "domain")
                    'イベントハンドラの作成
                    AddHandler webClient.DownloadFileCompleted, AddressOf downloadClient_DownloadFileCompleted
                    webClient.DownloadFileAsync(New Uri(address), filename)
                End Using
            Catch ex As Exception
                ' Log exception here ...
            End Try
        End Function

        Private Sub downloadClient_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
            If e.Cancelled Then
                MsgBox("キャンセルされました。")
            ElseIf Not (e.Error Is Nothing) Then
                MsgBox("エラー:" & e.Error.Message)
            Else
                MsgBox("ダウンロードが完了しました。")
            End If
            Try
                RaiseEvent OnDownloadCompleted()
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub

    End Class

End Namespace

引用返信 編集キー/
■93916 / inTopicNo.3)  Re[2]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ kume (3回)-(2020/02/19(Wed) 19:11:32)
2020/02/19(Wed) 19:36:53 編集(投稿者)
'----- vba側の参照設定 -----
COMVisibleEvents

'----- vba側のClass(Class1)-----
Public WithEvents objCOMVisibleEvents As COMVisibleEvents.DemoEvents

'※WithEventsにてイベント記述が取得できている事は確認できています
Private Sub objCOMVisibleEvents_OnDownloadCompleted()
    Debug.Print "OnDownloadCompleted"
End Sub

'----- vba側のModule(Module1)-----
Function Test1()
    Dim cl As Class1
    Set cl = New Class1
    Set cl.objCOMVisibleEvents = New COMVisibleEvents.DemoEvents
    Call cl.objCOMVisibleEvents.DownloadFileAsync("https://www.google.com/〜/googlelogo_color_272x92dp.png", "c:\googlelogo.png")
End Function

引用返信 編集キー/
■93917 / inTopicNo.4)  Re[3]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ kume (4回)-(2020/02/19(Wed) 19:11:47)
VBAでTest1()を実行すると「googlelogo.png」がダウンロードされvb.net側の"ダウンロードが完了しました。"のメッセージが表示されます。
しかしVBA側のobjCOMVisibleEvents_OnDownloadCompleted()イベントはなにも反応しない状態です。
またvb.netでのRaiseEvent時エラーキャッチもない為エラーメッセージも表示されません。

他のHPでのサンプルも試したのですが同じくイベントが取得できませんでした。ご指導のほどよろしくお願いします。
引用返信 編集キー/
■93918 / inTopicNo.5)  Re[4]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ Hongliang (963回)-(2020/02/19(Wed) 20:14:22)
リンク先と見比べたところ、DownloadFileAsyncの実装の内容が少々異なっているようですが。
お書きのコードだとTaskを返していませんよね?
リンク先では、WebClientのDownloadFileAsyncではなくDownloadFileTaskAsyncを使用していますし、DownloadFileCompletedイベントではなくてContinueWithで続きを行っていますし。
引用返信 編集キー/
■93919 / inTopicNo.6)  Re[5]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ kume (5回)-(2020/02/19(Wed) 20:41:32)
No93918 (Hongliang さん) に返信
> リンク先と見比べたところ、DownloadFileAsyncの実装の内容が少々異なっているようですが。
> お書きのコードだとTaskを返していませんよね?
はい。vb.netに変換したときに抜けていました。すみません。

> リンク先では、WebClientのDownloadFileAsyncではなくDownloadFileTaskAsyncを使用していますし、DownloadFileCompletedイベントではなくてContinueWithで続きを行っていますし。
はい。リンク先の「DownloadFileTaskAsync」は.NET Framework 4.5からの為、.NET Framework 4.0「DownloadFileAsync」を使用しました。

一応リンク先のC#のコードでも試したのですがイベントを取得することはできませんでした。
引用返信 編集キー/
■93922 / inTopicNo.7)  Re[6]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ Hongliang (964回)-(2020/02/19(Wed) 22:07:45)
https://support.microsoft.com/ja-jp/help/17455/lifecycle-faq-net-framework
一応書いておきますが、.NET 4は既にサポート終了しています。
.NET 4.5.2, または.NET 4.6以降に移行することをお勧めします。

さて、実際に確認する環境がないので推測ですが、OnDownloadCompletedの呼び出しが、
DownloadFileAsyncを呼び出したスレッドと同じでなければならないということなのだと思います。
なので、.NET 4向けだとこんな感じの記述になるんじゃないでしょうか。

Dim ctx = TaskScheduler.FromCurrentSynchronizationContext()
Return Task.Factory.StartNew(Sub() wc.DownloadFile(_address, _filename)) _
    .ContinueWith(Sub(_task) RaiseEvent OnDownloadCompleted, ctx)

引用返信 編集キー/
■93923 / inTopicNo.8)  Re[7]: vb.netで作成したCOMのイベントをvbaで取得できない
□投稿者/ kume (6回)-(2020/02/19(Wed) 23:49:08)
2020/02/19(Wed) 23:50:10 編集(投稿者)
No93922 (Hongliang さん) に返信
> https://support.microsoft.com/ja-jp/help/17455/lifecycle-faq-net-framework
> 一応書いておきますが、.NET 4は既にサポート終了しています。
> .NET 4.5.2, または.NET 4.6以降に移行することをお勧めします。
HPまでありがとうございます。お客様を説得するのに役に立ちます。

> さて、実際に確認する環境がないので推測ですが、OnDownloadCompletedの呼び出しが、
> DownloadFileAsyncを呼び出したスレッドと同じでなければならないということなのだと思います。
> なので、.NET 4向けだとこんな感じの記述になるんじゃないでしょうか。
> 
> Dim ctx = TaskScheduler.FromCurrentSynchronizationContext()
> Return Task.Factory.StartNew(Sub() wc.DownloadFile(_address, _filename)) _
>     .ContinueWith(Sub(_task) RaiseEvent OnDownloadCompleted, ctx)

まずご指摘がありましたのでバージョン.NET 4.5.2に上げました。
次に教えていただいたソースを組み込んで実行しましたが、やはりイベントが発生しませんでした。

さらにご指摘がありました「呼び出したスレッドと同じ」という事で単純に
webClient.DownloadFile(address, file)
RaiseEvent OnDownloadCompleted()
したところイベントの発生が確認できました。

という事はやはり「呼び出したスレッドと同じ」でなければ実行されないようです。
構成を考え直さなければなりませんのでこれで解決済とさせていただきます。

Hongliang さんにご指摘されなければ気づきませんでした。
ありがとうございます。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ