如何获得COM服务器为Excel写在VB.NET安装和自动化服务器列表注册?服务器、写在、如何获得、列表

2023-09-02 10:22:31 作者:少年你这是喜脉

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

Excel 2007, Windows Vista, VB.NET, Visual Studio 2008 with .NET 3.5 sp2, MSI setup package.

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

I have an Excel UDF that is written in VB.NET. It is exposed as a COM Server because you cannot create Excel UDFs in .NET languages directly. Installation is a real pain because none of the installation settings seem to get it quite right; none of them gives you an installation package that puts the COM Server on the client machine with the server registered, the type library registered, and the component visible in the Excel 2007's list of Automation Servers.

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

Here are the installation settings for type libraries, with their defects apparent at compile-time and install-time:

vsdrfComSelfReg

vsdrfComSelfReg

安装项目的编制在没有警告 模块xxx.tlb未能注册。 HRESULT -2147024703 在组件的ProgID和GUID在注册表中设置,但该组件没有出现在自动化服务器的列表

vsdrfDoNotregister

vsdrfDoNotregister

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

vsdrfCOM

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

正确的设置的应的是vsdrfCOM,作为解释here:

The correct setting should be vsdrfCOM, as explained here:

Q值。谁能告诉哪些呢   vsdrfCOM意味着在安装项目   Visual Studio的?它可当我   检查属性注册中   添加的文件在安装属性   项目。

Q. Can anyone please tell what does vsdrfCOM mean in a setup project of Visual Studio? It is available when I check the property "Register" among properties of added files in a Setup project.

一个。这意味着,Visual Studio将   提取在构建COM注册数据   时间,把它放在MSI文件   (主要是MSI文件的注册表中,   而且类表)。所以,当你   安装你的code不需要   自我注册,因为该文件获取   复制到磁盘和注册表   项目获得创建。它也将   通过创建类型库注册   将条目添加到微星的类型库   表中。

