简体   繁体   English

检查是否存在Windows API函数

[英]Checking for existence of Windows API Functions

I am new to Windows programming and I'm trying to discover the best way to check for the existence of Windows Shell API functions. 我是Windows编程的新手,我正在尝试发现检查Windows Shell API函数是否存在的最佳方法。 I want to use some of the new taskbar features in Windows7. 我想在Windows7中使用一些新的任务栏功能。

https://msdn.microsoft.com/en-us/library/dd378460%28VS.85%29.aspx#custom_jump_lists https://msdn.microsoft.com/en-us/library/dd378460%28VS.85%29.aspx#custom_jump_lists

But I still want my program to be usable by previous versions of Windows. 但我仍然希望我的程序可以被以前版本的Windows使用。 Is there an easy way to know if the functions are available to be called in the end users system. 有没有一种简单的方法可以知道这些函数是否可以在最终用户系统中调用。 I'm programming in C++. 我正在用C ++编程。

It depends on the kinds of the functions. 这取决于功能的种类。

For plain (non-COM) functions, the only way is to use LoadLibrary and GetProcAddress . 对于普通(非COM)函数,唯一的方法是使用LoadLibraryGetProcAddress If either fails, you know the OS is missing that function. 如果任何一个失败,您知道操作系统缺少该功能。 Writing those function pointer type declarations for function pointers duplicating existing function signatures can be tedious, though in VC++2010 you can use decltype for that. 为复制现有函数签名的函数指针编写那些函数指针类型声明可能很乏味,但在VC ++ 2010中,您可以使用decltype For example: 例如:

HMODULE user32 = LoadLibraryW(L"user32");
if (user32 != NULL)
{
    auto messageBoxW = reinterpret_cast<decltype(MessageBoxW)*>(GetProcAddress(user32, "MessageBoxW"));
    if (messageBoxW != NULL)
    {
        messageBoxW(HWND_DESKTOP, L"Hello!", NULL, MB_OK);
    }
}

However, many Shell APIs are exposed via COM components and interfaces. 但是,许多Shell API都是通过COM组件和接口公开的。 Those cases are different. 那些情况不同。 Sometimes you need to deal with entirely new components; 有时你需要处理全新的组件; eg IApplicationDestinations is a new interface in Win7, and the coclass that implements it is also new. 例如, IApplicationDestinations是Win7中的一个新接口,实现它的coclass也是新的。 In those cases, you can just do CoCreateInstance , and check the return value for REGDB_E_CLASSNOTREG - this means that such coclass isn't registered on the system (and, effectively, isn't supported). 在这些情况下,您可以只执行CoCreateInstance ,并检查REGDB_E_CLASSNOTREG的返回值 - 这意味着此类coclass未在系统上注册(并且实际上不受支持)。

Sometimes, however, new OS versions introduce new interfaces on existing coclasses. 但是,有时新的操作系统版本会在现有的coclass上引入新的接口。 An example is ITaskbarList3 , new in Win7, but provided on existing coclass that implements ITaskbarList and dates back to Win95. 一个例子是ITaskbarList3 ,Win7中的新增功能,但是在现有的coclass上提供,它实现了ITaskbarList并且可以追溯到Win95。 In those cases, you should first instantiate the coclass for the most basic interface, and then use QueryInterface to obtain new interface versions, and detect that they're not supported by checking return value for E_NOINTERFACE . 在这些情况下,您应该首先为最基本的接口实例化coclass,然后使用QueryInterface获取新的接口版本,并通过检查E_NOINTERFACE返回值来检测它们是否不受支持。

LoadLibrary and GetProcAddress will be your friends. LoadLibraryGetProcAddress将成为你的朋友。

Also, check out this tutorial . 另外,请查看本教程

I believe MSDN is your best bet for this. 我相信MSDN是你最好的选择。 Every MSDN page for a function's documentation contains a section in the end which states that which version of Windows support this function. 函数文档的每个MSDN页面都包含最后一节,说明哪个版本的Windows支持此功能。

As an example, Check the doumentation of GetModuleHandle . 例如,检查GetModuleHandle的doumentation。 This contains a section named Requirements under which there is a field Minimum Supported Client and Minimum Supported Server . 其中包含名为Requirements的部分,其中包含字段Minimum Supported ClientMinimum Supported Server

However, if you want to check for the existence of functions dynamically, then you can do this through LoadLibrary and GetProcAddress . 但是,如果要动态检查函数是否存在,则可以通过LoadLibraryGetProcAddress执行此操作。

I disagree with the currrent solutions. 我不同意当前的解决方案。 You'll end up with quite a bit of unreadable code. 你最终会得到相当多的不可读的代码。

A nicer alternative is to wrap the functionality in a custom Windows 7-only DLL. 一个更好的选择是将功能包装在自定义的Windows 7专用DLL中。 For other systems, provide another version of the DLL that implements the same functions. 对于其他系统,请提供实现相同功能的DLL的另一个版本。 This can often be a no-op. 这通常可以是无操作。 Eg a function to set the taskbar extensions would be a no-op on older Windows versions. 例如,设置任务栏扩展的功能将是旧版Windows上的无操作。

The dynamic switching between these DLLs is done by using the delay-load feature of MSVC. 这些DLL之间的动态切换是通过使用MSVC的延迟加载功能完成的。 You can use a custom hook in your EXE to pick the correct DLL version when the first function in your DLL is called, at which time you know whether you're running on Windows 7. 当调用DLL中的第一个函数时,您可以在EXE中使用自定义钩子来选择正确的DLL版本,此时您就知道自己是否在Windows 7上运行。

您应该使用LoadLibrary和GetProcAddress来动态加载和调用新功能。

Yes you can always check for the existence of function within a library at runtime and take suitable actions. 是的,您始终可以在运行时检查库中是否存在函数,并采取适当的操作。 Check the LoadLibrary and GetProcAddress APIs. 检查LoadLibrary和GetProcAddress API。 http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx

If you want to find out at compile time so as to get a build break if the function is not available on the OS you are targetting (eg Win 95), then you can define some macros, documented here :NTDDI_VERSION, _WIN32_WINNT, WINVER. 如果你想在编译时发现如果函数在你正在使用的操作系统上不可用(例如Win 95),那么就可以找到一个构建中断,然后你可以定义一些宏, 这里记录 :NTDDI_VERSION,_WIN32_WINNT,WINVER。

If you want your app to work fine when the functionality is not available (eg JumpLists on OSes older than Win7), then you should do combination of LoadLibrary/GetProcAddress to figure out whether the function you are looking for is available. 如果您希望应用程序在功能不可用时正常工作(例如,早于Win7的操作系统上的JumpLists),那么您应该组合使用LoadLibrary / GetProcAddress来确定您要查找的功能是否可用。

Use LoadLibarary to get library handle and GerProcAddress to get pointer to a function. 使用LoadLibarary获取库句柄,使用GerProcAddress获取指向函数的指针。 For those functions that are not supported by current OS you will get ERROR_CALL_NOT_IMPLEMENTED error from GetLastError . 对于当前操作系统不支持的那些函数,您将从GetLastError获得ERROR_CALL_NOT_IMPLEMENTED错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM