{"record":{"id":"ee2560afff77e57c","repo":"shadowsocks/shadowsocks-windows","slug":"plugin-program","errorCode":null,"errorMessage":"Plugin Program","messagePattern":"Plugin Program","errorType":"exception","errorClass":"ApplicationException","httpStatus":null,"severity":"error","filePath":"shadowsocks-csharp/Controller/Service/Sip003Plugin.cs","lineNumber":114,"sourceCode":"\r\n                _pluginProcess.StartInfo.Environment[\"SS_LOCAL_HOST\"] = LocalEndPoint.Address.ToString();\r\n                _pluginProcess.StartInfo.Environment[\"SS_LOCAL_PORT\"] = LocalEndPoint.Port.ToString();\r\n                _pluginProcess.StartInfo.Arguments = ExpandEnvironmentVariables(_pluginProcess.StartInfo.Arguments, _pluginProcess.StartInfo.EnvironmentVariables);\r\n                try\r\n                {\r\n                    _pluginProcess.Start();\r\n                }\r\n                catch (System.ComponentModel.Win32Exception ex)\r\n                {\r\n                    // do not use File.Exists(...), it can not handle the scenarios when the plugin file is in system environment path.\r\n                    // https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values\r\n                    //if ((uint)ex.ErrorCode == 0x80004005)\r\n                    //  https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d\r\n                    if (ex.NativeErrorCode == 0x00000002)\r\n                    {\r\n                        throw new FileNotFoundException(I18N.GetString(\"Cannot find the plugin program file\"), _pluginProcess.StartInfo.FileName, ex);\r\n                    }\r\n                    throw new ApplicationException(I18N.GetString(\"Plugin Program\"), ex);\r\n                }\r\n                _pluginJob.AddProcess(_pluginProcess.Handle);\r\n                _started = true;\r\n            }\r\n\r\n            return true;\r\n        }\r\n\r\n        public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null)\r\n        {\r\n            // Expand the environment variables from the new process itself\r\n            if (environmentVariables != null)\r\n            {\r\n                foreach(string key in environmentVariables.Keys)\r\n                {\r\n                    name = name.Replace($\"%{key}%\", environmentVariables[key]);\r\n                }\r\n            }\r","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs#L96-L132","documentation":"Thrown as ApplicationException wrapping a Win32Exception that occurred while starting the Sip003 plugin process, where the native error code is NOT 0x00000002 (file-not-found is handled separately). It is the catch-all for every other Process.Start failure: access denied, bad image, sharing violation, etc. The original Win32Exception is passed as the inner exception so the real native error is inspectable.","triggerScenarios":"ERROR_ACCESS_DENIED (the user/account cannot execute the file or the file is locked); ERROR_BAD_EXE_FORMAT / 0xC1 (the plugin is not a valid executable for this architecture, e.g. 64-bit plugin on a 32-bit host); ERROR_SHARING_VIOLATION (the file is open exclusively elsewhere); the plugin requires elevation and UAC blocks the launch.","commonSituations":"Running the client as a normal user but the plugin requires admin; an architecture mismatch (x64 plugin vs x86 client); antivirus blocking execution; the plugin file being written/replaced while it is being started.","solutions":["Inspect ex.NativeErrorCode of the inner Win32Exception to get the exact Windows error and act on it (e.g. 5 = access denied, 193 = bad exe format).","For access denied, run the client with sufficient privileges or fix file ACLs.","For bad exe format, use a plugin built for the matching architecture.","Add an antivirus exclusion or stop the conflicting process that locks the file."],"exampleFix":"// before\nthrow new ApplicationException(I18N.GetString(\"Plugin Program\"), ex);\n\n// after: include the native error code for diagnosis\nthrow new ApplicationException(\n    I18N.GetString(\"Plugin Program\") + $\" (NativeError 0x{ex.NativeErrorCode:X8})\", ex);","handlingStrategy":"try-catch","validationCode":"// Pre-flight: can the account read/execute the plugin?\nvar fi = new FileInfo(resolvedPluginPath);\nif (!fi.Exists) /* handle before start */","typeGuard":"static string ClassifyWin32(int code) => code switch\n{\n    2 => \"file-not-found\",\n    5 => \"access-denied\",\n    193 => \"bad-exe-format\",\n    _ => \"other\"\n};","tryCatchPattern":"try { plugin.Start(); }\ncatch (ApplicationException ex) when (ex.InnerException is Win32Exception w)\n{ /* branch on w.NativeErrorCode: 5 perms, 193 arch, etc. */ }","preventionTips":["Check bitness match between client and plugin executables.","Run the app with an account that has execute rights on the plugin.","Add antivirus exclusions for the plugin directory."],"tags":["plugin","sip003","process","win32","permissions"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}