如何获得COM服务器的写在VB.NET Excel中安装和自动化服务器列表中注册?(How to g

2019-07-20 12:33发布

版本

Excel 2007中,Windows Vista中,VB.NET,Visual Studio 2008中使用.NET 3.5 SP2,MSI安装程序包。

我所试图做的

我有写在VB.NET的Excel UDF。 据公开为COM服务器,因为你不能在.NET语言中直接创建Excel中的UDF。 安装是一个真正的痛苦,因为没有安装设置似乎得到完全正确; 没有人给你与注册服务器,注册类型库,并在Excel 2007中的自动化服务器的列表中的组件可见把COM服务器的客户机上安装包。

我已经试过

下面是类型库安装设置,与他们的缺陷在编译时显而易见,并且安装时:

vsdrfComSelfReg

  • 安装项目的编译过程中没有任何警告
  • 模块xxx.tlb注册失败。 HRESULT -2147024703
  • 组件的ProgID和GUID在注册表中设置,但该组件没有出现在自动化服务器的列表

vsdrfDoNotregister

  • 在编译过程中没有任何警告
  • 安装工作,但当然TLB未注册

vsdrfCOM

  • 编译时警告:警告:无法创建注册信息名为“xxx.tlb”文件
  • 类型库在安装过程中未注册

正确的设置应该是vsdrfCOM,如解释在这里 :

问:能否请人告诉是什么vsdrfCOM在Visual Studio中的安装项目是什么意思? 当我检查在安装项目的补充文件的属性之间的财产“注册”它是可用的。

答:这意味着,Visual Studio将在编译时提取COM注册数据,并把它的MSI文件(主要是MSI文件的注册表中,也有类表)。 所以,当你安装你的代码并不需要自行注册,因为该文件被复制到磁盘,并获得创建注册表项。 它还将通过向MSI的类型库表中的项创建类型库注册。

许多困难,似乎是Vista的具体。 尤其是,使用REGCAP实用生产从.TLB文件.reg文件在Vista中不起作用。 如果不是,也许这个建议是有用的 。 相反,它会产生空reg文件,当它在所有工作。

我已经尝试了所有的建议在这个StackOverflow的职位 。 该职位有技术问题的一个很好的说明:

在引用对话框中的条目来自HKCR \类型库的注册表项,而不是从HKCR \ CLSID。 如果您的程序集不引用对话框出现,但编译DLL的仍然可以使用你的COM组件,这意味着类和接口被正确注册程序集,但该类型库本身不是。

问题

任何人对如何使安装注册的组件和类型库的想法? 我没有访问Windows XP计算机。


阐述为什么这吮吸

该.TLB不需要任何编译后的代码来调用它。 我还没有尝试部署一个Excel自动化加载,因为你正在做的,但我的猜测是,应该的UDF加载和运行就好了。

这不是很喜欢在Excel中。

  • 用户打开一个工作表,并试图引用UDF。 它不找到,因为没有加载DLL。 失败
  • 用户进入首页| Excel选项|加载项| Excel的加载项+去和COM服务器未在加载项对话框中列出。 失败
  • 然后,用户按下自动化服务器,以获取可用的自动化服务器的列表。 该DLL是不存在的。 失败
  • 用户返回到加载项对话框,选择浏览,浏览到安装目录,并选择其一DLL(“XXX是不是有效的加载项”)或类型库(“您选择的文件不包含新的自动化服务器,或者您没有足够的权限......“)。 失败

据我所知道的,用户必须在命令行,使Excel的UDF / COM服务器提供regasm.exe运行。 你会感觉如何告诉人们运行命令行regasm安装的加载项到Excel?


编辑2009-10-04

迈克的意见和方向下面是真棒。 我不知道事情的关键是,安装程序已添加注册表项内置的注册表编辑器 。 哦,那跟属性ComRegisterFunctionAttribute安装功能并没有被微软称为安装 。 我已经有大约从他列举了源安装程序写入功能的方向。

Answer 1:

我参加了一个射击在部署自动化外接周末。 事实证明,这是非常复杂(不是惊喜给你!),我能找到绝对没有对如何做到这一点正确的在互联网上的来源。 没有。

有迹象表明,介绍如何使用来源RegAsm ,但没有如何正确使用安装项目注册一个自动化加载项,这是从标准的COM加载项稍有不同。

幸运的是,我能够解决这个问题。 下面是我发现了什么:

如果你读了一些关于如何创建并注册您的C#自动化插件,你会发现你需要添加一个名为注册表项物品的ProgrammableHKEY\_CLASSES\_ROOT\CLSID\\{GUID}其中{GUID}是你的COM可见类的GUID。

这通常是通过将一对由所标记的方法来完成ComRegisterFunctionAttribute和ComUnregisterFunctionAttribute 。 这方面的一个很好的例子来自于文章写在C#中自定义的Excel工作表函数由Gabhan贝瑞:

// C#:

[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type) {
  Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type));
}

