Click here to Skip to main content
15,879,326 members
Articles / Desktop Programming / Win32

Troubleshooting Registration Free COM

Rate me:
Please Sign up or sign in to vote.
4.97/5 (11 votes)
30 Apr 2018CPOL9 min read 17.6K   614   17   4
How to troubleshoot Registration Free COM using Tools

Introduction

There are plenty of articles on how to implement Registration Free COM. Most of those articles are well written and very useful if everything work as advertised. But what if something goes wrong? How one can see underneath and try to understand want went wrong?

In this article I would like to introduce couple of tools that can be used for troubleshooting any problems one may encounter during the implementation and testing of modules which make use of Registration Free COM.  Tools are explained with the help of a sample registration free COM application attached to this article. 

Tools introduced here are in fact part of either Windows OS or Windows SDK. I would also like to mention briefly about the importance of Activation Context which is a must-to-know for anyone working with Registration Free COM and Manifest files.

The article assumes that the reader knows something but not everything about COM and Registration Free COM.

Background

After things were put well in place, I got a nicely working registration free COM server and a client. The COM server is a C# Dll which makes use of .NET 4.6 and the client is a C++ application. I started working on other parts of the stuff and later found that in certain situations there comes "Class not registered" message from the C++ client application. The message came obviously when the C++ client application tried to create an instance of a COM component contained in the C# dll.

This was the point at which I started getting across couple of highly useful tools. It can be used to hunt down problems that can arise during testing of registration free COM modules and its interaction with client applications.

Using the Application

I would like to start with a registration free COM application. It contains a C# library which is exposed as an in-proc COM server and a C++ console application that invokes the C# COM library via registration free COM. You can download and refer the sample application source or the demo binaries while going through this article.

Please note for the C# COM library, Visual Studio option "Register for COM interop" is NOT selected. This ensures that the no information pertaining to COM interface will be kept in Windows registry. 

If you are not much familiar with Registration Free COM, then the sample application will demonstrate it in a very simple way. 

The combination of C# COM library and a C++ client is chosen to emphasis the beauty of COM which facilitates a smooth interaction between modules written in different programming languages.

Before explaining how to troubleshoot registration free COM, I would like to mention couple of important things which are good to know during the implementation of COM library.

Use of Guid Attribute

When implementing an interface, one can use tool such as "guidgen.exe" to generate a GUID and specify the generated GUID along with the Guid attribute shown above. This will prevent potential automatic GUID generation each time the project is compiled and will maintain the fact that there is no interface change during successive compilation. An excerpt from the sample application is shown below.

using System.Runtime.InteropServices;

[Guid("7E7DB6F5-7A52-47F9-8C12-093BDA5B3811")]
public class RegFree : IRegFree
{
}

Type Library & Manifest File Generation

This is regarding how type library (.tlb) file and manifest (.manifest) file can be generated using Post Build script.

"$(TargetFrameworkSDKToolsDirectory)tlbexp.exe" $(TargetPath) /out:"$(TargetDir)$(TargetName).tlb" 
"$(MTToolPath)" -managedassemblyname:$(TargetPath) -out:$(TargetName).manifest -nodependency

Please note that MTToolPath is a custom value added to the RegFreeCOMDll.csproj file by first unloading the project (right click RegFreeCOMDll in the Solution Explorer and choose “Unload Project) and again right click the RegFreeCOMDll in the Solution Explorer and choose “Edit RegFreeCOMDll.csproj”.

All Is Good

All is good when everything is in place. But it will start to screw up things when a little goes wrong. Here comes the importance of understanding troubleshooting.

Each of the following troubleshooting section contains sample steps that can be tried at your end, using the demo binaries available with this article. Each section also contains useful references.

Troubleshoot #1

“Class not registered”

There will come a COM exception with the error message shown above when client application’s manifest file which is RegFreeCOMDllClient.exe.manifest in this case, is not present in the application path. This message means the system is not able to locate the COM component which a client application is trying to create.

As demonstrated inside the sample application, following is a typical way of creating a COM object.

