Calling regasm without administrative rights for COM interop in Excel VBA - vba

A workaround for calling regasm without the admin rights was described here already:
COM Interop without regasm
I'm trying to create a COM library that my users can deploy and use from Excel VBA without the admin privileges. I liked the regasm workaround, since it seems that people don't have much success with using registration-free COM objects from Excel VBA. I also want early binding so my users can benefit from syntax completion.
The accepted answer in the question mentioned above, however, doesn't describe where to put the assembly dll on the user's computer. Admin rights are required to install the assembly in the GAC, so I'm wondering where one can put the dll file. I presume that the application's dir is being searched for any referenced dlls, but I can't put my dll in the Excel's dir without the admin rights again. Is it possible to use the workaround with the Excel client? Is there any other way to call COM objects from VBA without the need of the admin privileges to deploy them first?

Calling regasm without administrative rights for COM interop
I think it should be possible to use RegistrationServices.RegisterAssembly and RegOverridePredefKey APIs together to implement automatic registration under the HKCU hive, in a UAC-friendly way. I've posted a more detailed answer here.

Yeah, now you have two problems, you cannot put it anywhere you should put it, like the GAC or a c:\program files subdirectory. Since those locations also require UAC elevation. You probably also forgot to run Regasm.exe with the /codebase option, required to tell the CLR where to look for the file.
The user needs to have enough privileges to copy the DLL to a directory he has write access to. That's normally only a directory in c:\users\username, like the appdata subdirectory. The headache you'll have to address that the .reg file needs to be adapted for each individual user since his username is different. So the CodeBase value in the .reg file needs to be changed for each user. This scales poorly, to put it mildly.
The answer you found is just not a very good one. The only solution that really works is to write your own registration function. One that writes the registry keys in HKCU instead of HKLM. Use the [ComRegisterFunction] attribute. You know from the .reg file what keys you need to write. And you use Assembly.GetExecutingAssembly().Location to figure out what to write for CodeBase registry value. Don't forget the [ComUnregisterFunction].
Do keep in mind that, at least in spirit, you are trying to sail around the restrictions that the LAN admin imposed on these users. They do care a lot about knowing what kind of code runs on the machines they support. This may well get you in trouble, at least talk to the guy.

Related

Is replacing existing DLL without re-registering it possible?

