Win32 Apps Not Working, Diagnosed and Fixed (2026 Guide)

Microsoft Fix Intermediate 14 min read Official Docs Grounded Updated April 20, 2026

Why Win32 Apps Stop Working

I've seen this exact situation hundreds of times: a Win32 app runs perfectly fine for weeks, then one morning a user opens it and gets a cryptic error message. Or worse, the app crashes silently, leaving no indication of what went wrong. You restart it, it works for a bit, then fails again. Increasingly often. Until eventually it stops working entirely.

That pattern, works at first, then degrades, then dies, is one of the most telling signatures of a COM+ thread initialization problem. And it's maddening precisely because Win32 apps don't tell you that cleanly. You get something like:

E_INVALIDARG: "The parameter is incorrect" (0x80070057/-2147024809)

Or if you're developing in Visual Basic 6.0:

Run-time error '5': "Invalid procedure call or argument" (0x800a0005/-2146828283)

Or from a .NET client:

System.ArgumentException: "The parameter is incorrect."
at System.Runtime.Type.CreateInstanceImpl(Boolean publicOnly)

None of these error messages give you any real direction. "The parameter is incorrect", which parameter? What call? Where? I know how frustrating it is to be handed that and told to figure it out.

What's actually happening is a COM thread apartment problem deep inside the Win32 application stack. The Component Object Model tracks how many times CoInitialize and CoUninitialize have been called on any given thread using an internal reference count. When that count hits zero, because CoUninitialize was called one too many times, COM is torn down on that thread. If that thread belongs to a COM+ STA ThreadPool, its apartment activator is destroyed along with it. Any activation request routed to that thread from that point forward will fail.

Here's why the degrading pattern happens: as more and more COM+ ThreadPool threads get uninitialized this way, a larger and larger percentage of your activation requests get routed to broken threads. At first, maybe one in twenty requests fails. Then one in ten. Then every single one. Restarting the process resets the thread pool and buys you some time, but unless you fix the root cause, the cycle repeats.

Win32 app activation errors like this commonly happen when a COM DLL is calling CoInitialize or CoUninitialize in its DllMain function in response to attach or detach events, a very common bug pattern, even in well-known components. The threads being managed by COM or COM+ at that point are not the DLL's threads to initialize or uninitialize. They belong to the client application, the COM runtime, or the COM+ runtime.

This affects .NET Framework apps, C++ apps, Visual Basic 6.0 apps, and any Win32 application that consumes COM+ components. It's not limited to developers, system administrators running enterprise software on Windows servers hit this constantly. Browse all Microsoft fix guides →

Beyond COM+ thread issues, Win32 apps not working can also stem from missing Visual C++ Redistributables, corrupted application manifests, side-by-side assembly conflicts (the dreaded SxS errors), insufficient UAC permissions, and DLL load order problems. This guide covers all of them.

The Quick Fix, Try This First

Before you go deep into COM thread tracing or DebugDiag, try restarting the COM+ application hosting the problematic component. This is the fastest way to confirm you're dealing with the thread pool exhaustion pattern, and it often gets you running again immediately while you plan the proper fix.

Open Component Services. The fastest way on any Windows version: press Win + R, type dcomcnfg, and hit Enter. In the left panel, expand Component Services → Computers → My Computer → COM+ Applications. Find the application that's failing, right-click it, and choose Shut down. Wait five seconds, then right-click again and choose Start.

If your Win32 app immediately starts working again after that restart, you've just confirmed the root cause: thread initialization state is accumulating incorrectly over the lifetime of the COM+ application process. The fix is real, it's just not permanent yet.

For Win32 apps failing with side-by-side assembly errors or missing DLL messages, the fastest first move is installing the Visual C++ Redistributable packages. Many Win32 applications depend on specific runtime versions:

winget install Microsoft.VCRedist.2015+.x64
winget install Microsoft.VCRedist.2015+.x86

Run both, even on a 64-bit system, because many Win32 apps ship 32-bit components. After installation, reboot and test before going any further.

