What Is Reg-Free COM - Using COM Without Registration

· Updated: · · COM, Reg-Free COM, Registration-Free COM, Windows Development, Legacy Technology

Revision history (1 updates, last updated Sep 1, 2026)

A log of the changes made to this article. Where a pre-update version was archived, it stays readable at a permanent DOI link.

Retranslated as a full translation of the Japanese original. The previous English version was an abridgement that carried only part of the source, so sections, tables, Mermaid diagrams, figure captions and FAQ entries were missing. All of them have been restored to match the Japanese original, and the technical claims are the same as in the Japanese version. Read the version before this update (DOI: 10.5281/zenodo.21614527)
First published
Cite this article(DOI: 10.5281/zenodo.21614526)

This article is archived on Zenodo. Below are both the DOI that always resolves to the latest version and the DOI pinned to the version you are reading.

Go Komura (2026). What Is Reg-Free COM - Using COM Without Registration. KomuraSoft LLC. https://doi.org/10.5281/zenodo.21614526 https://comcomponent.com/en/blog/2026/03/16/011-what-is-reg-free-com/

DOI (latest version)
10.5281/zenodo.21614526
DOI (this version)
10.5281/zenodo.22217163

COM / ActiveX / OCX projects run into the same problems with every deployment and every update.

  • regsvr32 is required
  • Administrator privileges tend to become necessary
  • It collides with a different version installed by another app
  • Uninstalling it drags other products down with it
  • It works on the development machine but not in a clean environment

Reg-Free COM can cut that overhead down considerably. Despite the name, though, it is not magic that makes every COM headache disappear. What it removes is mainly the overhead that comes with global registration. It does not erase the difficulties of bitness, dependent DLLs, type libraries, or threading models.

What Reg-Free COM removes and what it leaves behindA diagram showing that what Reg-Free COM removes is mainly the overhead that comes with global registration, while the difficulties of bitness, dependent DLLs, type libraries, and threading models remain.Reg-Free COMLess global registration overheadSome difficulties remainbitness / dependent DLLs / type libraries

Figure 1: Expect it to split the headaches into the ones that go away and the ones that stay, not to work magic.

This article looks at Reg-Free COM mainly in the context of keeping COM DLLs / OCXs application-local inside a Windows desktop app.

Who This Is For and What It Assumes

This is written for developers who ship a Windows desktop app that uses an existing COM DLL / OCX and want to get out from under regsvr32 and administrator privileges. It assumes you have worked with the basics of COM at least once: CLSID, ProgID, CoCreateInstance, and in-proc servers. If that ground is still shaky, it is faster to read What Are COM / ActiveX / OCX? - The Differences and Relationships Explained first.

The step-by-step parts use mt.exe and sxstrace from the Windows SDK, so they assume a machine with Visual Studio or the Windows SDK installed.

1. The Conclusion First, in One Line

Here is a rough but useful way to put it up front.

  • Reg-Free COM is a way of holding COM registration information in a manifest instead of the registry
  • At runtime, the activation context is consulted first when CoCreateInstance or CLSIDFromProgID resolves a class
  • That is what lets you keep a COM DLL / OCX private to each application
  • The main benefits are that it is easy to deploy by XCOPY, that version conflicts are easier to avoid, and that uninstalls are harder to break
  • However, the 32-bit / 64-bit problem does not go away. No way of writing the manifest gets around it
  • You also need to think separately about dependent DLLs, type libraries, design-time references, and dependencies on non-standard registration data
  • In practice it is a very good fit when you want to ship an app-specific COM component alongside the app

In short, Reg-Free COM is a mechanism that pulls COM activation back to the per-application level.

Where registration information lives changesA diagram showing that Reg-Free COM holds COM registration information in a manifest instead of the registry, that the activation context is consulted first when calls such as CoCreateInstance resolve a class, and that COM components can therefore be kept private to each application.Hold registration information in a manifestActivation context comes first during resolutionCOM components can be private per applicationEasier XCOPY deployment and conflict avoidance

Figure 2: The essence is that the entry point for resolution moves from the registry to the manifest.

Knowledge map for this article

