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

发布于 2024-12-29 07:42:27 字数 432 浏览 0 评论 0原文

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

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

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

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

I'd like to build an application that invokes CancelIoEx on Windows Vista and newer (where it is supported) and does something else on Windows XP (where it is not).

  1. What happens if I compile the application under Windows 7 but run it under Windows XP? What will happen at runtime? Will I get some sort of load error?

  2. How do I get my application to pick one code path or another (avoiding load errors) depending on what operating system is being used at runtime? Please provide sample code.

UPDATE: Please note that the DLL exists on Windows XP but the function does not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千纸鹤 2025-01-05 07:42:27

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

Yes, an application that references a non-existent DLL export will fail to load.

Adding code to take different paths based on the OS version won't help much, because you'll still have the reference to the non-existent function.

Instead, you need to resolve the reference at run-time.

One option is Delay Load Import (with the /DELAYLOAD linker flag), but I don't think this is supported for the core system DLLs (like kernel32).

The other is to use LoadLibrary and GetProcAddress. The code is something like this, though in reality you'd do the lookup once when your app starts, not each time you call the function.

// 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
}
没企图 2025-01-05 07:42:27

为了在运行时解析符号,您需要使用 LoadLibraryGetProcAddress< /a>:

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

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

pCancelIoEx(h, &lp);

In order to resolve a symbol at runtime, you need to use LoadLibrary and GetProcAddress:

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

In the case that CancelIoEx is not available, you will get NULL back from GetProcAddress. Once you have the pointer (you only need to do the above once), you can call it normally with:

pCancelIoEx(h, &lp);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文