Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
778 views
in Technique[技术] by (71.8m points)

vba - Registering .Net COM DLLs without Admin rights / regasm

Recently, I wrote a class library in C# for use in Office applications, including a critical Access application used by ~70 people. For users with admin rights, registering the DLL is trivial, but getting the DLL working on other machines was problematic.

Registering the DLL for use with admin privileges

  • Build the DLL in Visual Studio. Ensure these options are selected on the project's Application tab:
    • Output Type: Class Library
    • Assembly Information: Make assembly COM-visible: Checked
  • Use an elevated command prompt to register the assembly:
    • RegAsm YourDll.dll /tlb /codebase
  • Add a reference to YourDll.tlb in VBA: Tools-->References
  • Verify that you can create an instance of your object

What is happening?

Regasm is doing several things here. First, it is creating a type library (YourDLL.tlb) which provides information about the classes that are in your DLL. Second, it is storing the information about the library in the registry so that the system "knows" what you mean when you ask for a class to be instantiated as an object.

To see what registry entries Regasm is adding, you can run it with the /regfile parameter:

Regasm YourDLL.dll /codebase /regfile

(The /regfile option is invalid with the /tlb parameter.)

If the /codebase option tells Regasm to include information about where YourDLL.dll is located on disk, which is important for creating the objects.

If you open YourDLL.reg in a text editor, you'll see the entries that Regasm is adding to the registry: entries to HKEY_Classes_Root (which is really just a redirect to HKLMSoftwareClasses). Unfortunately, you need admin privileges to modify HKLM, so this isn't going to work for our other users.

There are a few other threads (e.g. Registering a COM without Admin rights, Register COM DLL for use by VBA, Register DLL (ActiveX) for non-admin user, Unable to register .NET COM DLL, COM Interop without regasm) that discuss the problem, but their solutions are complex (e.g. require registry redirection) or incomplete (assume you already know at least half of the answer) or do not work in mixed 64/32 bit environments (e.g. Win64, Office32).

So how do you register a COM DLL, created in Visual Studio, for use in VBA 32 and 64 bit environments for the current user, without administrative privileges?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Setting up the registry files

To register the components for use in 32 and 64 bit environments, we are going to need to modify the registry file we created in our test case. Open it with your favorite text editor. The entries should look something like this:

[HKEY_CLASSES_ROOT\YourAssembly.Class]
@="YourAssembly.Class"

[HKEY_CLASSES_ROOT\YourAssembly.Class\CLSID]
@="{YourClassGUID}"

Make sure that it includes "CodeBase"= entries.

Do a global find/replace:

  • Change HKEY_CLASSES_ROOT (which is aliasing to HKLMSoftwareClasses)
  • To HKEY_CURRENT_USERSoftwareClasses

Copy all of the registry keys (and their values, which are listed below the keys) to a second text file. In the second text file:

  • Delete all of the keys (and their related values) that do not contain CLSID
  • Do a global find/replace:
    • Change ClassesCLSID
    • To: ClassesWow6432NodeCLSID

Copy all of the keys from the second text file to your original .reg file, and save it.

Remove the registration entries from HKLM by using regasm:

Regasm YourDLL.dll /unregister

Make sure things don't work

In order to make sure that our change worked (and that you're not just successful because of the registration you did with regasm originally), we need to make sure that VBA cannot create the object right now.

Open up your favorite VBA application, and add a reference to YourDLL.tlb. Create a new procedure that is something like this:

Public Sub TestYourDLL()
  Dim x as AssemblyName.ClassName
  Set x = New AssemblyName.ClassName
  Debug.Print "Apparently this worked."
End Sub

Run TestYourDLL. You should receive the error:

Run-time error '429':

ActiveX component can't create object

(If you don't receive the error, your DLL is still registered.)

Save and exit your VBA application.

Making sure they work

Now, run the YourDLL.reg that you created earlier to import the entries to the registry. (If you get an "Access denied" message, you forgot to change from HKEY_CLASSES_ROOT to HKEY_CURRENT_USERSoftwareClasses)

Open your VBA application again, and run TestYourDLL. You should now see "Apparently this worked." in your immediate window. Congratulations! You've registered the DLL! (If you get an "Automation error: The system cannot find the file specified"-type error, your registry file is either missing the Codebase entries, or they are not pointing to the actual location of your DLL.)

Additional steps

In my case, I'm going to be installing the DLL on a bunch of other users' computers alongside my application, so at installation time I'll update the CodeBase value to refer to the location where I'm installing the DLL, and I'll also install the registry entries through code, rather than by executing the .reg file. But, now that I know the required entries, doing that is trivial.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...