如果操作系统支持,如何有条件地执行功能?

时间:2012-01-26 18:25:26

标签: windows backwards-compatibility

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

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

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

  3. 更新:请注意,Windows XP上存在该DLL,但该功能不存在。

2 个答案:

答案 0 :(得分:2)

是的,引用不存在的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
}

答案 1 :(得分:1)

要在运行时解析符号,您需要使用LoadLibraryGetProcAddress

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

如果CancelIoEx不可用,您将从NULL返回GetProcAddress。一旦你有了指针(你只需要执行上面的一次),你可以用:

正常调用它
pCancelIoEx(h, &lp);