我在周末尝试部署了一个自动化插件。结果发现它非常复杂(对你来说并不奇怪!)我在网上找不到任何关于如何正确处理的资料。一个也没有。
有些资料描述了如何使用
RegAsm
,但是没有如何正确使用安装项目来注册自动化外接程序,这与您的标准COM外接程序略有不同。
幸运的是,我能够解决它。我发现:
如果您阅读了一些关于如何创建和注册c automation外接程序的文章,您将看到您需要添加一个名为
Programmable
在
HKEY\_CLASSES\_ROOT\CLSID\\{GUID}
在哪里
{GUID}
是COM可见类的guid。
这通常是通过添加一对由
ComRegisterFunctionAttribute
以及
ComUnregisterFunctionAttribute
. 一个很好的例子来自于这篇文章
Writing Custom Excel Worksheet Functions in C#
加班贝里:
// 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
由自动调用
复律
注册此类的程序集时。以
ComUnregisterFunctionAttribute
由自动调用
复律
当通过
/u
开关。
问题是
ComRegisterFunction属性
和
ComUnregisterFunctionary属性
是
通过Visual Studio安装项目安装时完全忽略。
一开始这似乎很奇怪,因为visual studio安装项目运行
复律
使用
/regfile
切换以生成包含所有必需注册表项的.reg文件。然后使用这个.reg文件,然后在客户端站点上运行.msi包。
从
Build and Deploy a .NET COM Assembly
菲尔·威尔逊:
visual studio如何计算
COM类注册条目?好,
如果您已经配置了fusion日志
查看器(在.NET 2.0中为fuslogvw.exe
sdk)记录程序集加载,运行
在你的设置和
你会注意到regasm.exe实际上
在构建安装程序期间运行
项目。但是,它不执行
任何登记。发生了什么事
visual studio使用
/ReFr档
创建.reg文件的选项
包含注册表项
需要获取的信息
步骤1,这个.reg文件是
内部导入到设置中
项目。如果你想看看
类注册项可视化
工作室将在MSI设置中创建,
你可以自己用
/ReFr档
选项
当我自己使用
/ReFr档
不过,我注意到
可编程
开关是
不
包括在内。然后我将日志记录放在我的方法中,标记为
ComRegisterFunction属性
和
ComUnregisterFunctionary属性
发现它们在运行时都被调用
复律
没有
/ReFr档
切换,但是
不
在运行时调用
/ReFr档
切换,也不会在通过Visual Studio安装项目创建的.msi包运行时调用它们。
这个
help files for Regasm.exe
确认(增加重点):
你可以使用
/ReFr档
选择权
生成包含
注册表项而不是
直接更改到注册表。你
可以更新计算机上的注册表
通过使用
注册表编辑器工具(regedit.exe)。
注意,.Reg文件不包含任何可以注册的注册表更新。
由用户自定义寄存器生成
功能。
然后,解决方案是添加
可编程
关键是我们自己。可以这样做:
-
在安装项目中,打开注册表编辑器。创建名为
CLSID
在下面
HKEY_CLASSES_ROOT
右键单击
香港大学根课程
文件夹,然后选择“新建”,然后选择“键”。
-
下
CLSID
key,为guid添加一个新的key,包括花括号。
-
在您添加的新guid密钥下,添加一个名为
可编程
. 您不需要将任何值放入这个键中;但是,我们确实需要强制创建它。因此,右键单击
可编程
键并选择“属性窗口”。然后改变
AlwaysCreate
属性到
True
.
完成此操作后,您不再需要标记为comRegisterFunctionattribute和comUnregisterFunctionattribute的方法,但在您通过regasm而不是通过安装项目进行安装时,我仍会保留这些方法。
现在你已经准备好部署了。构建解决方案,然后右键单击安装项目并选择“构建”。然后,可以使用创建的StupU.EXE和.MSI文件部署到客户端机器。
但是,还需要考虑的是,通过Excel的“加载项”对话框添加自动化加载项时,将显示一条错误消息,指出“找不到mscoree.dll,是否删除该加载项?”或者类似的东西。这个错误消息可以被忽略,并且你的外接程序将运行不管你回答什么,但是它可能会对安装你的外接程序的客户端造成警告。
这篇文章很好地描述了这种情况,并解释了如何解决它
Writing user defined functions for Excel in .NET
作者:埃里克·卡特。
问题是
InprocServer32
关键是
mscorree.dll
,这足以让.NET找到它,但会导致Excel抱怨。解决方案是确保inprocserver32键的默认值包含到系统目录的完整路径。例如,在32位窗口上,它应该读取
C:\Windows\system32\mscoree.dll
. 但是,此路径需要根据安装它的系统而有所不同。所以这个路径不应该硬编码。
Eric Carter通过修改
ComRegisterFunction属性
和
ComUnregisterFunctionary属性
如下:
// 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
这是可行的,但在运行时正确注册程序集的地方也有同样的问题
复律
在本地计算机上,但在尝试在Visual Studio安装项目中使用时失败。
同样,解决方案是添加我们自己的注册表项。但是,这次我们必须创建一个默认值,它使用
[SystemFolder]
属性,相当于
System.Environment.SystemDirectory
上面Eric Carter代码中使用的调用。
为此,请添加名为
进程服务器32
在你的下面
CLSID\\{GUID}
我们之前创建的密钥。然后右键单击新的
进程服务器32
键并选择“新建”,然后选择“字符串值”。结果将是一个名为
New Value #1
,但您将处于编辑模式,允许您重新命名它。你想做的是
删除所有字符,然后按回车键
. 通过删除名称中的所有字符,您将创建一个默认值,注册表值的图标将自动重命名为“(默认)”。然后右键单击此默认值图标并选择“属性窗口”。在“属性”窗口中,将“值”属性设置为
"[SystemFolder]mscoree.dll"
(没有引号)。
然后您可以右键单击安装项目并选择“生成”,然后准备部署。
还有最后一件事要担心。如果您要安装到excel 2007或更高版本,上述操作将100%有效。但是,如果要在Excel 2003或更低版本上安装,则需要包括以下内容:
FIX: Add-ins, smart documents, or smart tags that you create by using Microsoft Visual Studio 2005 do not run in Office
Divo详细解释了如何部署它
here
.
如果不应用此修复,所有的内容都会正确注册,甚至可以成功地添加您的自动化加载项——一切看起来都很好,但是您的工作表函数会失败,您仍然可以获得名称吗?结果是错误。(但是,同样,对于Excel2007及更高版本,您不需要这个。)
所以,最终,tlb并不重要。在我的所有测试中,我使用了regasm,其中包含/tlb开关,并且在通过安装项目注册时不包含任何tlb。所以我在vista做这个没问题,
which has issues when attempting to add a TLB file to a Setup Project
.
我希望这能帮上忙,休,希望将来有人会偶然发现这条线索…
迈克