From 297bbff5cf57ad9b8c088b2359728c2c773120ec Mon Sep 17 00:00:00 2001 From: Nick Babcock Date: Tue, 9 Jul 2019 05:59:10 -0500 Subject: [PATCH] Prefer load nvml from standard search order (#97) Currently it is assumed that `nvml.dll` is located in ``` %ProgramW6432%\NVIDIA Corporation\NVSMI\nvml.dll ``` Not everyone has it installed there. Those that have the nvidia drivers installed through windows updates will have it in in `%WINDIR%\system32\nvml.dll` and won't have anything under the "NVSMI" directory. Instead of hard coding `%WINDIR%\system32\nvml.dll` as a search location, we can load whatever `nvml.dll` appears first in the search order: ```csharp LoadLibrary("nvml.dll") ``` From [Standard Search Order for Desktop Applications](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications): > 1. The directory from which the application loaded. > 1. The system directory. Use the GetSystemDirectory function to get the path of this directory. > 1. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. > 1. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory. > 1. The current directory. > 1. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path. `%WINDIR%\system32` is the system directory and thus `nvml.dll` is loaded. This will also allow those interested to override the `nvml.dll` by placing their own in the current directory as LibreHM without effecting a system installation. Only if there is no `nvml.dll` in the search space does LibreHM fallback to searching program files. This may technically be a breaking change for those that have `nvml.dll` in both the search space (like `%WINDIR%\system32\nvml.dll`) and `%ProgramW6432%\NVIDIA Corporation\NVSMI\nvml.dll` and those files differ. I don't suspect this to be a common occurrence. If this is expected to be a common occurrence I can switch the logic such that program files is checked before the standard search space, though this would make it so one couldn't override the program files `nvml.dll`. Tested it and works great so far! --- Hardware/Nvidia/NVML.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Hardware/Nvidia/NVML.cs b/Hardware/Nvidia/NVML.cs index 0514daa..e9fcd48 100644 --- a/Hardware/Nvidia/NVML.cs +++ b/Hardware/Nvidia/NVML.cs @@ -38,10 +38,21 @@ namespace OpenHardwareMonitor.Hardware.Nvidia { } } else if (IsNvmlCompatibleWindowsVersion()) { - var programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); - var dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI\nvml.dll"); + // Attempt to load the Nvidia Management Library from the + // windows standard search order for applications. This will + // help installations that either have the library in + // %windir%/system32 or provide their own library + windowsDll = LoadLibrary("nvml.dll"); - windowsDll = LoadLibrary(dllPath); + // If there is no dll in the path, then attempt to load it + // from program files + if (windowsDll == IntPtr.Zero) + { + var programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); + var dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI\nvml.dll"); + + windowsDll = LoadLibrary(dllPath); + } if (windowsDll == IntPtr.Zero) return;