Reg-Free COM is a mechanism that keeps COM registration information in manifests rather than the registry and, at run time, consults the activation context first to resolve the DLL. The application manifest declares the side-by-side assemblies it depends on while the component manifest holds the information that originally lived in the registry, such as the CLSID and the ProgID; the manifests are embedded with mt.exe, and resolution failures are traced with sxstrace. The 32bit/64bit match requirement is not lifted, however, and the handling of dependent DLLs and type libraries remains a separate issue, so the approach suits making existing desktop assets such as VB6, MFC, and WinForms app-local, but does not suit situations that require COM to be shared machine-wide. On .NET 5+ and .NET 8, EnableComHosting produces a comhost, and enabling EnableRegFreeCom emits the side-by-side manifest for Reg-Free COM.

Reg-Free COMDiagram showing how Reg-Free COM keeps COM registration information per application through the activation context and side-by-side assembly mechanisms, how the application manifest and the component manifest divide the roles between them, how mt.exe builds the configuration and sxstrace investigates failures, and how all of this relates to comhost in .NET 5 and laterusesusesusesrequiresimplementsrequiressuccessor tousesconfigured byverified byconfigured byrequiresusesrequiresconfigured byimplementsusesusesusesusesusesusesrecommended forrecommended forrecommended fornot recommended forRegistration-Free COMActivation ContextWin32 Application ManifestComponent manifest (assembly manifest)Side-by-Side AssemblyBitness Match Requirementregsvr32Type Library (TLB)mt.exe (Manifest Tool)sxstracePrivate Assembly Searching Sequence.NET (Core and Later)COM host (*.comhost.dll)EnableComHostingEnableRegFreeComVisual Basic 6.0 (VB6)CLSID (Class ID)ProgID (Programmatic Identifier)COM (Component Object Model)ActiveXOCXMFC (Microsoft Foundation Classes)Windows FormsMachine-Wide COM Sharing

In the diagram a solid line marks a relation that always holds and a dashed line marks a conditional one (the conditions are given per relation on the detail page). The full list of relations (26 in total, with evidence and certainty) and the definitions of the main concepts are collected on the knowledge map detail page (in Japanese). Data: JSON-LD / Turtle

2. What This Article Means by Reg-Free COM

Reg-Free COM is short for Registration-Free COM. In Japanese it is also written as toroku fuyo COM, literally COM that needs no registration.

“Registration-free” here means not depending entirely on global registry registration such as HKCR / CLSID / InprocServer32 in order to use COM. It does not mean that COM itself goes away, nor that GUIDs are no longer needed.

The main subjects of this article are the following.

  • Native COM DLLs
  • ATL-based COM servers
  • ActiveX / OCX
  • COM interop based on .NET Framework
  • Exposure through the .NET 5+ / .NET 8 COM host

Conversely, there are two points this article wants to stress.

  1. Reg-Free COM is a story about activation
  2. Distributing type information and configuring design-time references can remain a separate issue

Mixing the two muddies the discussion considerably.

Two issues that must not be mixedA diagram showing that Reg-Free COM is about activation while distributing type information and configuring design-time references remain a separate issue, so mixing the two muddies the discussion.Reg-Free COMA story about activationType information and design-time referencesRemain a separate issueMixing them muddies the discussion

Figure 3: Keep the runtime story and the design-time story apart from the start.

3. The Whole Picture on One Page

Before the diagram, here are definitions for the four terms that keep coming up in this article.

Term Meaning
activation context A runtime data structure that holds which version of which assembly this thread uses right now. CoCreateInstance consults it before the registry
side-by-side assembly The Windows mechanism for letting components with the same name coexist on one machine in different versions. They are identified by manifests, and assemblyIdentity is the name tag
application manifest XML attached to the EXE that states which side-by-side assemblies the app depends on
component manifest (assembly manifest) XML attached to the component that states which files this assembly contains and which COM classes it exposes. The information that used to live in the registry moves here

An activation context is held per thread. COM hands the creating thread’s activation context to the hosting thread before it calls LoadLibrary or DllGetClassObject, so no special setup is needed on the calling side.

With that in place, it is faster to see the whole picture in a single diagram.

