{"record":{"id":"bc2cc9072005b7c4","repo":"BluePointLilac/ContextMenuManager","slug":"failed-to-create-shelllink-object","errorCode":null,"errorMessage":"Failed to create ShellLink object.","messagePattern":"Failed to create ShellLink object\\.","errorType":"exception","errorClass":"COMException","httpStatus":null,"severity":"critical","filePath":"ContextMenuManager/BluePointLilac.Methods/ShellLink.cs","lineNumber":274,"sourceCode":"        {\n            get\n            {\n                LinkDataList.GetFlags(out ShellLinkDataFlags flags);\n                return (flags & ShellLinkDataFlags.RunasUser) == ShellLinkDataFlags.RunasUser;\n            }\n            set\n            {\n                LinkDataList.GetFlags(out ShellLinkDataFlags flags);\n                if(value) flags |= ShellLinkDataFlags.RunasUser;\n                else flags &= ~ShellLinkDataFlags.RunasUser;\n                LinkDataList.SetFlags(flags);\n            }\n        }\n\n        public ShellLink(string lnkPath = null)\n        {\n            try { shellLinkW = (IShellLinkW)new CShellLink(); }\n            catch { throw new COMException(\"Failed to create ShellLink object.\"); }\n            Load(lnkPath);\n        }\n\n        ~ShellLink() { Dispose(false); }\n\n        public void Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if(shellLinkW == null) return;\n            Marshal.FinalReleaseComObject(shellLinkW);\n            shellLinkW = null;\n        }\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/BluePointLilac/ContextMenuManager/blob/55507155dd8e49c7ab4606da97f2af192d590dfe/ContextMenuManager/BluePointLilac.Methods/ShellLink.cs#L256-L292","documentation":"The ShellLink constructor instantiates the COM class CShellLink (which implements IShellLinkW, the Windows shell shortcut interfaces). If the COM activation fails — because shell32 is not registered, COM is uninitialized, or the process lacks shell access — the original exception is swallowed and re-thrown as a COMException with a generic message. This masks the root cause, making diagnosis harder.","triggerScenarios":"Calling new ShellLink() (or new ShellLink(path)) on a non-Windows platform, on a thread that has not entered a compatible COM apartment (STA is expected by shell COM objects), or in an environment where the Shell.CLSID {00021401-0000-0000-C000-000000000046} is not registered. Also possible when shell32.dll is corrupted or the process runs in a sandbox container without shell COM access.","commonSituations":"Running unit tests on Linux/macOS CI without COM. Running as a Windows service under a non-interactive session where shell COM is restricted. Forgetting [STAThread] on the entry point, causing MTA-threaded COM activation of an STA-only object. Using a trimmed/self-contained .NET publish that strips COM interop support.","solutions":["Ensure the application runs on Windows with shell32 registered (guard with RuntimeInformation.IsOSPlatform(OSPlatform.Windows))","Ensure the instantiating thread is STA: apply [STAThread] to Main, or call thread.SetApartmentState(ApartmentState.STA) before thread.Start()","Verify the process has shell COM access (not running in an AppContainer or sandbox)","If publishing with trimming, disable COM interop trimming or add a runtime directive for the ShellLink types"],"exampleFix":"// before\nvar link = new ShellLink(shortcutPath);\n\n// after\nif(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n    throw new PlatformNotSupportedException(\"ShellLink requires Windows.\");\n\nvar link = new ShellLink(shortcutPath);","handlingStrategy":"try-catch","validationCode":"static bool CanCreateShellLink()\n{\n    return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)\n        && Type.GetTypeFromCLSID(typeof(CShellLink).GUID) != null;\n}\n\nif(!CanCreateShellLink())\n    throw new PlatformNotSupportedException(\n        \"ShellLink COM object is not available on this platform.\");","typeGuard":null,"tryCatchPattern":"ShellLink link = null;\ntry\n{\n    link = new ShellLink(lnkPath);\n}\ncatch(COMException ex)\n{\n    // The constructor wraps the root cause; check environment first.\n    if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n        throw new PlatformNotSupportedException(\n            \"ShellLink requires Windows with shell32.\", ex);\n    throw new InvalidOperationException(\n        \"Shell COM activation failed. Ensure STA thread and shell32 registration.\", ex);\n}\nfinally\n{\n    link?.Dispose();\n}","preventionTips":["Apply [STAThread] to the application entry point before any ShellLink use","Guard with RuntimeInformation.IsOSPlatform(OSPlatform.Windows) to fail gracefully on non-Windows","Do not instantiate ShellLink in background thread pools without setting STA apartment state","When publishing trimmed/self-contained, add COM interop runtime directives to prevent type stripping"],"tags":["com","shell-link","interop","windows","initialization","threading"],"backgroundTag":null,"analyzedSha":"55507155dd8e49c7ab4606da97f2af192d590dfe","analyzedAt":"2026-08-13T13:32:34.501Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}