【问题标题】:How to conditionally execute function if operating system supports it?如果操作系统支持,如何有条件地执行函数?
【发布时间】:2012-01-26 18:25:25
【问题描述】:

我想构建一个应用程序,它在 Windows Vista 和更新版本(支持)上调用 CancelIoEx,并在 Windows XP(不支持)上执行其他操作。

  1. 如果我在 Windows 7 下编译应用程序但在 Windows XP 下运行它会发生什么?运行时会发生什么?我会收到某种加载错误吗?

  2. 如何让我的应用程序根据运行时使用的操作系统选择一个或另一个代码路径(避免加载错误)?请提供示例代码。

更新:请注意,DLL 存在于 Windows XP 上,但该函数不存在。

【问题讨论】:

标签: windows backwards-compatibility


【解决方案1】:

是的,引用不存在的 DLL 导出的应用程序将无法加载。

添加代码以根据操作系统版本采用不同的路径并没有太大帮助,因为您仍然会引用不存在的函数。

相反,您需要在运行时解析引用。

一个选项是延迟加载导入(带有 /DELAYLOAD 链接器标志),但我认为核心系统 DLL(如 kernel32)不支持此功能。

另一种是使用LoadLibraryGetProcAddress。代码是这样的,但实际上您会在应用启动时进行一次查找,而不是每次调用该函数时。

// Declare type of pointer to CancelIoEx function
typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);

// Load module; won't fail because it's already imported
HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
// Look up function address
CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
// Do something with it
if (pCancelIoEx)
{
    // Function exists so call it
    pCancelIoEx(hMyFile, pMyOverlapped);
}
else
{
    // Function doesn't exist
}

【讨论】:

    【解决方案2】:

    为了在运行时解析符号,你需要使用LoadLibraryGetProcAddress

    HMODULE kernel32 = LoadLibrary("kernel32.dll");
    BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED) = GetProcAddress(kernel32, "CancelIoEx");
    

    CancelIoEx不可用的情况下,您将从GetProcAddress获得NULL。一旦你有了指针(你只需要做一次上面的事情),你就可以正常调用它了:

    pCancelIoEx(h, &lp);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多