MyApp.exeApplication ManifestdependentAssemblyComponent / Assembly Manifestfile / comClass / typelibVendorControl.dll / .ocxActivation ContextCLSIDFromProgID / CoCreateInstance

Figure 4: Following the app manifest to the component manifest reaches the DLL without using the registry.

In ordinary COM, CoCreateInstance walks the registry to decide which DLL to load. In Reg-Free COM, it first looks at the activation context currently in effect and resolves the class from the manifest information written there.

That makes it much easier for app A and app B to run on the same machine while each carries its own version of the same family of COM component. It nudges COM’s culture of sharing a little way back toward being application-local.

4. Why Ordinary COM Deployment Tends to Get Heavy

Ordinary COM deployment is heavy less because COM itself is bad than because of the assumption of global registration.

Using a COM class requires roughly this set of information.

Information Role
CLSID GUID that uniquely identifies the class
ProgID A name that is easy for people to work with
InprocServer32 Which DLL to load
ThreadingModel Assumptions such as Apartment or Both
TypeLib Type information

Once these go into the registry, they are convenient machine-wide, because several apps can share them easily.

In practice, though, that sharing backfires.

  • One product’s setup overwrites another product’s COM registration
  • An uninstaller breaks shared COM while believing it removed only its own entries
  • A registration that happens to be present on the development machine is missing on the production machine
  • The 32-bit and 64-bit registrations fail to line up, and only the symptoms drift around in unsettling ways

In other words, the deployment model troubles people far more often than COM itself does. Reg-Free COM is a mechanism for reducing the pain of that deployment model.

How machine-wide sharing backfiresA diagram showing that putting COM registration information in the registry makes it easy to share machine-wide, but that in practice the sharing backfires as overwrites by other products, collateral damage during uninstall, and differences between development and production machines, so the deployment model troubles people more than COM itself.Share registration information machine-wideConvenient because many apps can use itIn practice the sharing backfiresOverwrites / collateral damage / environment driftThe deployment model troubles people

Figure 5: The pain does not come from COM itself but from the assumption of global registration.

5. How Reg-Free COM Works

5.1 Declaring Dependencies in the Application Manifest

First, the app side writes which side-by-side assemblies it depends on into its application manifest.

This manifest can be handled either way:

  • placed next to the EXE, as in MyApp.exe.manifest
  • embedded in the EXE as a resource

In practice the split is usually an external file when you want deployment and replacement to stay visible, and embedding when you value robustness and a simple deployment more.

Note that when both an external file and an embedded copy exist, the manifest on the file system wins.

5.2 Describing COM Information in the Component Manifest

Next, the COM side carries the information that would normally live in the registry in a component manifest.

The information that goes in here looks like this.

  • comClass
  • clsid
  • progid
  • threadingModel
  • typelib
  • proxy / stub entries, window classes, and so on when they are needed

In other words, the idea is to describe what the COM component looks like in XML instead of in the registry.

This manifest can be set up either way:

  • placed as a separate file next to the DLL
  • embedded in the DLL as a resource

In practice, embedding it in the DLL as a private assembly is usually harder to get wrong. Running with a separate file is easier to follow, but it is also easy to trip over the mapping between the file name and assemblyIdentity, over where the file has to sit, and over copies that never got made.

Ways to hold the component manifestA diagram showing that the component manifest holds information such as comClass, clsid, and typelib that used to live in the registry as XML, that it can be placed as a separate file next to the DLL or embedded into the DLL as a resource, and that embedding is harder to get wrong in practice.Hold the registry information as XMLPlace it as a separate fileEmbed it into the DLLEasy to trip over missed copiesUsually harder to get wrong in practice

Figure 6: The content is the same either way, but how you place it decides how much can go wrong.

5.3 At Runtime, the Activation Context Is Consulted First

This is the heart of Reg-Free COM.

When the app calls CLSIDFromProgID or CoCreateInstance, the COM runtime looks at the active activation context. If the ProgID to CLSID and CLSID to DLL information it needs is there, it can resolve the class without touching the registry.

If the manifest is missing something it needs, resolution falls back to the usual registration-based path. That behavior sets up the trap where it happens to work on the development machine: you think you have gone Reg-Free, when in fact a local registration is bailing you out.

This is the nastiest pitfall in Reg-Free COM.