For Win32 apps that fail immediately on launch with an access denied error or simply do nothing when you double-click them, right-click the executable and choose Run as administrator. If that fixes it, you have a UAC elevation issue rather than a COM+ problem, which is a completely different (and simpler) fix path covered in Step 3 below.

Pro Tip
When a COM+ application starts degrading gradually, working fine in the morning but throwing errors by afternoon, the culprit is almost always a COM DLL calling CoUninitialize on COM+ managed threads. The number of requests failing will scale directly with how many ThreadPool threads have been hit. Restarting the COM+ process is a temporary fix every time; you need to identify and patch or replace the bad DLL to stop the cycle permanently.
1
Reproduce the Failure and Capture the Exact Error Code

Don't start fixing until you know exactly which error you're dealing with. Generic "Win32 app not working" descriptions get you nowhere. You need the hex error code.

Open Event Viewer immediately after the failure: press Win + R, type eventvwr.msc, and hit Enter. Navigate to Windows Logs → Application. Sort by date and look for entries with the red Error icon matching the time the app failed. Double-click the entry and copy the full event details, especially any HRESULT codes like 0x80070057.

If the Win32 app is a COM+ hosted application, also check Windows Logs → System for DCOM and COM+ errors (Event IDs 10000, 10001, and 10005 are the most common culprits here).

For .NET-based Win32 apps, check the Application log for entries with Source = .NET Runtime or Application Error. These will often include the faulting module name, the actual DLL that caused the crash, which is critical for the advanced tracing steps later.

Write down: the exact error code, the source module if shown, and the time of failure. You'll need all three to diagnose accurately. If you see 0x80070057 in the Event Viewer entries, you're almost certainly dealing with the COM thread initialization pattern described above. If you see 0x8007007E or 0x8007045A, you're looking at a missing DLL. If you see 0xC0000135, the application failed to initialize entirely, usually a missing .NET runtime or side-by-side assembly conflict.

2
Identify the Problematic COM DLL Using DebugDiag

If your error code is 0x80070057 (E_INVALIDARG / "The parameter is incorrect"), the official Microsoft resolution requires you to find which specific COM DLL is calling CoInitialize and CoUninitialize incorrectly. That's where DebugDiag comes in, it's a free Microsoft tool that attaches to running processes and logs exactly what's happening at the function call level.

Download DebugDiag from the Microsoft Download Center (search "DebugDiag download" on microsoft.com, do not use third-party mirrors). Install it, then launch it from Start → IIS Diagnostics (32bit) → Debug Diagnostics Tool.

When it opens, if you see a Select Rule Type dialog, hit Cancel. Go to Tools → Options and Settings → Folders and Search Paths tab and paste this into both the Symbol Search Path fields:

srv*C:\symsrv\*http://msdl.microsoft.com/download/symbols

Now click Add Rule → Crash → Next → A specific MTS/COM+ application. Select your failing COM+ application from the list, then click through to Advanced Configuration → Breakpoints → Add Breakpoint.

Add two breakpoints. First: enter ole32!CoInitializeEx in the Expression field, set Action Limit to 1000, keep Log Stack Trace selected. Second breakpoint: ole32!CoUninitialize, Action Limit 1000. Save, activate the rule, and then use your Win32 app normally until you see the failure.

After a failure, open the log file at C:\Program Files\IIS Resources\DebugDiag\Logs\ and look for CoUninitialize calls with stack traces that show a DLL name other than COMSVCS.dll or ole32.dll. That foreign DLL is your culprit.

3
Remove Incorrect CoInitialize Calls from the Affected COM DLL

Once you know which DLL is making the rogue CoInitialize and CoUninitialize calls, the fix is clear: those calls need to come out. The rule is unambiguous, a COM DLL that is loaded through COM calls should never call CoInitialize or CoUninitialize on the threads used to load or start it. Those threads are owned by the client application, the COM runtime, or the COM+ runtime. Your DLL does not own them.

The only threads a COM DLL is allowed to initialize this way are threads that the DLL itself explicitly creates. A thread you create with CreateThread inside your DLL? Fine. A thread handed to you by the COM+ ThreadPool? Absolutely not.

