在没有管理员权限的情况下注册.Net COM DLL/regasm
最近,我用C#编写了一个类库,用于Office应用程序,包括一个供大约70人使用的关键访问应用程序。对于具有管理员权限的用户来说,注册DLL很简单,但是让DLL在其他机器上工作是有问题的 注册DLL以使用管理员权限在没有管理员权限的情况下注册.Net COM DLL/regasm,.net,vba,dll,registry,regasm,.net,Vba,Dll,Registry,Regasm,最近,我用C#编写了一个类库,用于Office应用程序,包括一个供大约70人使用的关键访问应用程序。对于具有管理员权限的用户来说,注册DLL很简单,但是让DLL在其他机器上工作是有问题的 注册DLL以使用管理员权限 在VisualStudio中构建DLL。确保在项目的应用程序选项卡上选择了这些选项: 输出类型:类库 程序集信息:使程序集COM可见:选中 使用提升的命令提示符注册程序集: RegAsm YourDll.dll/tlb/codebase 在VBA:Tools-->引用中添加
- 在VisualStudio中构建DLL。确保在项目的应用程序选项卡上选择了这些选项:
- 输出类型:类库
- 程序集信息:使程序集COM可见:选中
- 使用提升的命令提示符注册程序集:
RegAsm YourDll.dll/tlb/codebase
- 在VBA:Tools-->引用中添加对
的引用YourDll.tlb
- 验证是否可以创建对象的实例
/regfile
参数运行它:
Regasm YourDLL.dll/codebase/regfile
(带有/tlb
参数的/regfile
选项无效。)
如果/codebase
选项告诉Regasm包含有关YourDLL.dll
在磁盘上的位置的信息,这对于创建对象很重要
如果在文本编辑器中打开YourDLL.reg
,您将看到Regasm正在添加到注册表的条目:HKEY_Classes\u Root
(这实际上只是重定向到HKLM\Software\Classes
)。不幸的是,您需要管理员权限才能修改HKLM
,因此这对我们的其他用户不起作用
还有一些其他线程(例如,,)讨论了该问题,但它们的解决方案很复杂(例如,需要注册表重定向)或不完整(假设您已经知道至少一半的答案),或者不能在64/32位混合环境中工作(例如,Win64、Office32)
那么,如何在没有管理权限的情况下为当前用户注册在Visual Studio中创建的COM DLL,以便在VBA 32和64位环境中使用?设置注册表文件
为了在32位和64位环境中注册组件,我们需要修改在测试用例中创建的注册表文件。用你最喜欢的文本编辑器打开它。条目应如下所示:
[HKEY_CLASSES_ROOT\\YourAssembly.Class]
@="YourAssembly.Class"
[HKEY_CLASSES_ROOT\\YourAssembly.Class\\CLSID]
@="{YourClassGUID}"
Public Sub TestYourDLL()
Dim x as AssemblyName.ClassName
Set x = New AssemblyName.ClassName
Debug.Print "Apparently this worked."
End Sub
确保事情不会发生
为了确保我们的更改有效(并且您的成功不仅仅是因为您最初向regasm进行了注册),我们需要确保VBA现在无法创建对象
打开您喜爱的VBA应用程序,并添加对YourDLL.tlb
的引用。创建一个类似以下内容的新过程:
[HKEY_CLASSES_ROOT\\YourAssembly.Class]
@="YourAssembly.Class"
[HKEY_CLASSES_ROOT\\YourAssembly.Class\\CLSID]
@="{YourClassGUID}"
Public Sub TestYourDLL()
Dim x as AssemblyName.ClassName
Set x = New AssemblyName.ClassName
Debug.Print "Apparently this worked."
End Sub
运行TestYourDLL
。您应该会收到以下错误:
Run-time error '429':
ActiveX component can't create object
运行时错误“429”:
ActiveX组件无法创建对象
(如果未收到错误,则DLL仍在注册中。)
保存并退出VBA应用程序
确保他们工作
现在,运行前面创建的YourDLL.reg
,将条目导入注册表。(如果您收到“拒绝访问”消息,则您忘记从HKEY\U CLASSES\U ROOT
更改为HKEY\U CURRENT\U USER\Software\CLASSES
)
再次打开VBA应用程序,然后运行TestYourDLL
。现在,您应该在直接窗口中看到“显然这起作用了”。祝贺你已经注册了DLL!(如果出现“自动错误:系统找不到指定的文件”类型错误,则注册表文件可能缺少Codebase
项,或者它们没有指向DLL的实际位置。)
附加步骤
在我的例子中,我将在我的应用程序旁边的一堆其他用户的计算机上安装DLL,因此在安装时,我将更新
CodeBase
值以引用我安装DLL的位置,并且我还将通过代码而不是通过执行.reg文件来安装注册表项。但是,现在我知道了所需的条目,这样做很简单。C怀特的答案很好,如果你能在每台计算机上手动操作的话
为了自动添加必要的注册表项,我使用以下代码。它在64位Windows上占32位Office,可以在以后进行清理
Public Sub RegisterDLL(DLLPath As String)
Dim RegasmPath As String
RegasmPath = "C:\Windows\Microsoft.NET\Framework\" & Dir("C:\Windows\Microsoft.NET\Framework\v4*", vbDirectory) & "\RegAsm.exe" 'Path to RegAsm, adjust to the version of the .Net framework you're targeting
#If Win64 Then
Const Win64 = True
#Else
Const Win64 = False
#End If
Dim LibraryPath As String
LibraryPath = Left(DLLPath, Len(DLLPath) - 4)
If Dir(DLLPath) = "" Then 'Check if file exists
Err.Raise 1, Description:="Missing DLL!"
Exit Sub
End If
CreateObject("WScript.Shell").Run """" & RegasmPath & """ """ & DLLPath & """ /codebase /regfile", 0, True 'Create .reg file using RegAsm
Dim strNewRegPath As String
If Not Win64 And Environ$("ProgramW6432") <> vbNullString Then
strNewRegPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\Wow6432Node" '32 bits Office on Win 64
Else
strNewRegPath = "HKEY_CURRENT_USER\SOFTWARE\Classes" 'Default registry path
End If
Dim strRegFileContent As String
Dim fileNo As Integer
fileNo = FreeFile
Open LibraryPath & ".reg" For Binary Access Read Write As #fileNo
strRegFileContent = String(LOF(fileNo), vbNullChar)
Get #fileNo, , strRegFileContent 'Read reg contents
strRegFileContent = Replace(strRegFileContent, "HKEY_CLASSES_ROOT", strNewRegPath) 'Change reg path
Put #fileNo, 1, strRegFileContent 'Overwrite, always extends so no need to truncate
Close #fileNo
CreateObject("WScript.Shell").Run "regedit.exe /s """ & LibraryPath & ".reg""", 0, True 'Merge silently into registry
Kill LibraryPath & ".reg" 'Clean up registry
End Sub
这些脚本不需要引用,也不需要管理员访问。它们通常应该运行得很快,并允许在应用程序启动时进行设置,以及在应用程序关闭时进行清理(如果可能存在冲突)。我不久前尝试过类似的过程,但它对我不起作用,因为生成的reg文件。这可能不会影响您,但您应该意识到这一限制…@PetrSr:我的经验是,
regasm/regfile
中完全缺失的条目只有CodeBase
条目,但regasm/CodeBase/regfile
修复了这一问题。(当然,32位注册也丢失了,这就是为什么我必须自己创建这些条目,使用基本信息作为基础。)你能找出哪些条目丢失了吗?TypeLib和接口ID丢失了,没有它们我无法让我的DLL工作。如中所述,使用/regfile
选项将始终缺少这些条目。我试图直接从注册表中获取丢失的etnries,但结果证明这是一项相当繁琐的任务。我最终放弃了,并要求我的老板使用他的管理员帐户为我注册DLL…:-