{"record":{"id":"183c57ffe3641798","repo":"seerge/g-helper","slug":"failed-to-get-switchable-graphics-applications-er","errorCode":null,"errorMessage":"Failed to get switchable graphics applications. Error code: ","messagePattern":"Failed to get switchable graphics applications\\. Error code: ","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"app/Gpu/AMD/AmdGpuControl.cs","lineNumber":374,"sourceCode":"\n        return performanceLevels;\n    }\n\n    public void KillGPUApps()\n    {\n\n        if (!IsValid) return;\n\n        nint appInfoPtr = nint.Zero;\n        int appCount = 0;\n\n        try\n        {\n            // Get switchable graphics applications information\n            var result = ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr);\n            if (result != 0)\n            {\n                throw new Exception(\"Failed to get switchable graphics applications. Error code: \" + result);\n            }\n\n            // Convert the application data pointers to an array of structs\n            var appInfoArray = new ADLSGApplicationInfo[appCount];\n            nint currentPtr = appInfoPtr;\n\n            for (int i = 0; i < appCount; i++)\n            {\n                appInfoArray[i] = Marshal.PtrToStructure<ADLSGApplicationInfo>(currentPtr);\n                currentPtr = nint.Add(currentPtr, Marshal.SizeOf<ADLSGApplicationInfo>());\n            }\n\n            var appNames = new List<string>();\n\n            for (int i = 0; i < appCount; i++)\n            {\n                if (appInfoArray[i].iGPUAffinity == 1)\n                {","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/seerge/g-helper/blob/b9ba417f1b822110ce41a1e152031a84bfa6ad80/app/Gpu/AMD/AmdGpuControl.cs#L356-L392","documentation":"Thrown inside AmdGpuControl.KillGPUApps when the AMD Display Library call ADL2_SwitchableGraphics_Applications_Get returns a value other than ADL_SUCCESS (0). This is a P/Invoke into atiadlxx.dll (AmdAdl2.cs:534) that enumerates applications with GPU affinity; the iListType argument is hardcoded to 2. AMD ADL returns negative integer codes (e.g. ADL_ERR=-1, ADL_ERR_NOT_INIT=-2, ADL_ERR_INVALID_PARAM=-3, ADL_ERR_NOT_SUPPORTED=-8), which are appended to the message. Note the whole block is wrapped in try/catch that calls Logger.WriteLine, so the exception is caught and logged and KillGPUApps simply degrades to not killing any apps.","triggerScenarios":"Calling KillGPUApps when ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr) returns non-zero. This happens when the ADL context handle is stale/uninitialized, atiadlxx.dll is the wrong version, the driver does not support switchable graphics or list type 2, no discrete+integrated GPU pairing exists, or the call is made after ADL2_Main_Control_Destroy. The guard 'if (!IsValid) return;' (line 363) only checks _isReady && _adlContextHandle != 0, so a valid-but-not-fully-functional context still reaches the throwing call.","commonSituations":"AMD Adrenalin driver is missing, outdated, or a version that dropped the switchable-graphics API; the system is a desktop with a single AMD GPU (no switchable graphics); atiadlxx.dll loaded but ADL2_Main_Control_Create partially failed; running on an Intel/NVIDIA-only machine where Adl2.Load succeeded by accident; the context was disposed while KillGPUApps ran. Because it is logged and swallowed, users usually only see it in the log file, not as a crash.","solutions":["Update the AMD Adrenalin driver to a version that supports ADL2 switchable graphics on this hardware.","Keep the existing 'if (!IsValid) return;' guard and also early-return when _iGPU is null (no integrated GPU means no switchable graphics).","Stop throwing for a non-zero result: log the code and return, since KillGPUApps is already best-effort and wrapped in try/catch.","Verify Adl2.Load() succeeded and _adlContextHandle is non-zero before calling (IsValid covers this but pair it with the _iGPU null check).","Decode the returned code against known ADL constants (ADL_ERR, ADL_ERR_NOT_SUPPORTED) to log a precise reason."],"exampleFix":"// before\nvar result = ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr);\nif (result != 0)\n    throw new Exception(\"Failed to get switchable graphics applications. Error code: \" + result);\n// after\nvar result = ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr);\nif (result != Adl2.ADL_SUCCESS)\n{\n    Logger.WriteLine($\"ADL2_SwitchableGraphics_Applications_Get failed (code {result}); skipping GPU app cleanup.\");\n    return;\n}","handlingStrategy":"try-catch","validationCode":"// The strongest pre-check available is the public IsValid property plus a switchable-GPU presence check.\nif (!amdGpu.IsValid) return;             // ADL context not created (AmdGpuControl.cs:95)\nif (amdGpu._iGPU is null)   return;       // no integrated GPU => no switchable graphics\n// Note: _iGPU is private; expose a bool HasSwitchableGraphics property if you need this guard outside the class.","typeGuard":null,"tryCatchPattern":"// KillGPUApps already does this — keep it, but stop throwing inside the try:\ntry\n{\n    var result = ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr);\n    if (result != Adl2.ADL_SUCCESS)\n    {\n        Logger.WriteLine($\"KillGPUApps: switchable-graphics query failed (ADL code {result}).\");\n        return;\n    }\n    // ... process appInfoArray ...\n}\ncatch (Exception ex)\n{\n    Logger.WriteLine($\"KillGPUApps: {ex.Message}\");\n}\nfinally\n{\n    if (appInfoPtr != nint.Zero) Marshal.FreeCoTaskMem(appInfoPtr);\n}","preventionTips":["Always gate AMD ADL calls with IsValid (which checks _isReady && _adlContextHandle != nint.Zero).","Add an _iGPU null check before switchable-graphics calls: a single-GPU system legitimately has none.","Prefer logging + early return over throw for non-zero ADL results; these are expected on unsupported drivers and the method is best-effort.","Free the CoTaskMem pointer in a finally (already done) and never use appInfoPtr after a non-zero result.","Keep Adl2.Load() failure paths silent and ensure AmdGpuControl is not constructed at all on non-AMD systems (the constructor returns early at line 72)."],"tags":["amd","adl","gpu","pinvoke","native","windows","driver","switchable-graphics"],"backgroundTag":null,"analyzedSha":"b9ba417f1b822110ce41a1e152031a84bfa6ad80","analyzedAt":"2026-08-13T15:05:32.228Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}