- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们的团队正在编写一些代码,要求我们与联网设备进行交互。该设备使用专有协议(protocol),制造商以OCX控件(即ActiveX控件)的形式为我们提供了接口(interface)库。
我在尝试使用 ActiveX 控件时遇到过几次错误的开始,例如使用包含在 C++/CLI 中的 native C++ (MFC),包含在 C# 中,我了解到我可以将控件拖放到 winforms 窗体中,还有一些包装器代码将自动生成。因此,我将控件放在一个空的表单中,并将其方法和事件存入表单中,目的是让此表单成为控件的代理/包装类。
我现在遇到的问题是设备通过每隔几秒发回一个数据包来报告其状态。这应该会导致 ActiveX 控件引发事件,但只有当表单在 Application
中运行时才会引发这些事件:
Application.Run(new Form());
为了在控制台应用程序或单元测试中使用表单类,我尝试过这样的事情:
Var proxy = new Form();
Task.Run(() => { Application.Run(proxy); };
proxy.SomeMethod();
但这会引发异常:跨线程操作无效:从创建它的线程以外的线程访问控件“Form1”
由于代理类最终将在 Windows 服务中运行,因此这是一个交易破坏者。如何启用 ActiveX 控件引发事件而不在应用程序内部托管其窗体?
最佳答案
该片段提供的指导很少,但它肯定在不止一个方面是错误的。它死得太早了,无法解决真正的问题。 “跨线程操作无效”异常是尝试在工作线程拥有的对象上调用 SomeMethod() 方法的简单结果。您必须使用 Begin/Invoke() 方法来避免这种情况发生。在尝试使用它之前,您还必须确保工作线程正在运行并且控件已正确初始化。
更大的问题是线程不适合支持 ActiveX 控件。该线程必须标记为 STA(单线程单元),这是您做出的 promise ,即您将为非线程安全的代码提供一个好客的家。与任何 ActiveX 控件一样。实现 STA 契约(Contract)需要泵送消息循环 (Application.Run) 并且从不阻塞线程。 Task
不会创建这样的线程,线程池线程不能被标记为 STA。你需要一个 custom TaskScheduler或者只是一个普通的线程,所以你可以调用它的 SetApartmentState() method .
一些示例代码可以帮助您开始:
using System;
using System.Threading;
using System.Windows.Forms;
class ActiveXHost : Form {
public ActiveXHost(Control control, bool hidden = false) {
if (control.IsHandleCreated) throw new InvalidOperationException("Control already committed to wrong thread");
if (hidden) this.Opacity = 0;
this.ShowInTaskbar = false;
using (initDone = new ManualResetEvent(false)) {
thread = new Thread((_) => {
this.Controls.Add(control);
Application.Run(this);
});
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
initDone.WaitOne();
}
}
public void Execute(Action action) {
this.BeginInvoke(action);
}
public TResult Execute<TResult>(Func<TResult> action) {
return (TResult)this.Invoke(action);
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
initDone.Set();
}
protected override void Dispose(bool disposing) {
if (disposing && thread != null) {
this.Invoke(new Action(() => {
base.Dispose(disposing);
Application.ExitThread();
thread = null;
}));
}
}
private Thread thread;
private ManualResetEvent initDone;
}
构造函数负责创建合适的 STA 线程并负责与该线程的互锁,确保在线程启动并运行并且 ActiveX 控件准备好开始生成事件之前它不会完成。如果您收到 InvalidOperationException,那么您初始化控件的方式有问题,请通过订阅控件的 HandleCreated 事件来诊断。
我添加了 Execute() 方法,让您有机会正确调用 SomeMethod()。
使用 Dispose() 方法销毁控件并终止线程。
对于服务,您通常会像这样使用它:
ActiveXHost host;
protected override void OnStart(string[] args) {
var ctl = SomeAxHostWrapper();
host = new ActiveXHost(ctl);
ctl.HasMessage += MessageReceived;
}
protected override void OnStop() {
host.Dispose();
host = null;
}
请记住,服务并不是 ActiveX 控件的理想环境。它们在 session 0 中运行,该 session 具有较小的桌面堆。这可能会导致您的服务失败并出现难以理解的 0xC0000142 异常。背景 is here
关于c# - 启用 ActiveX 控件以在不在 System.Windows.Forms.Application 中运行的情况下引发事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36853716/
我创建了一个安装在客户端计算机上的 ActiveX 控件。现在我已经在 ActiveX 控件中进行了一些更改,现在希望更改的 ActiveX 应该在客户端计算机中自动更新。 我已将安装文件的版本从 1
我用 C# 创建了一个 com 组件,并使用 Regasm 注册了该组件。我现在可以通过使用 ActiveXObject(...) 在 IE 中使用它。然而,这只在我更改 IE 安全设置并允许运行
我以前做过,但我完全忘记了如何签署 activeX 控件? 最佳答案 Digital Signing for ActiveX Components (MSDN) 关于activex - 签署 Acti
我有一个多页网页流 (jsp)。用户完成大量工作后,我需要使用 activex 组件,如果机器上没有显示,用户会在顶部显示黄色条以接受组件,接受后页面将重新加载,用户必须重复所有操作工作,请注意页面已
背景 有一个由 VB 创建的旧 ActiveX 控件。我将此 ActiveX 控件添加到我的 Excel 工作簿并设置了一些属性。这些属性是在保存书籍时保存的。具体来说,它们在 VB 代码中使用 Pr
我有一个想要从 SAP 调用的自定义 ActiveX 控件。 在这种情况下我不能使用 PI,我还有什么其他选择? 最佳答案 看节目 SAPRDEMO_ACTIVEX_INTEGRATION 举个例子。
我的 .NET 程序中有 WebBrowser 控件。实际上使用哪个 .net 包装器(wpf 或 winforms)并不重要,因为它们都包装 ActiveX 组件“Microsoft Interne
我有一个正在注册多个 dll 的安装程序,需要知道这是否成功。 最佳答案 这似乎对我有用:http://www.nirsoft.net/utils/registered_dll_view.html 关
如何将 ActiveX 应用程序转换为 NPAPI 应用程序? 我找到的所有方法都是为 NPAPI 实现入口点和映射函数。 (NPP_GetEntryPoints...)除了使用 Framework
“ActiveX 控件——小程序构建 block ——可以用于创建分布式应用程序,这些应用程序可以通过 Web 浏览器在 Internet 上运行。示例包括用于收集数据、查看某些类型的文件和显示动画的
微软发布了 Edge 浏览器,该浏览器不支持 ActiveX。 我有一个应用程序需要从 Windows 注册表获取信息,因此我对 ActiveX 的替代方案有一些疑问: 有没有办法通过 Edge 或类
我正在使用现有的 SDK 编写一个附加组件,该 SDK 没有类似 webview 的组件,但允许使用 ActiveX 控件。 所以我想到的唯一想法是找到一个实现网络浏览器的 ActiveX 控件,或者
嗨,我有一个这样的 ActiveX: CMyActiveX 类: 公共(public) CComObjectRootEx... ... { HRESULT FinalContruct(){return
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
我有一个放置在 IE 浏览器容器中的 ActiveX 控件。该控件创建另一个启用了 WS_POPUP 和 WS_LAYERED 属性的对话框窗口,以便能够使用 SetLayeredWindowAttr
几天前,我在 Internet Explorer 中搜索了一种无需打印对话框直接打印的方法,并找到了这个 solution . 在此解决方案中,使用 ActiveX 对象“Shell.Explorer
我在服务器端使用 ASP.NET,在客户端使用 JavaScript。 我正在尝试开发一些有助于用户进行故障排除的页面,我想知道是否有一种方法可以通过编程方式确定以下内容: 如果 ActiveX 在
在 Visual Studio 2008 中,我可以创建一个 MFC activex 项目,它提供了一个向导来创建单个 activex 控件。我现在想在这个项目中创建新控件。 我找不到任何方法来做到这
我正在尝试为一个简单的 hello world 消息框运行 activex 控件。 首先,我创建了类库,现在有了 dll,然后我创建了 HTML 页面并调用了 activeX 控件:
免责声明:我没有签署文件的经验,这是我第一次。 我们的网站有一个通配符 SSL 证书。现在我们要在我们的一个站点上托管一个 ActiveX 控件。当我尝试使用该证书对我的 cab 文件进行签名时,它会
我是一名优秀的程序员,十分优秀!