[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type) {
  Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type), false);
}

private static string GetSubKeyName(Type type) {
  string s = @"CLSID\{" + type.GUID.ToString().ToUpper() + @"}\Programmable";
  return s;
}

翻译成VB.NET,这个作品出来:

'VB.NET:

<ComRegisterFunctionAttribute()> _
Public Shared Sub RegisterFunction(ByVal type As Type)
    Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type))
End Sub

<ComUnregisterFunctionAttribute()> _
Public Shared Sub UnregisterFunction(ByVal type As Type)
    Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type), false)
End Sub

Private Shared Function GetSubKeyName(ByVal type As Type) As String
    Dim s As String = ("CLSID\{" _
                + (type.GUID.ToString.ToUpper + "}\Programmable"))
    Return s
End Function

通过标记的方法ComRegisterFunctionAttribute自动由称为RegAsm当这个类的组件被登记。 通过标记的方法ComUnregisterFunctionAttribute自动由称为RegAsm当这个类的组件被通过所述未注册/u切换。

问题是, ComRegisterFunctionAttributeComUnregisterFunctionAttribute 通过Visual Studio安装项目安装时完全忽略。

这似乎在第一惊讶,因为在Visual Studio安装项目运行RegAsm使用/regfile以生成一个包含所有必需的注册表键.reg文件开关。 这时候就是被利用,则.MSI包在客户现场运行该.reg文件。

从构建和部署.NET COM大会由菲尔·威尔逊:

如何Visual Studio中工作了COM类注册项? 好吧,如果你已经(在.NET 2.0 SDK Fuslogvw.exe)配置的融合日志查看器来记录集加载,你设置的生成后运行它,你会发现,Regasm.exe的构建过程中实际运行的安装项目。 但是,它不执行任何注册。 什么情况是,Visual Studio中运行Regasm与/regfile选项来创建一个包含以获取步骤1中的信息所需的注册表项.reg文件,而此.reg文件在内部被导入到安装项目。 所以,如果你想看到什么类注册项Visual Studio将在MSI安装程序创建,你可以自己与运行Regasm /regfile选项

在使用运行RegAsm本人/regfile开关,但是,我注意到, Programmable 没有被列入开关。 然后我把我的标记方法中记录ComRegisterFunctionAttributeComUnregisterFunctionAttribute ,发现它们运行时,都被称为RegAsm而不/regfile开关,但与运行/regfile开关,也不是在通过运行他们叫。通过Visual Studio安装项目创建MSI软件包。

该用于Regasm.exe帮助文件证实了这一点(强调):

您可以使用/regfile选项生成包含注册表项,而不是直接更改注册表.reg文件。 您可以通过使用注册表编辑器工具(Regedit.exe)中导入.reg文件更新计算机上的注册表。 请注意,.reg文件不包含可由用户自定义的寄存器的功能进行任何注册表更新。

该解决方案的话,就是添加Programmable键自己。 这是可以做到如下:

  1. 在安装项目,打开注册表编辑器。 创建一个名为新密钥CLSIDHKEY_CLASSES_ROOT在右侧单击HKEY_CLASSES_ROOT文件夹,然后选择“新建”,然后“按键”。
  2. 根据CLSID项中,添加一个名为您的GUID新的密钥,包括大括号。
  3. 在您添加新的GUID键,添加一个名为键Programmable 。 你不需要把这个键内的任何值; 然而,我们确实需要强制将创建它。 因此,在右键单击Programmable键并选择“属性窗口”。 然后更改AlwaysCreate属性为True

一旦你做到了这一点,你不再需要打上ComRegisterFunctionAttribute和ComUnregisterFunctionAttribute的方法,但我还是会离开他们在这些场合,当你通过RegAsm而不是通过安装项目intall。

此时,您已经准备好部署。 构建解决方案,然后用鼠标右键单击您的安装项目,然后选择“生成”。 然后,您可以使用创建的Setup.exe和.MSI文件部署到客户机上。

别的东西要考虑,但是,是增加自动化通过Excel的加载项对话框中加载时,将显示一条错误消息指出“的Mscoree.dll找不到,你想删除加载项? “ 或非常类似的东西。 此错误消息可以忽略,并且您的加载项将运行无论你回答什么,但它可以是惊人的,以客户端安装的加载项。