The trap of falling back to registration-based resolutionA diagram showing that the activation context is consulted first when CoCreateInstance resolves a class, but that resolution falls back to the usual registration-based path when the manifest lacks the information it needs, which creates the trap of the app happening to work on the development machine thanks to a local registration.EnoughNot enoughResolution starts with the activation contextDoes the manifest have enough informationResolved without the registryFalls back to registration-based resolutionThe trap of happening to work on the dev machine

Figure 7: A fallback that happens silently is the biggest pitfall in this mechanism.

6. What You Gain

The benefits of Reg-Free COM are quite clear in practice.

6.1 Easy XCOPY Deployment

You can put every file you need into the app folder, which lightens the installer and the registration steps. Permissions are a separate matter if you write under Program Files, of course, but at minimum the administrator work needed for COM registration is easy to cut down.

6.2 Easier to Reduce Version Conflicts

Even when several versions of a COM component exist on the same machine, it becomes easy to keep each app on the version it wants. That makes it far easier to avoid the incident where behavior suddenly changed after another product's setup ran.

6.3 Existing Code Often Needs Few Changes

Reg-Free COM changes how resolution happens rather than fundamentally changing how existing code makes its calls. So when it fits, you can adopt it with almost no changes to the CoCreateInstance side of the code.

6.4 Removal and Rollback Get Easier

Because everything is contained per app, updates and rollbacks become much more straightforward. At the extreme, it becomes reasonable to think in terms of swapping the whole folder.

What you gain by containing things per applicationA diagram showing that containing COM components per application yields easy XCOPY deployment, easier avoidance of version conflicts, adoption with almost no changes to existing code, and simple removal and rollback.Contain it per applicationEasy XCOPY deploymentFewer version conflictsSwap the whole folderCalling code barely changes

Figure 8: Every one of the benefits grows out of the single property of being contained.

7. Where It Fits and Where It Does Not

7.1 Where It Fits

In cases like these, Reg-Free COM is a strong option.

Situation Fit
You want to bundle an app-specific COM DLL / OCX Very good
You want several versions coexisting on one PC Very good
You want to avoid registration problems with vendor components Good
You want to use an ActiveX / OCX privately inside an existing desktop app Good
You want lighter deployment without changing existing calls much Good

Typically it fits well with line-of-business desktop apps, equipment-integration tools, and existing VB6 / MFC / WinForms assets.

7.2 Where It Does Not Fit, or Deserves a Careful Look

On the other hand, there are cases worth looking at carefully.

Situation Comment
You want to share COM machine-wide Reg-Free has little to offer
Bitness does not line up Reg-Free does not solve this
Heavy dependence on non-standard registration data or a custom setup Hard to express as a manifest
Distribution of dependent DLLs or the VC++ runtime is not sorted out You will trip somewhere else instead
Design-time tools or IDE reference settings assume the registry A separate operational design is needed

The last point in particular matters. Reg-Free COM helps with runtime activation, but it does not single-handedly change what the design-time reference UI assumes.

Runtime is covered but design time is notA diagram showing that Reg-Free COM helps with runtime activation but does not by itself change design-time tools and IDE reference settings that assume the registry, so a separate operational design is needed.Runtime activationReg-Free helps hereDesign-time reference settings UIMay assume the registryA separate operational design is needed

Figure 9: Getting the software to run is one job; getting it to be developed against is another.

8. Common Misconceptions

8.1 With Reg-Free COM, the Bitness Problem Goes Away

It does not. A 32-bit process can load only 32-bit in-proc COM DLLs, and a 64-bit process takes only 64-bit DLLs. This is the same under Reg-Free as it always was.

8.2 With Reg-Free COM, the Registry Is Never Consulted

Also wrong. If the manifest lacks the information it needs, resolution falls back to the usual registration-based path. So success on the development machine does not mean the Reg-Free configuration is correct.

8.3 With Reg-Free COM, the Type Library Story Sorts Itself Out

This one is only half right. A manifest can carry typelib information too, but handling type information - VBA reference settings, #import in C++, generating design-time references on the .NET side - routinely needs a design of its own.

Reg-Free COM is, first of all, about getting things to start. How to develop against types is the next issue after that.

