Ame*_*ILI 25 c# com events vba
我一直在尝试向VBA客户端公开和触发事件.到目前为止,在VBA客户端,事件已暴露,我看到方法事件处理方法已添加到我的模块类,但VBA事件处理方法不会触发.出于某种原因,调试事件时为null.同步修改我的代码也没有帮助.
为了记录,我已经检查了其他SO问题,但他们没有帮助.
任何好的答案将不胜感激.
[ComVisible(true)]
[Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IWebEvents))]
[ProgId("MyAssembly.MyClass")]
public class MyClass : ServicedComponent, IMyClass
{
public string _address { get; private set; }
public string _filename { get; private set; }
[DispId(4)]
public void DownloadFileAsync(string address, string filename)
{
_address = address;
_filename = filename;
System.Net.WebClient wc = new System.Net.WebClient();
Task.Factory.StartNew(() => wc.DownloadFile(_address, _filename))
.ContinueWith((t) =>
{
if (null != this.OnDownloadCompleted)
OnDownloadCompleted();
});
}
public event OnDownloadCompletedEventHandler OnDownloadCompleted;
}
[ComVisible(false)]
public delegate void OnDownloadCompletedEventHandler();
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IWebEvents
{
[DispId(1)]
void OnDownloadCompleted();
}
Run Code Online (Sandbox Code Playgroud)
对于所有赏金猎人来说,这是一个很好的演出,200个代表点
dee*_*dee 20
.net代码中的关键概念是将事件定义为单独接口上的方法,并通过它将其连接到类[ComSourceInterfacesAttribute].在示例中,这是通过此代码完成的,[ComSourceInterfaces(typeof(IEvents))]其中IEvents接口定义应在COM客户端上处理的事件.
事件命名注意事项:c#类中定义的事件名称和接口上定义的接口方法名称必须相同.在这个例子中IEvents::OnDownloadCompleted对应DemoEvents::OnDownloadCompleted.
然后定义第二个接口,它表示类本身的公共API,在这里它被调用IDemoEvents.在此接口上定义了在COM客户端上调用的方法.
C#代码(构建到COMVisibleEvents.dll)
using System;
using System.EnterpriseServices;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace COMVisibleEvents
{
[ComVisible(true)]
[Guid("8403C952-E751-4DE1-BD91-F35DEE19206E")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IEvents
{
[DispId(1)]
void OnDownloadCompleted();
}
[ComVisible(true)]
[Guid("2BF7DA6B-DDB3-42A5-BD65-92EE93ABB473")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IDemoEvents
{
[DispId(1)]
Task DownloadFileAsync(string address, string filename);
}
[ComVisible(true)]
[Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IEvents))]
[ProgId("COMVisibleEvents.DemoEvents")]
public class DemoEvents
: ServicedComponent, IDemoEvents
{
public delegate void OnDownloadCompletedDelegate();
private event OnDownloadCompletedDelegate OnDownloadCompleted;
public string _address { get; private set; }
public string _filename { get; private set; }
private readonly string _downloadToDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
public async Task DownloadFileAsync(string address, string filename)
{
try
{
using (WebClient webClient = new WebClient())
{
webClient.Credentials = new NetworkCredential(
"user", "psw", "domain");
string file = Path.Combine(_downloadToDirectory, filename);
await webClient.DownloadFileTaskAsync(new Uri(address), file)
.ContinueWith(t =>
{
// https://stackoverflow.com/q/872323/
var ev = OnDownloadCompleted;
if (ev != null)
{
ev();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
catch (Exception ex)
{
// Log exception here ...
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
文件下载注意事项:要下载文件,请WebClient.DownloadFileTaskAsync使用该方法.它使用任务对象将指定资源作为异步操作下载到本地文件.任务对象通常在线程池线程上异步执行,而不是在主应用程序线程上同步执行.因此,必须调用ContinueWith主线程,否则将无法执行该OnDownloadCompleted事件.这就是为什么ContinueWith(continuationAction, TaskScheduler.FromCurrentSynchronizationContext)使用.
regasm
C:\Windows\Microsoft.NET\Framework\v4.0.30319>regasm C:\Temp\COMVisibleEvents\bin\Debug\COMVisibleEvents.dll /tlb: C:\Temp\COMVisibleEvents\bin\Debug\COMVisibleEvents.tlb
Run Code Online (Sandbox Code Playgroud)
VBA客户端引用
*.tlb文件
添加*tlb由其生成的引用regasm.这里是这个tlb文件的名称COMVisibleEvents.
这里Excel用户表单用作VBA客户端.单击按钮后,DownloadFileAsync执行该方法,当此方法完成时,事件在处理程序中被捕获m_eventSource_OnDownloadCompleted.在此示例中,您可以从我的保管箱下载c#项目COMVisibleEvents.dll的源代码.
VBA客户端代码(MS Excel 2007)
Option Explicit
Private WithEvents m_eventSource As DemoEvents
Private Sub DownloadFileAsyncButton_Click()
m_eventSource.DownloadFileAsync "https://www.dropbox.com/s/0q3dskxopelymac/COMVisibleEvents.zip?dl=0", "COMVisibleEvents.zip"
End Sub
Private Sub m_eventSource_OnDownloadCompleted()
MsgBox "Download completed..."
End Sub
Private Sub UserForm_Initialize()
Set m_eventSource = New COMVisibleEvents.DemoEvents
End Sub
Run Code Online (Sandbox Code Playgroud)
结果
| 归档时间: |
|
| 查看次数: |
3821 次 |
| 最近记录: |