try
{
    IRegFreePtr pRegFree(__uuidof(RegFree));

    ...

}
catch (_com_error _com_err)
{
    wprintf(L"\n %s", _com_err.ErrorMessage());
    getch();
}

When the OS is not able to find reference to the COM component being created, it will throw an exception.

Let’s try an example with the contents of Demo folder.

  1. Rename “RegFreeCOMDllClient.exe.manifest”
  2. Run RegFreeCOMDllClient.exe.

The "Class not registered" message will be displayed in the console window.

The point here is that for registration-free COM otherwise called Side-by-Side Assemblies to work correctly, the manifest file should be present alongside the client application. This sample seems to be trivial, but in a real environment having number COM Registration free modules, presence of appropriate manifest files should be ensured.

Reference:

About Side-by-Side Assemblies

Troubleshoot #2

When there comes disparities between Assembly manifest and Application manifest, a message box such as shown below will be displayed.

Image 1

In this case, there is a mismatch in the identities of a referenced component with that of the requested one. Upon launching the application, above message will be displayed by Windows OS and the application will be exited.

One of the apparent ways is to look at the Windows Event Viewer (eventvwr.exe) to see what went wrong. In this case an Error log having “SideBySide” as the source can be seen as shown below.

Activation context generation failed for "D:\Demo\RegFreeCOMDllClient.exe.Manifest".
Error in manifest or policy file "D:\Demo\RegFreeCOMDll.DLL" on line 1. 
Component identity found in manifest does not match the identity of the component requested. 
Reference is RegFreeCOMDll,processorArchitecture="msil",version="2.0.0.0". 
Definition is RegFreeCOMDll,processorArchitecture="msil",version="1.0.0.0". 
Please use sxstrace.exe for detailed diagnosis.

In this case, it is obvious that there is a mismatch between the version of referred component and actual version of the referred component.

Let’s try an example with the contents of Demo folder.

  1. Open RegFreeCOMDllClient.exe.manifest in a text editor.
  2. Change the value of "version="1.0.0.0" that comes under assemblyIdentity node to version="2.0.0.0"
  3. Run RegFreeCOMDllClient.exe

There will come above message box.

The catch is that Application Events in the Windows Event Viewer is a place to look at first when something goes wrong in this way.

Reference:

Application Manifest

Assembly Manifest

Troubleshoot #3

Usage of Tool sxstrace.exe

Event log shown above in Troubleshoot #2 gives us a clue on the possibility of using another tool named “sxstrace.exe”.

There will be situation in which Windows Event Log gives us a little clue on what went wrong. Here comes the usage of a Windows tool named “sxstrace.exe”. This tool provides a detailed sequence of operations executed by Windows SxS Manager. 

The tool is usually available in the path “C:\Windows\System32”. In order to make use of this tool, following lines can be put inside a batch file such as “SxTrace.bat”.

sxstrace Trace -logfile:d:\demo\sxsTrace.bin 
sxstrace Parse -logfile:d:\demo\sxsTrace.bin -outfile:d:\demo\sxsTrace.txt

The first line will start the trace tool and will log side by side assembly loading events to a specified file such as sxsTrace.bin. Once the batch file is running, you can run the problematic registration free COM application. Then stop the batch file by pressing Enter in the batch console window. It will produce a file specified in the second line of the script that is sxsTrace.txt.

Let’s try an example with the contents of Demo folder. 

  1. Ensure that there exists a folder such as D:\Demo.
  2. Rename “RegFreeCOMDll.manifest” to something else.
  3. Start SxTrace.bat.
  4. Run RegFreeCOMDllClient.exe. It would result in a message box shown in Troubleshoot #2.
  5. Press the Enter key in the SxTract.bat console.

You can see the contents of D:\Demo\sxsTrace.txt something such as shown below.
Image 2

The log depicts the sequence of operations done by OS in trying to solve reference to an assembly. Notable line in the above trace log is that of "ERROR: Cannot resolve reference RegFreeCOMDll,processorArchitecture="msil",version="1.0.0.0".". This line indicates the problem to be solved.

This is just an example to show the possibility of using sxsTrace.exe tool. If this tool didn’t encounter any errors then the last but one line will looks like “INFO: Activation Context generation succeeded.