The most common place this bug lives is in DllMain. If you have code like this:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);  // BUG: remove this
    }
    if (fdwReason == DLL_PROCESS_DETACH) {
        CoUninitialize();  // BUG: remove this
    }
    return TRUE;
}

Remove both those calls. Recompile, redeploy the DLL, restart the COM+ application in Component Services, and test. If you do not have source access to the DLL, it's a third-party component, contact the vendor. One well-known Microsoft component with this exact bug is Cdo.dll, which is explicitly unsupported in multithreaded environments. Microsoft's recommendation is to migrate to Cdosys.dll or Cdonts.dll as replacements.

4
Fix Missing DLL and Side-by-Side Assembly Errors

Win32 apps that fail on launch with errors like "The program can't start because MSVCP140.dll is missing" or "The application was unable to start correctly (0xc000007b)" are missing runtime dependencies. This is one of the most common Win32 app failure modes in 2026, particularly after Windows updates or after migrating apps to a new machine.

First, check whether you're dealing with a Visual C++ runtime issue. Open PowerShell as Administrator and run:

Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "*Visual C++*"} | Select-Object Name, Version | Sort-Object Name

Compare what's installed against what the app requires (check the app's documentation or the vendor's system requirements). Missing a specific version? Install it directly. You can also run the System File Checker to repair corrupted system DLLs:

sfc /scannow

For side-by-side (SxS) assembly errors, typically Event ID 59 or 33 in the System event log with Source = SideBySide, the fix is often to run the application compatibility troubleshooter or to manually register missing assemblies. Run this in an elevated Command Prompt:

regsvr32 "C:\Windows\System32\your_assembly.dll"

For .NET apps specifically, run:

dotnet --list-runtimes

This shows every installed .NET runtime. If the version your app needs isn't there, download it from the official .NET download page. After installing any new runtime, reboot before testing, .NET runtime registration doesn't always take effect without a restart.

5
Repair Application Manifests and UAC Elevation Settings

Win32 apps that silently do nothing when launched, no error message, no window, nothing, are often failing at the manifest validation stage or being silently blocked by UAC. This is particularly common with older enterprise Win32 applications that were written before UAC existed and assume they're always running as Administrator.

First, check whether the app has an embedded manifest. Open an elevated Command Prompt and run:

mt.exe -inputresource:"C:\Path\To\YourApp.exe";#1 -out:manifest.xml
notepad manifest.xml

Look at the requestedExecutionLevel setting. If it says requireAdministrator and UAC is prompting (or suppressed by policy), the app will fail silently in some configurations. The simplest fix without recompiling: right-click the .exe → Properties → Compatibility tab → check "Run this program as an administrator" → Apply.

For Win32 apps deployed via Group Policy or enterprise software management, you can also create a compatibility shim using the Application Compatibility Toolkit (ACT). The most useful shim for legacy Win32 apps is RunAsAdmin, which you can apply without modifying the original binary.

If the app uses COM components registered under HKEY_LOCAL_MACHINE but is being run by a standard user, you may also need to adjust the COM application identity. In Component Services (dcomcnfg), right-click your COM+ application → Properties → Identity tab. Switch from Interactive User to a specific service account with appropriate permissions. After changing the identity, the COM+ application must be restarted for the change to take effect.

After applying any of these manifest or identity changes, test immediately and check Event Viewer for any remaining COM errors (Event IDs 10000–10010 in the System log are all DCOM-related). A clean run with no new entries in those IDs means the fix worked.

Advanced Troubleshooting for Win32 App Failures

If the steps above haven't resolved your Win32 app issues, or if you're in an enterprise environment with domain-joined machines, Group Policy in play, and multiple users affected, you need to go deeper.

Process Monitor (ProcMon) analysis. Download Process Monitor from the Microsoft Sysinternals suite. Launch it, apply a filter for your application's process name (Filter → Process Name → contains → [your app name] → Include), then attempt to launch the failing Win32 app. ProcMon will show you every file access, registry read, and DLL load attempt, including the ones that fail. Look for NAME NOT FOUND results on DLL loads and ACCESS DENIED on registry reads. These tell you exactly which missing dependencies or permission issues are killing the launch.