I need to update an existing DLL file that is already in use for our client-software that is installed on 400+ computers. This DLL file exists today and is already registered with regsvr32.exe when the software was installed.
The problem is that I cannot easily run the regsvr32.exe command without changing the entire update process, which is a mayor hassle as it is ancient and no documentation exists on it.
So I wondered if I actually have to re-register the dll file, or if replacing the file is enough. I tried searching for more information on this, but so far came up blank.
It depends on how you created the DLL.
If you broke the binary compatibility you must re-register the DLL using regsvr32. If you mantained the binary compatibility copying the new DLL should be enough.
VB6 had an option called "Binary Compatibility" which helped to deal with these issues (http://msdn.microsoft.com/en-us/library/aa733715(v=vs.60).aspx). I don't know if VC++ or VS.NET provide something similar.
Greetings,
edu

How to force creation of manifest file in release folder?

This is driving me crazy. I have developed a .NET COM DLL that is used by a VB6 DLL wrapper in order to update and replace some legacy functions in an application.
I am now trying to remove the requirement to use regasm on client machines so have worked out how to do that on a test DLL which all works fine.
I branched the DLL just in case and added an app.manifest file. Everything else worked out fine and I got it all working. The manifest is embedded and Visual Studio 2012 generates a mydll.dll.manifest file in the release folder.
Then I went back to the original trunk and added an app.manifest file (no point in merging as there were no code changes). I copied the contents of the branch into the app.manifest file and built the release version. The manifest is embedded in the DLL but no mydll.dll.manifest file is generated.
I know that it's not strictly necessary to have the mydll.dll.manifest file but I'd like things to be consistent (and for some reason the test process doesn't produce the same results with the trunk version) so how can I force it to be created?
This is a VB.NET DLL project so it doesn't have (or I can't find) the 'Generate Manifest' property drop down mentioned in the first answer here. How can I set this? Or is there a way to set it by editing the project file directly?
References:
Original walkthrough article and some corrections.
Overview by Junfeng Zhang in two articles plus a useful tool
You are making a fairly common mistake. A reg-free COM manifest helps an application find a COM server without looking in the registry to locate the DLL. Embedding the manifest in the DLL is like trying to solve the chicken and egg problem, Windows cannot possibly find that manifest if it cannot locate the DLL first.
The manifest needs to be part of the client app. Which is tricky since it is VB6, it doesn't support embedding manifests in its executables.
You could tinker with the mt.exe tool, an SDK utility that supports embedding manifests in an executable. You'd have to run it by hand after building the VB6 binaries. That's unfun and very likely to cause trouble when you forget. It is in general not a joyful tool to use, documentation is meager, incomplete and unhelpful, a chronic problem with manifests.
The fall back is a separate app.exe.manifest file, what Windows will look for next when it cannot find a manifest embedded in the executable. Where "app.exe" must be renamed to the name of the VB6 program. The EXE, not the DLL. This now also gives you a chance to avoid having to register the VB6 DLL, presumably what you really want if you truly want to make your program run reg-free. The disadvantage is that it will not work when you debug your VB6 program, wrong EXE. You'd also need a vb6.exe.manifest, located in the VB6 install directory.
Needless to say perhaps, very hard to get ahead with VB6 here. It just wasn't made to help you do this, they didn't have a time machine in 1998.
I have to admit that I don't know VB at all, but in the case of C++ and C# Visual Studio projects I previously had to resort to calling mt.exe in a post-build step in order to get the DLL manifest I wanted. Maybe that workaround would work in your case as well?

Can I package and utilize a dll with an MFC ActiveX Control Object?

I've been able to create a signed CAB file for web deployment containing my control and dll, but my control seems unable to access classes and functions in my dll even though it is listed as a dependency in the CAB's inf file. For all my research, I can't even tell if what I'm trying to do is "allowed". Followup: if it is possible to talk to a non-com dll, is it a security risk?
I'm using msvc 2010. Thanks for your time!
Pretty certain what I was trying to do wasn't possible. Ended up creating a class library instead so that I could reference and include the functions I needed at compile time.

Registration free COM: VB6 Executable referencing VB6 DLL

So, I've got a single VB6 executable that references multiple VB6 COM DLLs. Is it possible for me to generate, on-the-fly, a manifest for the executable as well as a manifest for each of the referenced DLLs? If so, then how?
I would like to perform this operation as part of our build process without having to register the COM DLLs as part of the process.
NOTE: All the reg-free COM examples that I've found so far involve .NET interop, which is not a requirement for what I'm doing.
[EDIT]
After performing some preliminary testing using Unattended Make My Manifest, I've found that its just not as user-friendly as I would like. And, since there's only a Sample.ini file for documentation I've had a pretty hard time understanding what should be put into that file compared to what doesn't need to go into that file. Anyways, I've decided to craft manifests using my own tool. Hopefully, I'll get permission from my employers to release the code as open source.
*For now, if you're in the same position that I'm in and you would like to create a build and production environment that uses side-by-side/registration-free COM interactions, just know that its possible. I would recommend crafting them by hand with a simple DLL and consumer app at first, and then incrementally building on that until it suites your specific needs.**
We are using Unattended Make My Manifest in daily builds to create portable versions. It creates a single manifest that can be embedded to the executable with mt.exe
You could try Make my manifest which is a tool to create the manifest for a VB6 program. I don't know whether it can run automatically as part of a build process.

Register DLL (ActiveX) for Non-Admin user

I try to register dll (ActiveX) for non-admin user using MSI.
To create registry settings I have register the dll in admin mode, then exported the relevant registry entries and renamed all HKLM to HKCU.
When I install it for non-admin user all works fine. But when I use the same settings with admin user, there is a problem of discovering TypeLib.
What should be changed in the registry entries to work both for admin and non-admin user, when the registration done under HKCU?
Thank you
If your entries are really registered under HKCU, it will work. What MSI installer are you using? There should be a way to specify that it should install in user mode.
Are you letting the dll self-register or having the msi register the dll? it is best practice to have the MSI do it, but it's more of a pain. If you're having the .dll self-register you need to make sure that the dll registers in HKEY_CURRENT_USER and not HKEY_LOCAL_MACHINE, which ATL does by default.
If you built it in VS2008 with ATL, you'll want to add:
AtlSetPerUserRegistration(true);
to your DllRegisterServer and DllUnregisterServer.
Anyway, those are some things to look for. You can use Process Monitor and watch the Reg commands to see exactly what is happening; something somewhere is writing to HKLM.