A. It means that Visual Studio will extract COM registration data at build time and put it in the MSI file (mostly the MSI file's registry table, but also the class table). So when you install it your code doesn't need to self-register because the file gets copied to disk and the registry entries get created. It will also create type library registration by adding an entry to the MSI's TypeLib table.

许多困难似乎是Vista的特定。具体地,使用REGCAP实用从.tlb文件生成一个.reg文件不能在Vista中正常工作。如果不是如此,或许这个建议将是有益的。相反,它会产生空reg文件,当它在所有工作。

Many of the difficulties appear to be Vista-specific. In particular, using the REGCAP utility to produce a .REG file from a .TLB file does not work in Vista. If not for that, perhaps this advice would be useful. Instead, it produces empty .REG files when it works at all.

我试着在this StackOverflow的帖子。这帖子有技术问题,一个pretty的很好的说明:

I've tried all of the advice in this StackOverflow post. That post has a pretty good description of the technical problem:

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

The entries in the References dialog box come from the HKCRTypeLib registry key, not from HKCRCLSID. If your assembly does not show up in the References dialog but compiled DLL's can still use your COM assembly, it means the classes and interfaces were correctly registered for your assembly, but that the type library itself was not.

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

The question

要一段VB.NET发邮件的代码

Anyone have an idea of how to make the installation register the component and the type library? I don't have access to a Windows XP machine.

精为什么这吮吸

该.TLB是没有必要的任何编译code调用它。我还没有尝试部署一个Excel自动化加载项,因为你正在做的,但我的猜测是,UDF的应该加载和运行得很好。

The .TLB is not necessary for any compiled code to call it. I've not tried deploying an Excel Automation add-in, as you are doing, but my guess is that the UDFs should load and run just fine.

这不是很一样,在Excel中。

It's not quite like that in Excel.

在用户打开一个工作表,并试图引用UDF。它被发现,但因为未装载的DLL。 FAIL 在用户进入首页| Excel选项|加载项| Excel的加载项+去和COM服务器未在加载项对话框中列出。 FAIL 然后用户presses自动化服务器,以获取可用的自动化服务器的列表。该DLL是不存在的。 FAIL 在用户返回到加载项对话框,选择浏览,浏览到安装目录,并选择无论是DLL(XXX是不是有效的加载项)或类型库(您选择的文件呢不包含一个新的自动化服务器,或者您没有足够的权限......)。 FAIL The user opens a worksheet and tries to reference the UDF. It isn't found because the DLL is not loaded. FAIL The user goes to Home|Excel Options|Add-Ins|Excel Add-Ins+Go and the COM Server is not listed in the Add-Ins dialog. FAIL The user then presses Automation Servers to get a list of available automation servers. The DLL is not there. FAIL The user returns to the Add-Ins dialog and selects Browse, navigates to the installation directory, and selects either the DLL ("XXX is not a valid add-in") or the type library ("The file you selected does not contain a new Automation Server, or you do not have sufficient rights..."). FAIL

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

As far as I can tell, the user has to run regasm.exe from the command line to make the Excel UDF/COM server available. How would you feel about telling people to run regasm from the command line to install an add-in to Excel?

修改2009-10-04

迈克的意见和指导下面是真棒。最关键的事情,我不知道是该安装程序具有的内置注册表添加注册表项的编辑器。哦,那的与属性ComRegisterFunctionAttribute安装功能没有被调用的微软安装程序的。我已经有方向大约从他引用来源安装程序写入功能。

Mike's comments and directions below are awesome. The key thing I did not know was that the setup program has a built-in registry editor for adding registry keys. Oh, and that the installation function with attribute ComRegisterFunctionAttribute was not being called by the Microsoft installer. I already had the directions about writing installer functions from the sources he cited.

推荐答案

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

I took a shot at deploying an automation add-in over the weekend. It turns out that it is enormously complicated (not a surprise to you!) and I could find absolutely no sources on the internet on how to do this properly. None.

有描述了如何使用 RegAsm 来源,但没有如何正确使用安装项目注册一个自动加载,这是一个有点不同的你标准的COM加载项。

There are sources that describe how to use RegAsm, but none how to correctly use a Setup Project to register an automation add-in, which is a little different from your standard COM add-in.

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

Fortunately, I was able to solve it. Here's what I found out:

如果你读了一些关于如何创建并注册您的C#自动加载,你会发现你需要添加一个名为注册表项的文章可编程 HKEY _CLASSES _ROOT CLSID \ {GUID} ,其中 {GUID} 是COM的GUID -visible类。

If you read some of the articles on how to create and register your C# automation add-in, you'll see that you need to add a registry key named Programmable at HKEY_CLASSES_ROOTCLSID\{GUID}, where {GUID} is the GUID of your COM-visible class.

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

This is generally done by adding a pair of methods marked by the ComRegisterFunctionAttribute and the ComUnregisterFunctionAttribute. A good example of this comes from the article Writing Custom Excel Worksheet Functions in C# by Gabhan Berry:

// 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,这个作品出来:

Translated to VB.NET, this works out to:

'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 开关。

The method marked by the ComRegisterFunctionAttribute is automatically called by RegAsm when the assembly for this class is registered. The method marked by the ComUnregisterFunctionAttribute is automatically called by RegAsm when the assembly for this class is being unregistered via the /u switch.

的问题是, ComRegisterFunctionAttribute ComUnregisterFunctionAttribute 是完全忽略了通过Visual Studio安装安装时项目的

这似乎令人惊讶的在第一,因为在Visual Studio安装项目运行 RegAsm 使用 / REGFILE 开关,以提供要生成一个包含所有必需的注册表项的.reg文件。这是再利用则.MSI软件包运行在客户端站点此.reg文件。

This seems surprising at first, because the Visual Studio Setup Project runs RegAsm using the /regfile switch in order to generate a .REG file containing all of the required registry keys. It is this .REG file that is then utilized then the .MSI package is run at the client site.

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

如何Visual Studio中摸出   COM类注册项?井,   如果你已经配置了融合日志   浏览器(Fuslogvw.exe在.NET 2.0   SDK)来记录程序集加载,运行   它的安装程序的构建之后   你会真正注意到Regasm.exe   您设置的构建过程中运行   项目。然而,它不执行   任何注册。什么情况是,   Visual Studio中运行Regasm与    / REGFILE 选项来创建一个.reg文件   包含注册表项   来获取信息所需   第1步,这.reg文件是   内部导入设置   项目。所以,如果你想看到什么   类注册项视觉   Studio将创建的MSI安装程序,   您可以使用运行Regasm自己    / REGFILE 选项

How does Visual Studio work out the COM class registration entries? Well, if you have configured the Fusion Log Viewer (Fuslogvw.exe in the .NET 2.0 SDK) to record assembly loading, run it after the build of your setup and you'll notice that Regasm.exe actually runs during the build of your setup project. However, it doesn't perform any registration. What happens is that Visual Studio runs Regasm with the /regfile option to create a .reg file containing the registry entries required to get the information for step 1, and this .reg file is internally imported into the setup project. So if you want to see what class registration entries Visual Studio will create in the MSI setup, you can run Regasm yourself with the /regfile option

当使用 / REGFILE 开关运行RegAsm自己,但是,我注意到可编程开关为不是的被包括在内。然后我把在我的方法打上了 ComRegisterFunctionAttribute ComUnregisterFunctionAttribute 日志记录,并发现它们运行时,都被称为 RegAsm 而不 / REGFILE 开关,但是的没有的与 / REGFILE 开关,也不是所谓的通过由Visual Studio安装项目中创建的.msi包运行时。

Upon running RegAsm myself using the /regfile switch, however, I noticed that the Programmable switch was not being included. I then put logging within my methods marked by the ComRegisterFunctionAttribute and ComUnregisterFunctionAttribute and found that they are both called when running RegAsm without the /regfile switch, but are not called when run with the /regfile switch, nor are they called when run via the .MSI package created by the Visual Studio Setup Project.

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

The help files for Regasm.exe confirm this (emphasis added):

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

You can use the /regfile option to generate a .reg file that contains the registry entries instead of making the changes directly to the registry. You can update the registry on a computer by importing the .reg file with the Registry Editor tool (Regedit.exe). Note that the .reg file does not contain any registry updates that can be made by user-defined register functions.

该解决方案,那么,是添加可编程键自己。这可以如下进行:

The solution, then, is to add the Programmable key ourselves. This can be done as follows:

在安装项目,打开注册表编辑器。创建一个名为新密钥 CLSID HKEY_CLASSES_ROOT 在右侧单击 HKEY_CLASSES_ROOT 文件夹,然后选择新建,然后关键。 在该 CLSID 键,添加一个名为您的GUID新的密钥,包括大括号。 在您添加了新的GUID键,添加一个名为键可编程。你不需要把任何价值这一关键之内;但是,我们确实需要强制它被创建。因此,在可编程键单击鼠标右键,选择属性窗口。那么 AlwaysCreate 属性更改为。 Within the Setup Project, open up the Registry Editor. Create a new Key named CLSID under HKEY_CLASSES_ROOT by right-clicking on the HKEY_CLASSES_ROOT folder, then choosing 'New', and then 'Key'. Under the CLSID key, add a new key named for your GUID, including the curly braces. Under the new GUID key you added, add a key named Programmable. You don't need to put any value within this key; however, we do need to force it to be created. Therefore, right-click on the Programmable key and choose 'Properties Window'. Then change the AlwaysCreate property to True.

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

Once you've done this, you no longer need the methods marked with ComRegisterFunctionAttribute and ComUnregisterFunctionAttribute, but I would still leave them in for those occasions when you intall via RegAsm and not via the Setup Project.

在这一点上,你准备好部署。构建您的解决方案,然后用鼠标右键单击安装项目,然后选择生成。然后,您可以使用创建的Setup.exe并.MSI文件部署到客户端计算机。

At this point you are ready to deploy. Build your solution and then right click on your Setup Project and choose 'Build'. You can then use the created Setup.exe and .MSI files to deploy to a client machine.

另外需要考虑的,但问题在于,当添加的自动化通过Excel的加载项对话框,加载项,将显示一条错误消息中指出的Mscoree.dll找不到,你想删除的插件-在?或非常类似的东西。此错误消息可以忽略不计,而你的加载项将运行无论你回答什么,但它可以是令人震惊的,以安装外接程序的客户端。

Something else to consider, however, is that when adding the automation add-in via Excel's add-ins dialog box, an error message will be shown stating that "Mscoree.dll cannot be found, would you like to delete the add-in?" or something very similar. This error message can be ignored, and your add-in will run no matter what you answer, but it can be alarming to a client installing your add-in.

这情况,以及如何解决这个问题的解释,是好文章的编写用户定义为Excel中的.NET 通过埃里克·卡特功能。

This situation, and the explanation of how to solve it, is well described in the article Writing user defined functions for Excel in .NET by Eric Carter.

现在的问题是,对于 InprocServer32的键的默认值就是 mscorree.dll ,这足以满足.NET找到它,但导致Excel抱怨。解决的办法是,以确保该InprocServer32项的默认值包括完整路径到系统目录下。例如,在32位的Windows,它应该读 C: WINDOWS SYSTEM32 MSCorEE.dll中。这个路径需要然而以改变,这取决于它是安装在系统上。因此,这条道路不应该是硬codeD。

The problem is that the default value for the InprocServer32 key is simply mscorree.dll, which is sufficient for .NET to find it, but causes Excel to complain. The solution is to make sure that the default value for the InprocServer32 key includes the full path to your system directory. For example, on 32 bit windows, it should read C:Windowssystem32mscoree.dll. This path needs to vary, however, depending on the system it is installed on. So this path should not be hard-coded.

埃里克·卡特通过修改标注的 ComRegisterFunctionAttribute ComUnregisterFunctionAttribute 为以下方法处理这P>

Eric Carter handles this by modifying the methods marked by the ComRegisterFunctionAttribute and ComUnregisterFunctionAttribute to be the following:

// 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,这相当于:

Translated to VB.NET, this is equivalent to:

'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使用安装项目。

This works, but has the same exact problem where the assembly is properly registered when running RegAsm on the local machine, but fails when attempting to use this within a Visual Studio Setup Project.

该解决方案,再次是增加我们自己的注册表项。但是这一次,我们必须创建一个默认值,它使用的 [SystemFolder] 属性,它等同于系统。 Environment.SystemDirectory 调用内埃里克·卡特的code使用,上面。

The solution, again, is to add our own registry keys. This time, however, we'll have to create a default value that makes use of the [SystemFolder] property, which is equivalent to the System.Environment.SystemDirectory call used within Eric Carter's code, above.

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

To do this, add a Key named InprocServer32 under your CLSID\{GUID} key that we created previously. Then right-click on the new InprocServer32 key and choose 'New' then 'String Value'. The result will be a new Value named New Value #1, but you will be in edit mode allowing you to re-name it. What you want to do here is delete all the characters and then hit enter. By deleting all the characters from the name, you are creating a default value and the icon for the registry value will be automatically renamed "(Default)". Then right-click on this Default Value icon and choose 'Properties Window'. Within the properties window, set the Value property to "[SystemFolder]mscoree.dll" (without the quotes).

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

You can then right-click on your Setup Project and choose 'Build' and then you are ready to deploy.

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

There is just one last thing to worry about. If you are installing to Excel 2007 or above, the foregoing will work 100%. If you are installing on Excel 2003 or below, however, you will need to include the following:

FIX:加载项,智能文档或智能标签您创建通过使用Microsoft Visual Studio 2005中做在Office

如何部署它的详细的解释由迪沃here.

A detailed explaination of how to deploy it is given by Divo here.

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

If you do not apply this fix, everything will register correctly, and you can even add your automation add-in successfully -- everything seems fine -- but your worksheet functions will fail and you'll still get #NAME? errors as a result. (But, again, you don't need this for Excel 2007 and above.)

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

So, in the end, the TLB does not matter. In all my testing I used RegAsm witout the /TLB switch and did not include any TLB when registering via the Setup Project. So I had no trouble doing this from Vista, which has issues when attempting to add a TLB file to a Setup Project.

我希望这可以帮助,休,并希望其他人谁可能绊倒这个线程的未来......

I hope this helps, Hugh, and hopefully anyone else who might stumble onto this thread in the future...

迈克