版本
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安装功能并没有被微软称为安装 。 我已经有大约从他列举了源安装程序写入功能的方向。
我参加了一个射击在部署自动化外接周末。 事实证明,这是非常复杂(不是惊喜给你!),我能找到绝对没有对如何做到这一点正确的在互联网上的来源。 没有。
有迹象表明,介绍如何使用来源RegAsm
,但没有如何正确使用安装项目注册一个自动化加载项,这是从标准的COM加载项稍有不同。
幸运的是,我能够解决这个问题。 下面是我发现了什么:
如果你读了一些关于如何创建并注册您的C#自动化插件,你会发现你需要添加一个名为注册表项物品的Programmable
在HKEY\_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
切换。
问题是, ComRegisterFunctionAttribute
和ComUnregisterFunctionAttribute
通过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
没有被列入开关。 然后我把我的标记方法中记录ComRegisterFunctionAttribute
和ComUnregisterFunctionAttribute
,发现它们运行时,都被称为RegAsm
而不/regfile
开关,但与运行不叫/regfile
开关,也不是在通过运行他们叫。通过Visual Studio安装项目创建MSI软件包。
该用于Regasm.exe帮助文件证实了这一点(强调):
您可以使用/regfile
选项生成包含注册表项,而不是直接更改注册表.reg文件。 您可以通过使用注册表编辑器工具(Regedit.exe)中导入.reg文件更新计算机上的注册表。 请注意,.reg文件不包含可由用户自定义的寄存器的功能进行任何注册表更新。
该解决方案的话,就是添加Programmable
键自己。 这是可以做到如下:
- 在安装项目,打开注册表编辑器。 创建一个名为新密钥
CLSID
下HKEY_CLASSES_ROOT
在右侧单击HKEY_CLASSES_ROOT
文件夹,然后选择“新建”,然后“按键”。 - 根据
CLSID
项中,添加一个名为您的GUID新的密钥,包括大括号。 - 在您添加新的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
。 此路径需要不过,要因人而异,取决于它被安装在系统上。 因此,这条道路不应该是硬编码。
埃里克·卡特通过修改标记的方法处理这个ComRegisterFunctionAttribute
和ComUnregisterFunctionAttribute
是以下几点:
// 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?