如何在C#中创建ActiveX控件?
我无法在C#中创建正常运行的ActiveX控件;我尝试了以下教程,但没有成功 我创建了一个示例类库项目,其中包括以下代码:如何在C#中创建ActiveX控件?,c#,com,activex,tstcon32,C#,Com,Activex,Tstcon32,我无法在C#中创建正常运行的ActiveX控件;我尝试了以下教程,但没有成功 我创建了一个示例类库项目,其中包括以下代码: namespace AACWCSurvey { [ProgId("Prisoner.PrisonerControl")] [ClassInterface(ClassInterfaceType.AutoDual)] public class Class1 { public Class1() {
namespace AACWCSurvey
{
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
public Class1()
{
MessageBox.Show("FIRETRUCK!!!");
}
}
}
然后,我执行了以下步骤:
regasm MyDll.dll/tlb/codebase
囚犯.PrisonerControl
=(UPD:它从VBScript开始工作:
Dim objJava
Set objJava = WScript.CreateObject("Prisoner.PrisonerControl")
但是它在tstcon32中不可见。如果您使用Captive.PrisonerControl控件进行读取,则会在具有控件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机器,但这是另一回事。您创建了一个COM服务器,但没有ActiveX控件,这是一个复杂得多的COM对象,您可以使用tstcon32.exe执行
它必须实现一系列接口,关键的是IOleObject和IOleWindow。这种接口允许它与ActiveX主机进行所需的协商并创建一个可见窗口。Winforms控件类是创建一个窗口的最佳选择。以下是相关步骤。这是一个总结,省去了一些说明但没有任何必要的步骤 这个例子也非常类似于Garry Trinder在2008年11月25日发表的文章,我还包括了本文中的一些注释 将Windows窗体控件公开为ActiveX控件 本文将介绍如何使用Windows窗体控件 在.NET之外 写入控件
Control
,MiscStatus
,TypeLib
和
Version
[可以使用.REG
脚本创建],但通常更好
编写在注册/注销时调用的函数
他详细描述了注册表项:
Control
是空子键。TypeLib
映射到
TypeLib(这是assemblyinfo.cs中的程序集级别GUID)。
Version
是程序集的主要版本号和次要版本号
唯一稍微有趣的子键是MiscStatus
。这需要
设置为由OLEMISC
枚举。若要使此枚举可用,请添加
参考Microsoft.VisualStudio.OLE.Interop
(以及合适的
命名空间的“using”语句)
他的最后一句话是警告:
注意:这对于Excel似乎是可行的(测试非常有限)
我做过),部分使用PowerPoint,但在使用PowerPoint时失败惨重
可能,更多的OLEMISC
值可能会改善这一点;
可能有一些消息我们需要钩住;可能有
我们需要实现更多的接口…事实上我只需要
几乎没有以非常有限的方式让它工作
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[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 ( ) ;
}
[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 ( ) ;
}