c#如何使用新版本的Helper API
由于Windows 10已发布,因此现在不可靠(此函数报告Windows 8 for Windows 10),因此我尝试在我的C#应用程序中使用新版本的Helper API函数。是的 如果这只是我的DLL导入的一个问题,我很抱歉,但是我尝试引入这些新方法来正确检测操作系统c#如何使用新版本的Helper API,c#,c++,.net,windows,dllimport,C#,C++,.net,Windows,Dllimport,由于Windows 10已发布,因此现在不可靠(此函数报告Windows 8 for Windows 10),因此我尝试在我的C#应用程序中使用新版本的Helper API函数。是的 如果这只是我的DLL导入的一个问题,我很抱歉,但是我尝试引入这些新方法来正确检测操作系统 [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool IsWindows7OrGreater(); [DllImport(
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows7OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows8OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows8Point1OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows10OrGreater();
无论何时调用这些方法,我都会得到:
异常为:EntryPointNotFoundException-在DLL“kernel32.DLL”中找不到名为“IsWindows7OrCreater”的入口点
我做错什么了吗?有人有什么想法吗?谢谢你的帮助
编辑:请查看已接受的答案,并查看将这些方法移植到C#上的良好开端。不幸的是,这有点复杂。“函数”实际上是
VersionHelpers.h
中定义的宏
如果你想一想,那是唯一的办法——他们不能追溯到旧的Windows版本中添加功能
您必须将宏移植到C#。VersionHelpers函数不会在任何dll中导出,而是在VersionHelpers.h文件中定义, 为了利用C代码中的功能,您可以从头文件复制该功能 导入这两个功能:
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfo([In] ref OsVersionInfoEx lpVersionInfo, uint dwTypeMask, ulong dwlConditionMask);
定义以下结构:
[StructLayout(LayoutKind.Sequential)]
struct OsVersionInfoEx
{
public uint OSVersionInfoSize;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string CSDVersion;
public ushort ServicePackMajor;
public ushort ServicePackMinor;
public ushort SuiteMask;
public byte ProductType;
public byte Reserved;
}
然后使用以下功能:
static bool IsWindowsVersionOrGreater(uint majorVersion, uint minorVersion, ushort servicePackMajor)
{
OsVersionInfoEx osvi = new OsVersionInfoEx();
osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
osvi.MajorVersion = majorVersion;
osvi.MinorVersion = minorVersion;
osvi.ServicePackMajor = servicePackMajor;
// These constants initialized with corresponding definitions in
// winnt.h (part of Windows SDK)
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const byte VER_GREATER_EQUAL = 3;
ulong versionOrGreaterMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
uint versionOrGreaterTypeMask = VER_MAJORVERSION |VER_MINORVERSION | VER_SERVICEPACKMAJOR;
return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask, versionOrGreaterMask);
}您的代码必须有一个包含
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of all Windows versions that this application is designed to work with. Windows will automatically select the most compatible environment.-->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
</application>
</compatibility>
无需使用互操作/非托管代码或添加目标清单
正如本文和文档中已经提到的,Windows 8.1的行为/可用性发生了变化。(对于.NET<5.0,反映了这一点) 这同样适用于函数。如果您使用.NET 5或Core,您可以再次使用,顺便说一句,我的核心项目同事排除了使用with指令查询WMI的代码,因为它没有为Core编译) 另一种方法是将其他答案中的PInvoke与这些函数的Windows SDK对应项(来自ntdll.dll)一起使用
- (可以使用a结构,这是非SDK对应项的别名。只需确保在调用之前设置dwOSVersionInfoSize,以便它知道您引用的是哪一个。)
啊,我明白了。这是有道理的。非常感谢您的快速回复。下面是我发现的一个代码项目,它为在上面移植这些代码提供了一个良好的开端:@Krumelur一个例子可能会对这个答案有很大帮助。据报道,VerifyVersionInfo在Windows 10中不受欢迎。Windows 10中是否还有任何未弃用的API可以提供操作系统版本?@FrancisLitterio他使用的是
VerifyVersionInfo
,而不是VerifyVersionInfo
,但即便如此,他也包括了帮助函数,而且,仅仅因为某些东西被弃用并不意味着它不起作用-它通常意味着微软已经取代了它(即包括这些帮助函数)。这两个都应该仍然可以运行,但是您想使用上面的IsWindows10OrGreater()
函数。我们能够在没有清单的情况下在Windows 7上运行这些函数,因此我认为如果它可以在7上运行这些函数,那么如果没有清单,它在10上运行时不会也出现任何问题吗?它不应该已经有了相同的VerifyVersionInfo()
函数,只需要将10的数字作为ushort wMajorVersion
发送到isWindowsVersionOrCreater()
就可以了,看看当传递给它时它是否得到了10?很好,运行没有任何障碍或清单文件(至少在Windows 7上)!
using System;
using System.Runtime.InteropServices;
namespace VersionHelper
{
public static class VersionHelper
{
const byte VER_EQUAL = 1;
const byte VER_GREATER = 2;
const byte VER_GREATER_EQUAL = 3;
const byte VER_LESS = 4;
const byte VER_LESS_EQUAL = 5;
const byte VER_AND = 6;
const byte VER_OR = 7;
const byte VER_CONDITION_MASK = 7;
const byte VER_NUM_BITS_PER_CONDITION_MASK = 3;
//
// RtlVerifyVersionInfo() type mask bits
//
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_BUILDNUMBER = 0x0000004;
const uint VER_PLATFORMID = 0x0000008;
const uint VER_SERVICEPACKMINOR = 0x0000010;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const uint VER_SUITENAME = 0x0000040;
const uint VER_PRODUCT_TYPE = 0x0000080;
// wProductType
// Any additional information about the system.This member can be one of the following values.
const byte VER_NT_DOMAIN_CONTROLLER = 0x0000002;
const byte VER_NT_SERVER = 0x0000003;
const byte VER_NT_WORKSTATION = 0x0000001;
//
// _WIN32_WINNT version constants
//
const ushort _WIN32_WINNT_NT4 = 0x0400;
const ushort _WIN32_WINNT_WIN2K = 0x0500;
const ushort _WIN32_WINNT_WINXP = 0x0501;
const ushort _WIN32_WINNT_WS03 = 0x0502;
const ushort _WIN32_WINNT_WIN6 = 0x0600;
const ushort _WIN32_WINNT_VISTA = 0x0600;
const ushort _WIN32_WINNT_WS08 = 0x0600;
const ushort _WIN32_WINNT_LONGHORN = 0x0600;
const ushort _WIN32_WINNT_WIN7 = 0x0601;
const ushort _WIN32_WINNT_WIN8 = 0x0602;
const ushort _WIN32_WINNT_WINBLUE = 0x0603;
const ushort _WIN32_WINNT_WINTHRESHOLD = 0x0A00; /* ABRACADABRA_THRESHOLD*/
const ushort _WIN32_WINNT_WIN10 = 0x0A00; /* ABRACADABRA_THRESHOLD*/
const bool FALSE = false;
static byte LOBYTE(ushort w)
{
return ((byte)(w & 0xff));
}
static byte HIBYTE(ushort w)
{
return ((byte)(w >> 8 & 0xff));
}
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong ConditionMask, uint TypeMask, byte Condition );
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfoW(ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct OSVERSIONINFOEXW
{
public int dwOSVersionInfoSize;
public int dwMajorVersion;
public int dwMinorVersion;
public int dwBuildNumber;
public int dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion;
public UInt16 wServicePackMajor;
public UInt16 wServicePackMinor;
public UInt16 wSuiteMask;
public byte wProductType;
public byte wReserved;
}
public static bool
IsWindowsVersionOrGreater(ushort wMajorVersion, ushort wMinorVersion, ushort wServicePackMajor)
{
var osvi = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEXW))
};
var dwlConditionMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(ref osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
public static bool
IsWindowsXPOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
}
public static bool
IsWindowsXPSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
}
public static bool
IsWindowsXPSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
}
public static bool
IsWindowsXPSP3OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
}
public static bool
IsWindowsVistaOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
}
public static bool
IsWindowsVistaSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
}
public static bool
IsWindowsVistaSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}
public static bool
IsWindows7OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
}
public static bool
IsWindows7SP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
}
public static bool
IsWindows8OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
}
public static bool
IsWindows8Point1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
}
public static bool
IsWindowsThresholdOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0);
}
public static bool
IsWindows10OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0);
}
public static bool
IsWindowsServer()
{
var osvi = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
wProductType = VER_NT_WORKSTATION
};
var dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
return !VerifyVersionInfoW( ref osvi, VER_PRODUCT_TYPE, dwlConditionMask);
}
}
}
[DllImport("kernel32.dll")]
private static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);
[DllImport("ntdll.dll")]
private static extern uint RtlGetVersion(ref OSVERSIONINFOW lpVersionInformation);
[DllImport("ntdll.dll")]
private static extern uint RtlGetVersion(ref OSVERSIONINFOEXW lpVersionInformation);
[DllImport("ntdll.dll")]
private static extern bool RtlVerifyVersionInfo([In] ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);