dotnet/wpf · error · Win32Exception

Win32Exception(errorCode)

Error message

Win32Exception(errorCode)

What it means

Misc.WrapWin32Exception (or similar helper) maps a Win32 error code to a .NET exception. Codes it knows (1053, 1460) become TimeoutException; all unrecognized Win32 error codes are re-thrown as a generic Win32Exception carrying the original error code. This means the underlying native call failed with an error the UIAutomation proxy layer has no specific mapping for.

Solutions

  1. Inspect the Win32Exception.NativeErrorCode property to identify the actual error and address its root cause (e.g. permissions, missing process).
  2. Run the automation host under an account with the privileges needed for the target window/service.
  3. Verify the target process/service is running and responsive before driving UI Automation.
  4. Catch Win32Exception and branch on NativeErrorCode for codes you care about.
  5. exampleFixPlaceholder

Example fix

// before
var proxy = new ServiceInvokerProxy();
proxy.Start(); // throws Win32Exception(1062)

// after
if (!serviceController.Status.HasFlag(ServiceControllerStatus.Running))
{
    serviceController.Start();
    serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
}
var proxy = new ServiceInvokerProxy();
proxy.Start();
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Environment.UserInteractive && requiresWindowAccess)
    throw new InvalidOperationException("Run in an interactive session for UI automation");

Type guard

static bool IsMappedWin32Error(Win32Exception ex) =>
    ex.NativeErrorCode == 1053 || ex.NativeErrorCode == 1460; // mapped to TimeoutException

Try / catch

try { proxy.Call(); }
catch (Win32Exception ex)
{
    switch (ex.NativeErrorCode)
    {
        case 5: /* handle access denied */ break;
        case 2: /* handle not found */ break;
        default: throw;
    }
}

Prevention

When it happens

Trigger: A native Win32 call made by UIAutomation client-side providers (e.g. SendMessage, service control APIs used to inspect/start a service) fails with an unmapped error code such as ERROR_ACCESS_DENIED (5), ERROR_SERVICE_NOT_ACTIVE (1062), or ERROR_FILE_NOT_FOUND (2), and the code is passed to this helper.

Common situations: Automating services or controls from a process without sufficient privileges; querying a UI Automation element whose backing process/service has died or is unresponsive; running in restricted environments (sessions 0, non-interactive services) where window APIs fail.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/8f7651ef21d9c322. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Misc.cs:1705

                    throw new ElementNotAvailableException();

                case 8:     //    8 ERROR_NOT_ENOUGH_MEMORY         Not enough storage is available to process this command.
                case 14:    //   14 ERROR_OUTOFMEMORY               Not enough storage is available to complete this operation.
                    throw new OutOfMemoryException();

                case 998:   //  998 ERROR_NOACCESS                  Invalid access to memory location.
                case 5:     //    5 ERROR_ACCESS_DENIED
                    throw new InvalidOperationException();

                case 121:   //  121 ERROR_SEM_TIMEOUT               The semaphore timeout period has expired.
                case 258:   //  258 WAIT_TIMEOUT                    The wait operation timed out.
                case 1053:  // 1053 ERROR_SERVICE_REQUEST_TIMEOUT   The service did not respond to the start or control request in a timely fashion.
                case 1460:  // 1460 ERROR_TIMEOUT                   This operation returned because the timeout period expired.
                    throw new TimeoutException();

                default:
                    // Not sure how to map the reset of the error codes so throw generic Win32Exception.
                    throw new Win32Exception(errorCode);
            }
        }

        internal static bool UnhookWinEvent(IntPtr winEventHook)
        {
            // There is no indication in the Windows SDK documentation that UnhookWinEvent()
            // will set an error to be retrieved with GetLastError
            return UnsafeNativeMethods.UnhookWinEvent(winEventHook);
        }

        internal static bool UnionRect(out NativeMethods.Win32Rect rcDst, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
        {
            bool result = SafeNativeMethods.UnionRect(out rcDst, ref rc1, ref rc2);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);

View on GitHub (pinned to 81131a70a4)