Dependency Walker analysis. The classic tool for Win32 DLL dependency chains. Load your app's executable in Dependency Walker and it maps the full DLL dependency tree, flagging any missing modules with yellow warning icons. In 2026, use the updated "Dependencies" tool (a modern Dependency Walker replacement available on GitHub) for better support of modern Windows API sets.

Event Viewer correlation for COM+ failures. When Win32 apps fail due to COM+ thread exhaustion, you'll often see a pattern in Event Viewer: Application log entries with Source = COM+ and Event ID 4117 (activation failed) appearing with increasing frequency before the complete failure. Set up a custom view in Event Viewer (right-click Custom Views → Create Custom View) filtering for Event IDs 4117, 4104, and 4101 from source COM+. Watching this custom view over time tells you exactly how quickly thread pool exhaustion is occurring.

Registry integrity for COM registration. If your Win32 app's COM components are registered but not being found, the registry entries may be corrupted or pointing to the wrong DLL path. Check under:

HKEY_CLASSES_ROOT\CLSID\{your-component-CLSID}\InprocServer32

The (Default) value should be the full path to your DLL. If it's missing, blank, or pointing to a path that doesn't exist, re-register the component:

regsvr32 /u "C:\Path\To\Component.dll"
regsvr32 "C:\Path\To\Component.dll"

In domain-joined environments, also check whether Group Policy is applying software restriction policies or AppLocker rules that might be blocking your Win32 app's DLLs. Open gpresult /h c:\gp_report.html as the affected user and open the HTML report, search for "AppLocker" and "Software Restriction" sections. A block here will manifest as either a silent failure or an "Access is denied" error depending on the policy configuration.

Windows App Compatibility fixes. For legacy Win32 apps that fail only on Windows 11, the issue may be an API removed or changed in recent builds. Run the Program Compatibility Troubleshooter (right-click the app → Troubleshoot compatibility) and try "Windows 8" or "Windows 7" compatibility mode. Some Win32 apps also need the __COMPAT_LAYER environment variable set:

set __COMPAT_LAYER=Win7RTM
When to Call Microsoft Support
If you've identified the problem DLL through DebugDiag but it's a Microsoft-provided or third-party component you can't modify, if the COM+ thread exhaustion recurs within hours of every restart, or if you're seeing COM activation failures across multiple applications on the same server with no clear single DLL culprit, stop and escalate. These patterns can indicate deeper COM+ catalog corruption that requires Microsoft's dedicated tooling to diagnose safely. Open a support case at Microsoft Support and include your DebugDiag log files and the Event Viewer export, that evidence will cut the diagnosis time significantly.

Prevention & Best Practices for Win32 App Stability

The best Win32 app failure is the one that never happens. And most of the failures I've walked through above are entirely preventable with the right habits in place.

If you're developing or maintaining COM DLLs, the most impactful rule you can enforce in your codebase is this: never call CoInitialize or CoUninitialize in DllMain. Period. These functions do not belong there. DllMain has strict limitations on what it can safely do, starting or tearing down COM apartments is not one of them. Put COM initialization in explicit initialization functions that callers invoke deliberately.

Thread ownership is the conceptual key. When your DLL is loaded through a COM call, the thread executing that load belongs to someone else, the COM runtime, the COM+ runtime, or the client application. You are a guest on that thread. A guest does not rearrange the host's furniture. Only call CoInitialize and CoUninitialize on threads your code explicitly created and owns.

For enterprise deployments, regular COM+ application health monitoring is worth the setup time. A simple scheduled task that checks the COM+ application status and alerts on degradation catches the slow thread-exhaustion pattern before users start calling the help desk. Windows Task Scheduler with a PowerShell health check script watching Event ID 4117 frequency gives you that early warning for essentially zero cost.

Keep Visual C++ Redistributable packages current via Windows Update or SCCM. A surprising number of Win32 app failures in corporate environments come from machines that have a mix of redistributable versions, some updated, some not, leading to runtime version conflicts that surface as DLL load errors at the worst possible time.

Quick Wins

Frequently Asked Questions

Why does my Win32 app work fine at first but then start failing more and more over time?

