0

I'm using Delphi and Add-in Express VCL to develop an Excel COM Add-in. To enable theming in my forms, I'm using a manifest and activation contexts, as it's written in David Heffernan's answer here:

Apply Windows Theme to Office Com add-in

Based on the linked post, here is my code:

var
  ActivationContext: TActivationContext;
begin
  try
    ActivationContext := TActivationContext.Create;
    try
      ShowMessage('Exception comes after this');
    finally
      ActivationContext.Free;
    end;
  except
    on E:Exception do
      ShowMessage(Format(SErrorString, [E.ClassName, E.Message]));
  end;
end;

The message dialog is properly displayed (themed!) but when ActivationContext.Free is called (which calls DeactivateActCtx(0, FCookie);) I'm getting the following exception:

EExternalException: External exception C000000D

Please note that I've inserted ShowMessage in the above code for demonstration purposes, normally I'm creating and showing a form with the same results (error).

How can I get around this?


Update: Here is the manifest in question:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="*"
    name="AddinName"
    type="win32"
/>
<description>Addin description</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>

My Res file:

2 24 "XP.manifest"

The code to include the res file:

{$R XPManifest\xp_manifest.RES}

Is it important for AddinName to match the name of the Delphi project?

One more note: the add-in is compiled for 64-bit Excel.

Steve
  • 2,510
  • 4
  • 34
  • 53
  • How can we reproduce this? I'm sure I don't see this behaviour in my addin. – David Heffernan Feb 27 '20 at 04:33
  • Maybe you're using a different version of Add-in Express / Delphi XE / Office? I'll try it on a different computer with a different Office version. If I get the same error, I'll create and upload some sample code for you. – Steve Feb 27 '20 at 09:27
  • Far more likely it's something else in your code, to be honest – David Heffernan Feb 27 '20 at 09:35
  • I've made an empty add-in with just the code above and the error is the same. Could it be a wrong manifest? I'm attaching it to my original post. – Steve Feb 27 '20 at 09:57
  • If I were to try to debug this, I'd need to recreate an empty addin, and that's more work than I have time for. I do wonder however what would happen if you replace `ShowMessage` with a call to `MessageBox`, the Windows API function. – David Heffernan Feb 27 '20 at 10:18
  • MessageBox(FindWindow('XLMAIN', nil), PChar('test'), PChar('test'), mb_OK); - produces the same error. Do you have Add-in Express installed? If I upload my test add-in code somewhere can you try to compile it if it produces the same error? – Steve Feb 27 '20 at 10:26
  • Add-ins are a pain though, because of the registry settings. It's still going to take me time which I don't really have. If you could replicate it in a standalone DLL rather than an add in that would be useful. – David Heffernan Feb 27 '20 at 10:40
  • I'll try to reproduce it in a standalone DLL. Some more info: After the exception is generated by DeactivateActCtx, GetLastError returns 0. RaiseLastOSError returns "ExcelTest error: the add-in has fired an exception. A call to an OS function failed". Could you take a look at the original post I've linked to make sure that I'm using your most up-to-date code? – Steve Feb 27 '20 at 18:39
  • I actually use a different approach now to load the activation context, but the code in that question you linked to is known to be correct. – David Heffernan Feb 27 '20 at 19:20
  • Is there a post about the other approach you use? Maybe it's worth trying that. – Steve Feb 28 '20 at 09:41
  • No, it's just a cleaner way to do it, but it doesn't change anything material. You can use `GetCurrentActCtx` in `DllMain` to get the activation context, rather than creating it yourself. That's because the loader creates the context and activates it before calling `DllMain`. Won't change anything for you. – David Heffernan Feb 28 '20 at 09:53
  • There is one thing I don't understand: your code fails for Excel/Word/Outlook. But for Word and Outlook I've been successfully using the activation context code from this unit: https://github.com/miracle2k/ntfslink/blob/master/source/ntfslinkext/ActivationContext.pas Now if I use this unit with Excel, I get an EComponentError with "This control requires version 4.70 or greater of COMCTL32.DLL". Does this make sense to you? – Steve Feb 28 '20 at 19:07
  • My code works fine for me in Excel. – David Heffernan Feb 28 '20 at 19:34

0 Answers0