针对这种情况,以及如何解决这个问题的解释,很好地在文章中描述写作用户自定义函数在.NET为Excel由埃里克·卡特。

问题是,对于默认值InprocServer32关键是简单mscorree.dll ,这足以为.NET找到它,但导致Excel抱怨。 解决的办法是,以确保该InprocServer32项的默认值包括完整路径到系统目录下。 例如,在32位的Windows,它应该阅读C:\Windows\system32\mscoree.dll 。 此路径需要不过,要因人而异,取决于它被安装在系统上。 因此,这条道路不应该是硬编码。

埃里克·卡特通过修改标记的方法处理这个ComRegisterFunctionAttributeComUnregisterFunctionAttribute是以下几点:

// C#: 

[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{

  Registry.ClassesRoot.CreateSubKey(
    GetSubKeyName(type, "Programmable"));
  RegistryKey key = Registry.ClassesRoot.OpenSubKey(
    GetSubKeyName(type, "InprocServer32"), true);
  key.SetValue("",
    System.Environment.SystemDirectory + @"\mscoree.dll",
    RegistryValueKind.String);
}

[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{

  Registry.ClassesRoot.DeleteSubKey(
    GetSubKeyName(type, "Programmable"), false);
}

private static string GetSubKeyName(Type type,
  string subKeyName)
{
  System.Text.StringBuilder s =
    new System.Text.StringBuilder();
  s.Append(@"CLSID\{");
  s.Append(type.GUID.ToString().ToUpper());
  s.Append(@"}\");
  s.Append(subKeyName);
  return s.ToString();
}  

翻译成VB.NET,这相当于:

'VB.NET:

<ComRegisterFunctionAttribute()> _
Public Shared Sub RegisterFunction(ByVal type As Type)
    Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"))
    Dim key As RegistryKey = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true)
    key.SetValue("", (System.Environment.SystemDirectory + "\mscoree.dll"), RegistryValueKind.String)
End Sub

<ComUnregisterFunctionAttribute()> _
Public Shared Sub UnregisterFunction(ByVal type As Type)
    Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false)
End Sub

Private Shared Function GetSubKeyName(ByVal type As Type, ByVal subKeyName As String) As String
    Dim s As System.Text.StringBuilder = New System.Text.StringBuilder
    s.Append ("CLSID\{")
    s.Append(type.GUID.ToString.ToUpper)
    s.Append ("}\")
    s.Append (subKeyName)
    Return s.ToString
End Function

这工作,但其中运行时组件正确注册完全相同的问题RegAsm在本地机器上,而是试图在Visual Studio安装项目中使用时失败。

该解决方案,再次,是增加我们自己的注册表项。 然而这一次,我们必须创建一个默认值,使得使用的[SystemFolder]属性,这相当于System.Environment.SystemDirectory埃里克·卡特的代码中使用,上面的调用。

要做到这一点,添加一个名为关键InprocServer32你的下CLSID\\{GUID}我们先前创建的密钥。 在新的然后右键单击InprocServer32键并选择“新建”,然后“字符串值”。 其结果将是一个名为新值New Value #1 ,但你会在编辑模式让您重新命名。 什么你想在这里做的是删除所有的字符,然后按下回车键 。 通过从名称中删除所有的字符,你正在创建一个默认值和注册表值将会自动重命名图标“(默认)”。 在此默认值图标,然后单击鼠标右键,选择“属性窗口”。 内的属性窗口中,设置Value属性"[SystemFolder]mscoree.dll" (没有引号)。

您安装项目然后,您可以单击鼠标右键,选择“生成”,然后您准备部署。

还有最后一件事发愁。 如果要安装到Excel 2007或以上,上述将工作100%。 如果您在Excel 2003或以下安装,但是,您将需要包括以下内容:

FIX:加载项创建的是,智能文档或智能标记通过使用Microsoft Visual Studio 2005中不运行Office

如何部署它的详细的解释由迪沃给出这里 。

如果不应用此修复程序,一切都将正确地注册,你甚至可以添加您的自动化加载成功 - 似乎一切都很好 - 但你的工作表函数将失败,你仍然会得到#NAME? 错误的结果。 (但是,同样,你不需要这个对于Excel 2007及以上版本)。

因此,在年底,TLB无所谓。 在我所有的测试中,我使用RegAsm不用其他的/ TLB开关,并通过安装项目注册时没有包括任何TLB。 所以,我没有任何麻烦,从Vista,这样做尝试一个TLB文件添加到安装项目时有问题 。

我希望这有助于休,并希望其他人谁可能绊倒这个线程在未来...

麦克风



文章来源: How to get COM Server for Excel written in VB.NET installed and registered in Automation Servers list?