That gradual degradation pattern is the signature of COM+ STA ThreadPool thread exhaustion. What's happening is that a COM DLL is calling CoUninitialize on threads owned by the COM+ runtime, which destroys those threads' apartment activators. At first only a small percentage of activation requests hit a broken thread, so most work fine. Over time, more threads get hit, and failures become more frequent. Eventually every thread is broken and the app fails on every request. Restarting the COM+ application (dcomcnfg → right-click your app → Shut down → Start) resets the thread pool temporarily, but the permanent fix requires removing the rogue CoInitialize/CoUninitialize calls from the offending DLL.

I'm getting error 0x80070057 "The parameter is incorrect", what does that actually mean for a Win32 app?

In the context of Win32 apps using COM+, error 0x80070057 (E_INVALIDARG) most often means an activation request was routed to a COM+ STA ThreadPool thread whose apartment activator has been destroyed. The "parameter" that's "incorrect" is effectively the thread state, COM is telling you it can't fulfill the activation because the thread it's trying to use has been improperly uninitialized. C++ apps see this as E_INVALIDARG, Visual Basic 6.0 apps see it as "Run-time error '5': Invalid procedure call or argument" (0x800a0005), and .NET apps throw a System.ArgumentException. Same root cause, different surface. The fix in all three cases is identifying and removing the bad CoUninitialize call in the COM DLL.

Can I fix a Win32 app COM issue without source code access if it's a third-party DLL?

Your options are limited but not zero. First, contact the vendor, this is a well-documented bug pattern and any reputable vendor should have a fix or updated version. Second, check if Microsoft has a replacement: the classic example is Cdo.dll, which Microsoft explicitly acknowledges has this threading bug and recommends replacing with Cdosys.dll or Cdonts.dll. Third, as a temporary operational measure, you can set up a scheduled task to automatically restart the COM+ application on a regular interval, say, every 4 hours, to stay ahead of the thread exhaustion. It's not a fix, but it keeps the app functional while you work on the real solution.

How do I know if DebugDiag found the right DLL causing the Win32 app failure?

In the DebugDiag log file (found under C:\Program Files\IIS Resources\DebugDiag\Logs\), look at the stack traces captured when ole32!CoUninitialize was hit. The expected, harmless stack traces will show only COMSVCS.dll and ole32.dll in the call chain, those are the COM+ runtime doing legitimate cleanup work. If you see any other DLL name in the stack, something that isn't a core COM system DLL, that's your culprit. The log line will look something like: ole32!CoUninitialize ← Mybaddll.dll+0x1234 ← kernel32!BaseThreadStart. The non-system DLL in that chain is where the rogue call is originating.

My Win32 app crashes with 0xc000007b, is that the same COM issue?

No, 0xc000007b is a completely different problem. That error code means "Invalid image format", the app tried to load a DLL and found an architecture mismatch. Most often this means a 64-bit application is trying to load a 32-bit DLL (or vice versa), or a DLL is corrupted. The fix is to verify that all DLLs in the app's dependency chain match the application's architecture (all 64-bit or all 32-bit for a given process). Run the app through Dependency Walker or the modern "Dependencies" tool to see the full load chain and spot any architecture mismatches. Reinstalling the Visual C++ Redistributable for the correct architecture (x64 vs x86) resolves this in the majority of cases.

Is it safe to call CoInitialize in a standard Win32 DLL that isn't loaded through COM?

Yes, with one important restriction. A standard Win32 DLL that isn't loaded via COM calls can safely call CoInitialize and CoUninitialize if it needs to use COM APIs. The critical rule is that these calls must not happen inside DllMain. The DllMain function runs under the loader lock, which severely restricts what you can safely do, COM initialization is explicitly off-limits there. Put your CoInitialize call in a dedicated initialization function that your DLL exports, and call it explicitly after the DLL is loaded. That way you control when COM is initialized on the thread, and you avoid the timing and ownership problems that break COM+ ThreadPool behavior.

Related Microsoft Fix Guides

H
Sai Kiran Pandrala
Our team includes certified Microsoft engineers, Azure architects, and system administrators with 10+ years of enterprise IT experience. Every guide is written from hands-on troubleshooting, not guesswork. We test every fix before publishing.