我无法在C#中创建一个正常运行的ActiveX控件;我尝试过以下教程但没有成功。
我创建了一个示例类库项目,其中包含以下代码:
namespace AACWCSurvey
{
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
public Class1()
{
MessageBox.Show("FIRETRUCK!!!");
}
}
}
然后我做了以下步骤:
regasm MyDll.dll /tlb /codebase
在tstcon32 =(
Prisoner.PrisonerControl
醇>
我的操作系统是WinXP x86。
UPD:它适用于VBScript:
Dim objJava
Set objJava = WScript.CreateObject("Prisoner.PrisonerControl")
但它在tstcon32中不可见。
答案 0 :(得分:2)
如果您使用Prisoner.PrisonerControl控件阅读the actual article,则会使用您的控件GUID在密钥内创建一个名为Control
的子密钥。
在我的机器上使用guid {9DEA5F06-E324-31A7-837B-D0F3BDE91423}
创建密钥
HKEY_CLASSES_ROOT\CLSID\{9DEA5F06-E324-31A7-837B-D0F3BDE91423}\Control
使控件显示在tstcon32
中。无论有没有它,ActiveX都可用于javascript
var x = new ActiveXControl("Prisoner.PrisonerControl");
实际上我不得不在javascript执行和注册表路径上对抗Windows以在我的系统上测试它,因为它是一台x64机器,但这是另一个故事。
答案 1 :(得分:2)
您已经创建了一个COM服务器,但没有创建ActiveX控件,这是一个复杂得多的COM对象,您可以使用tstcon32.exe进行操作。
它必须实现一堆接口,关键的是IOleObject和IOleWindow。允许它与ActiveX主机进行必要协商并创建可见窗口的接口类型。 Winforms控件类是您创建一个类的最佳选择。
答案 2 :(得分:0)
以下是相关步骤as documented externally。对其进行了总结,省略了一些说明,但没有任何必要的步骤。
此示例也与2008年11月25日Garry Trinder的文章Using Managed Controls as ActiveX Controls非常相似,并且我也包括了本文的一些注释。
将Windows窗体控件公开为ActiveX控件
本文将介绍如何利用Windows窗体控件 .NET外部。
编写控件
- 在Visual Studio中创建一个新的控件项目-我的示例全部使用C#,但也可以使用VB.NET。
[这里Garry的文章建议,“ 首先,创建一个托管的用户控件项目-Windows Forms类库或控件库项目。使用用户控件设计器以所需的方式设计自定义用户控件(使用任何标准控制您喜欢的对象。)“]
将控件等添加到表单中,放入代码等中。
添加以下using子句...
using System.Runtime.InteropServices; using System.Text; using System.Reflection; using Microsoft.Win32;
- 为您的类分配属性,以便它获得ProgID。并非绝对必要,因为会生成一个,但是几乎总是最好 明确的。
[ProgId("Prisoner.PrisonerControl")] [ClassInterface(ClassInterfaceType.AutoDual)]
这分配了ProgID,并且还定义了接口 暴露的应该是“ AutoDual”-这是为了 班上所有公开的,非静态的成员。如果不是这样 您需要使用其他选项之一。
- 更新项目属性,以便为程序集注册COM互操作。
如果您使用的是VB.NET,则还需要一个强大的命名程序集。 奇怪的是,您没有使用C#,这似乎是C#的一个功能 环境,而不是编译器或CLR的功能。
- 将以下两个方法添加到您的类中。
[ComRegisterFunction()] public static void RegisterClass ( string key ) { // Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it StringBuilder sb = new StringBuilder ( key ) ; sb.Replace(@"HKEY_CLASSES_ROOT\","") ; // Open the CLSID\{guid} key for write access RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true); // And create the 'Control' key - this allows it to show up in // the ActiveX control container RegistryKey ctrl = k.CreateSubKey ( "Control" ) ; ctrl.Close ( ) ; // Next create the CodeBase entry - needed if not string named and GACced. RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ; inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ; inprocServer32.Close ( ) ; // Finally close the main key k.Close ( ) ; }
RegisterClass函数通过ComRegisterFunction分配- 在为程序集注册时将调用此静态方法 COM互操作。我在这里所做的只是将'Control'关键字添加到 注册表,再添加CodeBase条目。
CodeBase很有趣-不仅适用于.NET控件。它定义一个URL 可以找到代码的路径,可以是程序集 这样的磁盘,或Web服务器上的远程程序集 某处。当运行时尝试创建控件时,它将 探测此URL并根据需要下载控件。这非常 在测试.NET组件时很有用,就像常驻的警告一样 与.EXE位于同一目录(等)中的文件不适用。
[ComUnregisterFunction()] public static void UnregisterClass ( string key ) { StringBuilder sb = new StringBuilder ( key ) ; sb.Replace(@"HKEY_CLASSES_ROOT\","") ; // Open HKCR\CLSID\{guid} for write access RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true); // Delete the 'Control' key, but don't throw an exception if it does not exist k.DeleteSubKey ( "Control" , false ) ; // Next open up InprocServer32 RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ; // And delete the CodeBase key, again not throwing if missing k.DeleteSubKey ( "CodeBase" , false ) ; // Finally close the main key k.Close ( ) ; }
第二个功能将删除在(if)时添加的注册表项 班级未注册-整理整齐总是一个好的建议 随你去。
现在您可以编译并测试控件了。
Garry博客的其他说明:
[The]其他注册表项:
Control
,MiscStatus
,TypeLib
和Version
[可以创建]使用.REG
脚本,但是通常更好 编写将在注册/注销时调用的功能
他详细描述了注册表项:
Control
是一个空的子项。TypeLib
映射到 TypeLib(这是assemblyinfo.cs中的程序集级GUID)。Version
是程序集中的主要和次要版本号 版。唯一有趣的子项是MiscStatus
。这需要 设置为由OLEMISC
中的(按位)值组成的值 枚举documented here。要使该枚举可用,请添加一个 引用Microsoft.VisualStudio.OLE.Interop
(以及适当的 命名空间的“使用”语句。
他的最后一句话是警告:
注意:这对于Excel似乎可以正常工作(测试非常有限 我已经做完了),部分使用PowerPoint,但失败了 字。可能,更多的
OLEMISC
值可能会改善此情况; 可能有些消息需要我们钩住;可能有 我们还需要实现一些其他接口...事实上,我只是 勉强让它以非常有限的方式工作应该告诉你 可能不是您想以任何严肃的方式使用的技术。