The order of getting it to start and dealing with typesA diagram showing that a manifest can carry typelib information but that handling type information for VBA reference settings, C++ import, and design-time interop generation on the .NET side needs its own design, so Reg-Free COM is first about getting things to start and typed development is the next issue.Set up Reg-Free COMFirst get it to startThen decide how to develop against typesVBA references / import / interop generation

Figure 10: Being able to write typelib is not the same as having type information sorted out.

8.4 With Reg-Free COM, Any ActiveX / OCX Just Works As-Is

This one is dangerous too. If the component rides on standard COM registration data, you can move ahead easily, but once it leans heavily on custom registry settings, extra setup steps, licensing logic, or a cluster of other modules, going Reg-Free gets rough fast.

8.5 Reg-Free COM Is Roughly the Same on .NET Framework and .NET 8

They have things in common, but the toolchains differ considerably. The .NET Framework + RegAsm world and the .NET 5+ / .NET 8 + comhost world stand on different footing, even though both are COM.

9. Differences Between Native, .NET Framework, .NET 5+, and .NET 8

These get mixed up easily, so it is worth separating them once.

Family Rough summary
Native COM DLL / OCX Basically a matter of an application manifest plus a component manifest
COM interop based on .NET Framework On top of the Win32-style application manifest, the managed component side needs a manifest as well
Exposing COM on .NET 5+ / .NET 8 EnableComHosting builds a COM host, and EnableRegFreeCom can generate the Reg-Free manifest

9.1 .NET Framework-Based COM

With .NET Framework-based COM you end up with two tiers: a Win32-style application manifest on the COM app side and a component manifest on the managed component side.

In other words, one more manifest than with native COM. The naming and resource ID constraints in 10.4 apply to this component manifest in exactly the same way.

9.2 Exposing COM on .NET 5+ / .NET 8

On .NET 5+ / .NET 8, the entry point for COM exposure is *.comhost.dll. Add EnableRegFreeCom=true and the build also emits a side-by-side manifest for Reg-Free COM.

Type information remains a separate issue, as 8.3 says, and .NET Core / .NET 5+ changes that further. This is no longer the world of the .NET Framework days where a TLB falls out of the assembly on its own, so if you need typed usage you have to assemble TLB generation, embedding, and registration yourself. Using a .NET 8 DLL from VBA with Full Typing - COM Exposure and dscom TLB covers the concrete steps.

Reg-Free COM on .NET 5 and laterA diagram showing that on .NET 5 and later EnableComHosting builds the comhost.dll that serves as the entry point for COM exposure, that enabling EnableRegFreeCom emits a side-by-side manifest for Reg-Free COM, and that TLB generation and registration still have to be assembled separately.Build with EnableComHostingcomhost.dll becomes the entry pointEnable EnableRegFreeComA Reg-Free manifest is emittedHandle the TLB separately

Figure 11: On .NET 8 two properties get the plumbing in place, but type information is separate work.

10. A Minimal Configuration

This section sketches the minimal setup in which MyApp.exe uses Vendor.CameraControl.dll through Reg-Free COM.

10.1 File Layout Sketch

MyApp.exe
MyApp.exe.manifest
Vendor.CameraControl.Asm.manifest
Vendor.CameraControl.dll
Vendor.Helper.dll

The example above assumes the component manifest sits in a separate file. You can embed it in the DLL instead, but then fixed constraints apply to the assembly name and the resource ID. Section 10.4 covers that along with the steps.

10.2 Application Manifest Sketch

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="KomuraSoft.MyApp"
    version="1.0.0.0"
    processorArchitecture="amd64" />

  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Vendor.CameraControl.Asm"
        version="1.0.0.0"
        processorArchitecture="amd64" />
    </dependentAssembly>
  </dependency>
</assembly>

10.3 Component Manifest Sketch

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="Vendor.CameraControl.Asm"
    version="1.0.0.0"
    processorArchitecture="amd64" />

  <file name="Vendor.CameraControl.dll">
    <comClass
      clsid="{01234567-89AB-CDEF-0123-456789ABCDEF}"
      progid="Vendor.CameraControl.1"
      threadingModel="Apartment"
      tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}" />

    <typelib
      tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}"
      version="1.0"
      helpdir="" />
  </file>
