如何检测功能是否在已安装的库中实现?

How to detect if function is implemented in installed library?

我有我的 windows 程序,它使用 windows 系统库(我们将其命名为 "sysLib"),它实现了函数 "libFun1"。我的程序可以是这样的:

#include <sysLib.h>

void myFunction() {
    //some magic here
}

int main() {
    myFunction();
    libFun1();
    return 0;
}

稍后,库得到更新,其中添加了新的 "libFun2" 函数,它完美地完成了我的 "myFunction" 所做的,甚至做得更好。所以我将程序更新为如下所示:

#include <sysLib.h>

int main() {
    libFun2();
    libFun1();
    return 0;
}

我编译它并推送更新给客户端。

但是有一些客户,他们没有最新版本的 windows 并且他们有旧版本的 "sysLib" 没有实现 "libFun2",所以他们的程序不起作用(甚至没有开始)。

我发现,如果我用 "delayimp.lib /DELAYLOAD:sysLib.dll" 编译我的程序,程序现在可以启动,但在调用 "libFun2" 时下降。

我现在想更新我的代码,使其看起来像这样:

#include <sysLib.h>

void myFunction() {
    //some magic here
}

int main() {
    if(/*libFun2 exists*/) {
         libFun2();
    } else {
         myFunction();
    }
    libFun1();
    return 0;
}

如果 "libFun2" 函数存在于库中并围绕它制定逻辑,我如何检测?

I know that in linux is possible to do if(libFun2), but this doesn't work in windows

更新:

我发现,它可以被__try __except组合捕获,但它对我不起作用...

https://docs.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification?view=msvc-170

bool hasExport(LPCSTR mod, LPCSTR func)
{
  HMODULE handle = LoadLibraryA(mod);
  return handle && GetProcAddress(handle, func);
}

...

if (hasExport("syslib", "libfun2"))
  libfun2(); // must be delay loaded
else
  ...

此代码假定您不需要再次卸载库。它也不关心库是否已经加载。如果您需要不同的行为,请使用 GetModuleHandleFreeLibrary

在这种特定情况下,由于您有一个替换函数,您可以改为使用延迟加载挂钩并通过返回回退函数来处理 dliFailGetProc

解决方法很简单:

#include <sysLib.h>
#include <delayimp.h>
int CheckDelayException(int exception_value)
{
    if (exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) ||
        exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND))
    {
        // This example just executes the handler.
        return EXCEPTION_EXECUTE_HANDLER;
    }
    // Don't attempt to handle other errors
    return EXCEPTION_CONTINUE_SEARCH;
}

void myFunction() {
    __try {
         libFun2();
         return;
    } __except (CheckDelayException(GetExceptionCode())) {
         myFunction();
    }
    //some magic here
}

int main() {
    myFunction();
    libFun1();
    return 0;
}

https://docs.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification?view=msvc-170

UPDATE: moved __try into function for better usage in code, if multiple calls are used