如何基于操作系统版本导入DLL,兼容旧系统避免GetDpiForWindow报错
解决方案
针对你的问题,有两种可靠的处理方式,既能兼容旧系统,又能在符合要求的系统上正常调用API:
方案一:提前检查Windows版本
先判断当前系统是否满足GetDpiForWindow的最低要求(Windows 10 1607,对应内部版本号14393),如果不满足则直接返回默认DPI缩放因子1.0(对应96DPI)。
修改后的代码如下:
public static class WindowUtil { [DllImport("user32.dll")] private static extern int GetDpiForWindow(IntPtr hWnd); public static double GetWindowDPIFactor(IntPtr winhandle) { if (winhandle == IntPtr.Zero) { return 1; } // 检查系统是否为Windows 10 1607及以上版本 var osVersion = Environment.OSVersion.Version; if (osVersion.Major >= 10 && osVersion.Build >= 14393) { return (double)GetDpiForWindow(winhandle) / 96; } else { // 旧系统返回默认DPI缩放因子 return 1.0; } } }
方案二:捕获API调用异常
如果不想依赖版本检查,可以在调用GetDpiForWindow时捕获EntryPointNotFoundException(当系统找不到该API入口点时抛出),捕获到异常后返回默认值。这种方式更灵活,无需硬编码版本号。
修改后的代码如下:
public static class WindowUtil { [DllImport("user32.dll", SetLastError = true)] private static extern int GetDpiForWindow(IntPtr hWnd); public static double GetWindowDPIFactor(IntPtr winhandle) { if (winhandle == IntPtr.Zero) { return 1; } try { return (double)GetDpiForWindow(winhandle) / 96; } catch (EntryPointNotFoundException) { // 系统不支持该API,返回默认DPI缩放因子 return 1.0; } } }
补充说明
- 方案一的版本检查更高效,避免了异常捕获的性能开销;
- 方案二更鲁棒,即使未来系统版本号规则变化,只要API存在就能正常调用,不存在就 fallback 到默认值;
- 两种方案都能解决Win7等旧系统中类实例化或API调用时的异常问题。
内容的提问来源于stack exchange,提问作者mrpiggy
相关产品推荐
相关产品推荐