</assembly>

What really matters in this example is not the XML details but that the app-side dependentAssembly and the component-side assemblyIdentity agree. When they drift apart, you get a startup failure whose cause is invisible from the look of the error alone.

The GUIDs and names above are examples used for explanation. In real work you have to write them to match the CLSID / TLBID / ProgID / threading model that the component actually exposes.

The matching requirement between the two manifestsA diagram showing that the app-side dependentAssembly and the component-side assemblyIdentity have to agree on name and version, and that a mismatch produces a startup failure whose cause is invisible from the look of the error alone.MatchMismatchApp-side dependentAssemblyDo the name and version matchComponent-side assemblyIdentityResolution succeedsStartup failure with no visible cause

Figure 12: What decides life or death is not the XML details but whether the name tags on both sides agree.

10.4 Where to Put the Manifest and How to Embed It

This is where the procedure trips people up the most. The names you are allowed to use change depending on whether you place the manifest as a separate file or embed it in the binary.

For a private assembly, side-by-side searches in this order relative to the app folder.

  1. The WinSxS folder
  2. <appdir>\<assemblyname>.DLL
  3. <appdir>\<assemblyname>.manifest
  4. <appdir>\<assemblyname>\<assemblyname>.DLL
  5. <appdir>\<assemblyname>\<assemblyname>.manifest

If a DLL whose name matches the assembly name is found first, the search stops there. That leaves only the following two workable arrangements.

Placement Assembly name Files Embedded resource ID
Separate file Must differ from the DLL name. Example: Vendor.CameraControl.Asm Place Vendor.CameraControl.Asm.manifest next to the DLL Not embedded
Embedded in the DLL May be the same as the DLL name. Example: Vendor.CameraControl Vendor.CameraControl.dll only 1

In other words, if you use the name Vendor.CameraControl.Asm as in the 10.2 and 10.3 examples, that is the separate file convention. To switch to embedding, change the name in assemblyIdentity to Vendor.CameraControl and align the dependentAssembly side to the same name.

How the search stopsA diagram showing that side-by-side searches for a private assembly from WinSxS through the app folder, that the search stops as soon as a DLL matching the assembly name is found, and that a separate-file setup therefore needs an assembly name different from the DLL name.FoundNot foundStart the private assembly searchLook for a DLL matching the assembly nameThe search stops thereLook for a manifest file of the same nameWith separate files, use a different name

Figure 13: The naming constraint comes straight from the fact that the search stops partway.

There is one more constraint that is easy to get wrong. A component manifest cannot go into the resources of an EXE. What can go into an EXE is the application manifest.

Use mt.exe (the manifest tool) from the Windows SDK to embed a manifest. Run it from the Visual Studio developer command prompt.

rem 1. Get the syntax check to pass before embedding anything
mt.exe -manifest MyApp.exe.manifest -validate_manifest
mt.exe -manifest Vendor.CameraControl.manifest -validate_manifest

rem 2. Embed the application manifest into the EXE
mt.exe -manifest MyApp.exe.manifest -outputresource:MyApp.exe;#1

rem 3. Embed the component manifest into the DLL (resource ID is 1)
mt.exe -manifest Vendor.CameraControl.manifest -outputresource:Vendor.CameraControl.dll;#1

rem 4. Extract it again to confirm the embedding worked
mt.exe -inputresource:Vendor.CameraControl.dll;#1 -out:extracted.manifest

Comparing the extracted.manifest produced by the fourth command against the original XML rules out the case where you thought you embedded the manifest but nothing actually went in.

Embedding steps with mt.exeA diagram showing the mt.exe flow of first passing the syntax check with validate_manifest, then embedding the application manifest into the EXE and the component manifest into the DLL at resource ID 1, and finally extracting it again to compare against the original XML.Pass the syntax checkEmbed the app side into the EXEEmbed the component side into the DLL (ID 1)Extract it and compare with the original XML

Figure 14: Treat embedding as one procedure that runs all the way through verification.

