如何强制Windows.h在Visual Studio中静态链接而不是动态链接?

How can i force the Windows.h to be linked statically instead of dynamically in visual studio?

本文关键字:链接 动态 静态 Windows 何强制 Studio Visual      更新时间:2023-10-16

如何强制链接器静态链接到Windows.h,以便Windows库的所有功能都进入我的可执行文件?

我希望像VirtualAllocEx,OpenProcess这样的API调用,以及其他API调用,如写入另一个进程的内存等和CreateRemoteThread(基本上是所有的通信API调用和内存分配调用(在我的可执行文件中,所以我不必使用Windows.h,所以基本上我的IAT不会包含这些功能,实现这一点的最佳方法是什么?

你不能。

这些东西是操作系统的一部分。

操作系统有权执行您自己的代码不执行的操作。

此外,您的操作系统的实现对于该版本的操作系统是正确的。

这是一件好事。您不希望静态链接操作系统的 API 实现。

头文件Windows.h 仅提供允许您调用它们的声明。

我在MS Windows操作系统下的评论中说过,动态库具有一些与静态库代码无关的特征。让我们尝试以非常简单的方式解释:

首先,DLL独立于当前可执行文件加载,并直接从OS模块加载函数,作为单独的对象,其代码内存被映射在当前进程内存中,但保留以映射到不同的进程中。

在加载过程中,加载程序会创建不同的内存区域,这些内存区域对于单个进程是唯一的,也可以在进程之间共享,也可以是 DLL 内部函数专用的。

共享区域允许创建互斥锁,信号量和内核所需的任何数据,以仲裁多任务环境和资源共享。

相反,静态库仅在当前进程中加载,代码段与用户程序代码段放在一起,并且数据段以相同的方式添加到当前可执行数据空间中。

由于这些原因以及更多原因,您无法将任何系统库函数静态链接到可执行文件


使用 CRT 库进行静态和动态链接的简单实验。

创建一个主程序,在其中打开文件:

#include <stdio.h>
extern void DllReadRoutine(FILE *);
int main(int argc, char *argv[])
{
FILE *fp = fopen("Myfile.txt", "r");
//Diagnostic omitted to keep it simple
DllReadRoutine(fp);    //Pass the file pointer to the external DLL function
fclose(fp);
return 0;
}

现在创建 DLL(我们省略 DLL 条目(:

#include <stdio.h>
void DllReadRoutine(FILE *fp);
int main(int argc, char *argv[])
{
int c;
while ((c=fgetc(pFile)) != EOF)
{
putchar(c);
}
}

然后编译第一次静态链接CRT的两个(在 MSVC 上使用/MT(,第二次动态编译链接 CRT(在 MSVC 上使用/MD(。

在第一种情况下,DLL 函数将失败,因为到 CRT 的静态链接会创建与主可执行文件本地表不兼容的本地打开文件表。结果是崩溃。

在第二种情况下,内部 CRT 数据(作为打开的文件表(是在可执行和 DLL 访问的共享区域中创建的。在这种情况下,代码将顺利运行。

我想你可能误解了静态链接的过程。 Windows.h 头文件包含各种类型的活动的声明,例如函数调用。 请注意,这些是声明,而不是函数本身的二进制实现。 看看 ShellExecuteA 文档。 滚动到文档末尾,您将看到如下所示的"要求"部分:

要求

Minimum supported client Windows XP [desktop apps only] 
Minimum supported server Windows 2000 Server [desktop apps only] 
Target Platform Windows Header shellapi.h 
Library Shell32.lib 
DLL Shell32.dll (version 3.51 or later)

Windows.h包括shellapi.h(Target Platform Windows Header(。 Shellapi.h包含ShellExecuteA(我们在文档中查找的函数(的声明。 本节还告诉您包含函数二进制实现的库,在本例中为 Shell32.lib。 如果您知道函数声明及其二进制实现的位置,则可以链接它。 链接器仅将(函数(名称与链接时可用的(实现(名称匹配。 在 Windows 上,您应该能够使用 lib 文件静态链接,或使用 dll 文件动态链接。 如果静态链接,则将 lib 文件中的二进制实现包含在可执行文件中。 如果 MS 在您使用的函数中修复了 but,则除非您重新编译,否则您不会得到该修复。 如果动态链接(链接到 dll(,则可执行文件将更小,并且更包含将来的 MS 更改。