views:

17

answers:

1

I use VS2008 to develop a excel 2007 add-in, within add-in I want to use Activation Context API to instantiate a COM class.

The werid thing is I can instantiate the COM class successfully on Window 7, buf fails on Windows XP/2003.

Here's the code-snippet

  string codeBase = this.GetType().Assembly.CodeBase;
  string asmFullPath = new Uri(codeBase).LocalPath;
  string comAssemblyPath = Path.GetDirectoryName(asmFullPath);

  ACTCTX ac = new ACTCTX();
  ac.cbSize = Marshal.SizeOf(typeof(ACTCTX));
  ac.lpAssemblyDirectory = comAssemblyPath;
  ac.lpSource = Path.Combine(comAssemblyPath, "ComViewer.x.manifest");
  ac.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

  IntPtr cookie;
  IntPtr hActCtx = CreateActCtxW(ref ac);
  if (ActivateActCtx(hActCtx, out cookie))
  {
    try
    {
      //instantiate COM class
      IComViewer = new ComViewerClass();

    }
    finally
    {
      DeactivateActCtx(0, cookie);
    }
  }
  else
  {
    //TODO: Error message.
  }

The COM is written in C++ and the manifest looks like:

On Windows 2003/XP, I found that add-in looked for ComViewer.dll in c:\program files\microsoft Office\Office 12 rather than the directory I specified in lpAssemblyDirectory.

Anyone can help? thanks in advance.

A: 

Just figure out that, in XP/2003, Activation Context API doesn't respect lpAssemblyDirectory if you put COM file info within root manifest that lpSource points to, in this case Windows will only search COM file in the directory that executable resides in. The workaround is to create another mainfest that depends on original manifest ComViewer.x.manifest and pass it into lpSource. In above example you may pass in the following manifest:

Of course you should add element to ComViewer.x.manifest as well.

Erich