There are two things to watch out for with mt.exe.

  • The files a manifest references have to sit in the same directory as the manifest. If you wrote <file name="Vendor.CameraControl.dll">, put that DLL next to the manifest before running the command. When the build output and the manifest are managed in different places, this is where you stop
  • If you omit the resource ID from -outputresource, CREATEPROCESS_MANIFEST_RESOURCE (= 1) is used. Spelling out ;#1 reads better and keeps an unintended 1 from causing trouble

To replace something that is already embedded, -updateresource:<file>;#1 works. It means the same thing as passing the same argument to both -inputresource and -outputresource.

10.5 A Verification Procedure That Includes a Clean Environment

With Reg-Free COM, “it worked on the development machine” means almost nothing, because the possibility that a local registry registration is bailing you out never goes away. Verify in this order.

  1. Build, and gather the full set of deliverables into one folder. The EXE, the manifests, the COM DLL, the dependent DLLs, the VC++ runtime, and the proxy / stub DLLs
  2. Prepare a verification environment. Ideally one where the COM in question has never been registered. Windows Sandbox lets you start from a blank slate every time
  3. In that environment, confirm first that the COM is not registered. If the commands below fail with a message saying the key was not found, it is unregistered
  4. Copy the folder over and launch it as-is. No installer, no regsvr32
  5. Confirm that COM object creation actually goes through. Simply launching the app does not verify components that are created lazily. Exercise the screens and features where CoCreateInstance really runs
  6. If it fails, collect logs with the procedure in 11.2

These are the commands for step 3.

reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:64
reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:32
reg query "HKCR\Vendor.CameraControl.1"

The 32-bit and 64-bit registry views are separate things, so always look at the side that matches the app’s bitness. Checking both /reg:64 and /reg:32 makes it certain.

To try this on the development machine, unregister first with regsvr32 /u Vendor.CameraControl.dll and then check. That has side effects on machines where another product uses the same COM, though, so preparing a clean environment is safer.

The verification flow in a clean environmentA diagram showing the flow of gathering the full set of deliverables into one folder, preparing a verification environment where the target COM has never been registered, confirming first that it is unregistered, copying the folder over and launching it as-is, and exercising the features where CoCreateInstance runs.If it failsGather the full set of deliverablesPrepare a clean verification environmentConfirm first that it is unregisteredCopy it over and launch as-isExercise the features that create COM objectsCollect logs and investigate

Figure 15: Checking that nothing is registered keeps happens-to-work results out of the verification.

11. Pitfalls

11.1 It Works on the Development Machine but Not on the Target

The first suspect is the pattern where a registry registration was actually bailing you out. It is safer to verify Reg-Free COM in a clean environment wherever possible.

11.2 It Fails to Start with “side-by-side configuration is incorrect”

This family of failures comes from manifest inconsistencies, missing dependent DLLs, a missing VC++ runtime, an architecture mismatch, and the like. The surface error text is quite unhelpful on its own, so the standard move is to chase it through the event log and sxstrace.

For the event log, open Event Viewer > Windows Logs > Application and look for errors whose source is SideBySide. That tells you which assembly failed to resolve.

Capture sxstrace while reproducing the failure. Opening the command prompt as administrator makes this reliable.

rem 1. Start the trace. Leave this window open
sxstrace trace -logfile:sxstrace.etl

rem 2. In another window, launch the app and reproduce the failure

rem 3. Stop the trace. Press Enter in window 1, or run the following from another window
sxstrace stoptrace

rem 4. Convert the raw .etl into a human-readable form
sxstrace parse -logfile:sxstrace.etl -outfile:sxstrace.txt

If you do not want the stop prompt, add -nostop to step 1. If the output is too long, add -filter:MyApp.exe to step 4 to narrow it down to the app in question.

The converted sxstrace.txt lists, in order, which manifests were looked for and where the match failed. If you got the naming in 10.4 wrong, the file names it went looking for will show that here too.

How to investigate a side-by-side errorA diagram showing the flow for a startup failure reported as side-by-side configuration is incorrect: check Event Viewer for errors from the SideBySide source, start a trace with sxstrace, reproduce the failure, stop the trace and convert it with parse, and read where the mismatch occurred.Check the event log for SideBySideStart a trace with sxstraceLaunch the app and reproduce the failureStop it and convert with parseRead the search and the mismatch

