Search code examples
excelvb.netregistrynsisregasm

Launching Excel Spreadsheet Containing COM Object Instantiation in VBA - From NSIS "Finish" Page - Gives Class not registered Error For Admin User


I am experiencing a strange occurrence when installing for a Standard user versus Admin.

My installer requests "Highest" authentication level then proceeds to register COM dlls using a registry file import to HKCU (instead of using regasm.exe directly). The COM is for use in VBA in Excel. This allows me to install on a per-user basis.

After installation I have the "Run app" checkbox checked on the Finish page. The process is:

  1. The user clicks "Finish" and NSIS launches a VB.net exe I wrote
  2. The VB.net exe writes some additional registry entries to HKCU (that don't have anything to do with COM) then launches Microsoft Excel
  3. Excel opens and attempts to instantiate the COM object in VBA.

Here is the strange difference:

  1. For the "Standard" user this all works perfectly.

  2. For the "Admin" user I get:

Run-time error '-2147221164 (80040154':

Class not registered

Curiously, if I then close Excel and double-click the desktop shortcut Excel opens and instantiates the object for the Admin user with no problem.

So, effectively, this error only occurs for the Admin user during the initial installation process (e.g. when it is NSIS that launches the VB.net exe which then launches Excel).

This problem occurs both on Windows 10 64-bit with Office 365 64-bit as well as Window 10 32-bit with Office 365 32-bit. So, the bitness of the applications has nothing to do with it.

It's almost like the registry isn't "refreshing" for the Admin user during the initial installation.

Any ideas as to what is going on and what the code is to fix it?

Matthew


Solution

  • I'm guessing you are running into a UAC security feature. When running elevated, COM will not read the entries in HKCU (because a non-elevated application could write there and wait for an elevated application to use a hijacked COM class registration).

    That being said, what you are doing does not make sense. If you are using RequestExecutionLevel Highest then you should be writing to the ShCtx registry root after setting SetShellVarContext to Current or All depending on whether you are elevated or not in .onInit.

    If you want to ignore my advise and continue using your existing design then define MUI_FINISHPAGE_RUN_FUNCTION and use ShellExecAsUser, StdUtils.ExecShellAsUser or the ugly Explorer hack (Exec '"$WinDir\Explorer.exe" "$InstDir\MyApp.exe"').