我想在Windows Vista及更新版本(支持它)上构建一个调用CancelIoEx的应用程序,并在Windows XP上执行其他操作(不支持)。
如果我在Windows 7下编译应用程序但在Windows XP下运行它会怎样?运行时会发生什么?我会遇到某种负载错误吗?
如何让我的应用程序选择一个或另一个代码路径(避免加载错误),具体取决于运行时使用的操作系统?请提供示例代码。
更新:请注意,Windows XP上存在该DLL,但该功能不存在。
答案 0 :(得分:2)
是的,引用不存在的DLL导出的应用程序将无法加载。
添加代码以根据操作系统版本采用不同的路径将无济于事,因为您仍然可以参考不存在的功能。
相反,您需要在运行时解析引用。
一个选项是延迟加载导入(带有/DELAYLOAD
链接器标志),但我不认为核心系统DLL(如kernel32)支持这种做法。
另一种方法是使用LoadLibrary
和GetProcAddress
。代码是这样的,但实际上你在应用程序启动时会进行一次查找,而不是每次调用函数时都会进行查找。
// 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)
要在运行时解析符号,您需要使用LoadLibrary
和GetProcAddress
:
HMODULE kernel32 = LoadLibrary("kernel32.dll");
BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED) = GetProcAddress(kernel32, "CancelIoEx");
如果CancelIoEx
不可用,您将从NULL
返回GetProcAddress
。一旦你有了指针(你只需要执行上面的一次),你可以用:
pCancelIoEx(h, &lp);