Reference:

Assembly Searching Sequence

Diagnosing SideBySide Failures

Troubleshoot #4

Usage of Tool FUSLOGVW.exe

There will be situation in which the sxstrace.exe will not come to the rescue. Here comes the usage of another tool Assembly Binding Log Viewer or FUSLOGVW.exe.  The tool is part of Windows SDK and can be found in location such as “C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools”. The tool should be run in Administrator mode.

Let’s try an example with the contents of Demo folder. 

  1. Run FULOGVW.exe in Administrator mode.
  2. Rename RegFreeCOMDll.dll to something else.
  3. Run RegFreeCOMDllClient.exe. 

Upon running RegFreeCOMDllClient.exe you will get a message such as “The system cannot find the file specified”, in the console window. Now look at the Assembly Binding Log Viewer. You will see a window such as shown below.
 

Image 3

Select the first log in the above window and press the “View Log” button. The log file will be usually displayed in a browser. Some of the most important message in the log displayed is given below.

Image 4

From the above log, it is clear that the system is trying to locate the renamed RegFreeCOMDll.dll. Since we have renamed it, the system is not able to find and the log concluded that “All probing URLs attempted and failed.”

Troubleshoot #5

Moving forward with these tools, later on, there came a situation in which the tools kept quiet.  It wasn't possible to move a bit forward with the "Class not registered" message continued to popup until I came to know what is called Activation Context.

The trigger for me in writing this article was in fact this “Class not registered” message. Even though I ensured the point mentioned in Troubleshoot  #1, the message continued to popup.

In finding a way out of this situation, I referred one of the very useful tips here at stackoverflow. Even then it didn't succeed.

Finally, I came to realize the possibility of making use of Activation Context APIs and eventually made my addition to the list of possible solutions here.

Activation Context

Activation context is a Windows OS subsystem that deals with loading of Dlls including that of COM.  

In my case, I had to invoke some of the APIs provided by Activation Context, inside C++ client application.

Following functions can be seen in the sample client application that is available with this articile.

void EnableActivationContext()
{
    ACTCTX ctContext;
    memset(&ctContext, 0, sizeof(ctContext));
    WCHAR   modulePath[MAX_PATH] = { 0 };

    //Build manifest file path.
    GetModuleFileName(0, modulePath, sizeof(modulePath));
    wstring wstrModulePath = modulePath;

    int pos = wstrModulePath.rfind('\\');
    wstrModulePath = wstrModulePath.substr(0, pos);

    ctContext.cbSize = sizeof(ctContext);
    ctContext.lpSource = L"RegFreeCOMDllClient.exe.manifest";
    ctContext.lpAssemblyDirectory = wstrModulePath.c_str();
    ctContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

    g_ActivationContext = CreateActCtx(&ctContext);
    ActivateActCtx(g_ActivationContext, &g_Cookie);
}

void DisableActivationContext()
{
    DeactivateActCtx(0, g_Cookie);
    ReleaseActCtx(g_ActivationContext);
}

The code above is actually asking the OS to create an activation context for a given manifest file so that creation of COM component will succeed without any problems such as "Class not registered" message.

Reference:

Activation Contexts

Points Of Interest

There is an interesting phenomena called Activation Context Caching. In that, the external manifest files will be ignored by the system and you will end up in a situation in which modification to manifest file will be ineffective. This will be very irritating while during testing. One way to get rid of this caching is to create new folder somewhere and copy all related binaries, executable and manifest files to this directory. Then run the required components from this location.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Shooting for the Moon.

Comments and Discussions

 
QuestionAnother way for fixing the Activation Context Caching Pin
Doc_13245678912-Apr-22 1:20
Doc_13245678912-Apr-22 1:20 
QuestionThanks Nisamudheen Pin
Dansveen7-Sep-18 4:07
Dansveen7-Sep-18 4:07 
QuestionThanks Nisamudheen Pin
al13n1-May-18 1:27
al13n1-May-18 1:27 
AnswerRe: Thanks Nisamudheen Pin
Nisamudheen1-May-18 19:05
Nisamudheen1-May-18 19:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.