Figure 16: Do not agonize over the surface error text; follow the resolution path through logs and traces.

11.3 The Component Manifest and the Application Manifest Drift Apart

  • The name differs
  • The version differs
  • The processorArchitecture differs
  • The manifest you thought you copied is stale

These look like tiny differences on the surface, but they hit quite hard at startup.

11.4 Forgetting to Ship a Dependent DLL

If you look at Vendor.CameraControl.dll alone and call it done, you leave out the Vendor.Helper.dll that gets loaded downstream, the VC++ runtime, and the proxy / stub DLLs. Reg-Free COM reduces COM registration problems, but it does not also erase native dependency-resolution problems.

11.5 Putting Off Type Library and Reference-Setting Work

Even once runtime activation goes through, the moment you want to

  • early-bind from VBA
  • use #import from C++
  • generate interop at design time on the .NET side

you need a way to distribute type information. Reg-Free COM does not arrange all of that for you, so it matters to think about runtime and design-time separately.

12. Summary

In one line, Reg-Free COM is a mechanism that shifts COM registration information from the whole machine down to the individual application.

That gives you the following benefits.

  • COM DLLs / OCXs are easy to keep application-local
  • Version conflicts are easier to reduce
  • Deployment and rollback are easier to simplify

At the same time,

  • 32-bit / 64-bit
  • dependent DLLs
  • TLBs and reference settings
  • dependencies on non-standard registration data
  • verification in a clean environment

all still matter.

So the basic stance when adopting Reg-Free COM is this.

  1. Accept that this is a story about activation
  2. Separate the runtime and design-time issues
  3. Verify in a clean environment
  4. Line up bitness and dependent DLLs first

Take them in that order and far less goes wrong.

The basic stance when adopting itA diagram showing that adopting Reg-Free COM goes more smoothly when you accept it as a story about activation, separate runtime from design-time issues, verify in a clean environment, and line up bitness and dependent DLLs first.Accept it as a story about activationSeparate runtime from design-timeVerify in a clean environmentLine up bitness and dependent DLLs first

Figure 17: Follow the four stances in order and most of the trouble in adoption disappears.

14. References

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Frequently Asked Questions

Common questions about the topic of this article.

What is Reg-Free COM?
It is a mechanism that holds COM registration information in a manifest instead of the registry, and the name is short for Registration-Free COM. At runtime, resolution through CoCreateInstance or CLSIDFromProgID consults the activation context first and resolves the DLL from the manifest information found there. That is what lets you keep a COM DLL or OCX private to each application, which makes XCOPY deployment easy, makes version conflicts easier to avoid, and makes uninstalls harder to break.
Does moving to Reg-Free COM also solve the 32-bit / 64-bit problem?
No. A 32-bit process can load only 32-bit in-proc COM DLLs, and a 64-bit process takes only 64-bit DLLs. That is the same under Reg-Free as it always was. You also have to think separately about shipping dependent DLLs and the VC++ runtime, about type libraries, about design-time reference settings, and about dependencies on non-standard registration data. What Reg-Free COM removes is mainly the overhead that comes with global registration.
Why does a Reg-Free COM setup work on the development machine but fail on the target?
The first suspect is the pattern where a registry registration was actually bailing you out. When the manifest lacks the information it needs, the COM runtime falls back to the usual registration-based resolution, so a local registration on the development machine can make things happen to work. That is why it is safer to verify Reg-Free COM in a clean environment. When startup fails with side-by-side configuration is incorrect, the cause is a manifest inconsistency, a missing dependent DLL, or something similar, and the standard move is to chase it through the event log and sxstrace.
Can a COM component built on .NET 8 be made Reg-Free as well?
Yes. On .NET 5+ and .NET 8, EnableComHosting builds the *.comhost.dll that serves as the entry point for COM exposure, and adding EnableRegFreeCom=true emits a side-by-side manifest for Reg-Free COM. Reg-Free COM and TLB strategy are separate issues, though. On .NET Core and .NET 5+, a TLB does not fall out of the assembly the way it did in the .NET Framework days, so if you need typed usage such as early binding from VBA, it is safer to sort out TLB generation, embedding, and registration on their own.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog