6

我是 Windows 编程新手,我正在尝试寻找检查 Windows Shell API 函数是否存在的最佳方法。我想在 Windows7 中使用一些新的任务栏功能。

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

但是我仍然希望我的程序可以被以前版本的 Windows 使用。是否有一种简单的方法可以知道这些函数是否可以在最终用户系统中调用。我正在用 C++ 编程。

4

8 回答 8

11

这取决于函数的种类。

对于普通(非 COM)函数,唯一的方法是使用LoadLibraryand GetProcAddress。如果其中任何一个失败,您就知道操作系统缺少该功能。为复制现有函数签名的函数指针编写这些函数指针类型声明可能很乏味,尽管在 VC++2010 中您可以使用decltype它。例如:

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);
    }
}

但是,许多 Shell API 都是通过 COM 组件和接口公开的。这些情况是不同的。有时您需要处理全新的组件;egIApplicationDestinations是Win7中的一个新接口,实现它的coclass也是新的。在这些情况下,您只需执行CoCreateInstance, 并检查返回值REGDB_E_CLASSNOTREG- 这意味着此类 coclass 未在系统上注册(并且实际上不支持)。

然而,有时新的操作系统版本会在现有的 coclass 上引入新的接口。一个示例是ITaskbarList3Win7 中的新示例,但在现有的 coclass 上提供,实现ITaskbarList并可以追溯到 Win95。在这些情况下,您应该首先为最基本的接口实例化 coclass,然后使用它QueryInterface来获取新的接口版本,并通过检查返回值来检测它们不受支持E_NOINTERFACE

于 2009-07-15T04:55:51.453 回答
3

LoadLibraryGetProcAddress将成为您的朋友。

另外,请查看本教程

于 2009-07-15T04:05:24.597 回答
2

我相信 MSDN 是您最好的选择。功能文档的每个 MSDN 页面最后都包含一个部分,说明哪个版本的 Windows 支持此功能。

例如,检查GetModuleHandle的文档。这包含一个名为“要求”的部分,其中有一个字段Minimum Supported ClientMinimum Supported Server

但是,如果要动态检查函数是否存在,则可以通过LoadLibraryGetProcAddress执行此操作。

于 2009-07-15T04:05:07.657 回答
1

我不同意当前的解决方案。你最终会得到相当多的不可读的代码。

一个更好的选择是将功能包装在自定义的仅限 Windows 7 的 DLL 中。对于其他系统,请提供实现相同功能的另一个版本的 DLL。这通常是无操作的。例如,设置任务栏扩展的功能在旧 Windows 版本上是无操作的。

这些 DLL 之间的动态切换是通过使用 MSVC 的延迟加载功能完成的。当调用 DLL 中的第一个函数时,您可以在 EXE 中使用自定义挂钩来选择正确的 DLL 版本,此时您知道您是否在 Windows 7 上运行。

于 2009-07-15T11:34:03.820 回答
0

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

于 2009-07-15T04:05:04.070 回答
0

是的,您始终可以在运行时检查库中是否存在函数并采取适当的措施。检查 LoadLibrary 和 GetProcAddress API。 http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx

于 2009-07-15T04:05:40.370 回答
0

如果您想在编译时找出该函数在您的目标操作系统(例如 Win 95)上不可用的情况下获得构建中断,那么您可以定义一些宏,记录在此处:NTDDI_VERSION、_WIN32_WINNT、WINVER。

如果您希望您的应用程序在功能不可用时正常工作(例如 Win7 之前的操作系统上的 JumpLists),那么您应该结合使用 LoadLibrary/GetProcAddress 来确定您正在寻找的功能是否可用。

于 2009-07-15T04:07:32.783 回答
0

用于LoadLibarary获取库句柄并GerProcAddress获取指向函数的指针。对于当前操作系统不支持的那些功能,您ERROR_CALL_NOT_IMPLEMENTED将从GetLastError.

于 2009-07-15T04:49:38.050 回答