Skip to content

Fix onnxruntime search dll path.#689

Merged
chinazhangchao merged 2 commits into
mainfrom
chao/fixdllpath
May 21, 2026
Merged

Fix onnxruntime search dll path.#689
chinazhangchao merged 2 commits into
mainfrom
chao/fixdllpath

Conversation

@chinazhangchao
Copy link
Copy Markdown
Contributor

@chinazhangchao chinazhangchao commented May 21, 2026

Windows ships C:\Windows\System32\onnxruntime.dll (older API version) as part of the system WindowsML component.
When WinML EP plugin DLLs are loaded (via EpCatalog), they import "onnxruntime.dll" by base name and the loader binds them to the system copy, producing "The requested API version [N] is not available" errors.
Loading the wheel-bundled DLL by full path first makes later base-name imports resolve to the already-loaded module.

@chinazhangchao chinazhangchao changed the title fix onnxruntime search dll path Fix onnxruntime search dll path. May 21, 2026
@chinazhangchao chinazhangchao marked this pull request as ready for review May 21, 2026 02:32
@chinazhangchao chinazhangchao requested a review from a team as a code owner May 21, 2026 02:32
Copy link
Copy Markdown
Contributor

@xieofxie xieofxie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will it slow much? do we need to find the exact place before ort is loaded?

@chinazhangchao
Copy link
Copy Markdown
Contributor Author

will it slow much? do we need to find the exact place before ort is loaded?

Didn't feel slow. Almost the same.

timenick

This comment was marked as outdated.

timenick

This comment was marked as outdated.

timenick

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator

@timenick timenick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: missing regression coverage for the DLL preload mechanism.

Comment thread src/winml/modelkit/__init__.py
@chinazhangchao chinazhangchao enabled auto-merge (squash) May 21, 2026 02:51
@chinazhangchao chinazhangchao merged commit ab1bbca into main May 21, 2026
9 checks passed
@chinazhangchao chinazhangchao deleted the chao/fixdllpath branch May 21, 2026 02:56
@tezheng
Copy link
Copy Markdown
Collaborator

tezheng commented May 21, 2026

Do we have proof that "C:\Windows\System32\onnxruntime.dll" is indeed loaded? how can I repro if yest?

@tezheng
Copy link
Copy Markdown
Collaborator

tezheng commented May 21, 2026

At least we should try this first, and see which DLLs get loaded

import os, ctypes, onnxruntime as ort
from ctypes import wintypes

print("ort version:", ort.__version__)
print("ort package:", ort.__file__)
capi = os.path.join(os.path.dirname(ort.__file__), "capi")
for name in ("onnxruntime.dll", "onnxruntime_pybind11_state.pyd", "onnxruntime_providers_shared.dll", "DirectML.dll"):
    p = os.path.join(capi, name)
    print(f"  {'OK ' if os.path.isfile(p) else 'NO '} {p}")

k32 = ctypes.WinDLL("kernel32")
k32.GetCurrentProcess.restype = wintypes.HANDLE

psapi = ctypes.WinDLL("psapi")
psapi.EnumProcessModules.argtypes = [wintypes.HANDLE, ctypes.POINTER(ctypes.c_void_p), wintypes.DWORD, ctypes.POINTER(wintypes.DWORD)]
psapi.EnumProcessModules.restype = wintypes.BOOL
psapi.GetModuleFileNameExW.argtypes = [wintypes.HANDLE, ctypes.c_void_p, wintypes.LPWSTR, wintypes.DWORD]

mods = (ctypes.c_void_p * 4096)(); need = wintypes.DWORD()
psapi.EnumProcessModules(k32.GetCurrentProcess(), mods, ctypes.sizeof(mods), ctypes.byref(need))
print("--- onnxruntime* modules currently mapped in process ---")
for i in range(need.value // ctypes.sizeof(ctypes.c_void_p)):
    buf = ctypes.create_unicode_buffer(32768)
    psapi.GetModuleFileNameExW(k32.GetCurrentProcess(), mods[i], buf, len(buf))
    if "onnxruntime" in os.path.basename(buf.value).lower():
        print(" ", buf.value)

@xieofxie
Copy link
Copy Markdown
Contributor

Do we have proof that "C:\Windows\System32\onnxruntime.dll" is indeed loaded? how can I repro if yest?

yes, I have tested this both by process explorer and also log show it
image

timenick added a commit that referenced this pull request May 22, 2026
- Document that _IMAGE_FILE_MACHINE_TO_NAME is intentionally limited to
  the host architectures Windows 11 ships on (no 32-bit ARM, no IA64);
  unmapped values fall through to None and log at debug level.
- Log ctypes.get_last_error() when IsWow64Process2 returns 0 so a
  regression does not silently fall back to platform.machine().
- Hoist kernel32 + IsWow64Process2 to module scope, gated by
  sys.platform == "win32", so LoadLibrary runs once per process and
  non-Windows callers don't hit a ctypes.WinDLL error path.
- Add an explicit `if sys.platform != "win32": return None` guard in
  _get_windows_native_machine to match the pattern used in
  _preload_bundled_onnxruntime_dll (#689).
- Split the raw Win32 query (_query_native_machine_via_win32) from the
  name mapping (_get_windows_native_machine) and parametrize tests over
  IMAGE_FILE_MACHINE_* integers so a rename of "ARM64" → "Arm64" in the
  table fails the test instead of silently shipping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants