如何将程序的执行文件和静态加载动态库放在不同的目录

原创 2016年06月01日 17:46:06

一般windows程序的exe和dll需要放在同一个目录,静态加载才不会报错,否则需要修改path环境变量,将所有没有和exe放在同一目录的dll的路径加在path环境变量中。

有没有一种方法不去手动修改path环境变量并且可以将exe和dll随心所欲的改变路径呢?我没有发现,但是我们可以将修改环境变量这件事情交给我们的程序本身来处理,那么从现象上来看就是我们不需要修改环境变量而可以将dll从exe目录中拿走,放到你所希望的位置。

其实实现这个想法不难,反而很简单。

假设我们的exe模块叫“A.exe”,依赖“B.dll”和“C.dll",你希望将“B.dll”放在”./B“目录下,而把"C.dll"放在”./C"目录下。我们的处理思路是,再写一个壳程序,假如说叫“E.exe”,“E.exe”除了系统的库之外不依赖任何自己开发或者第三方的库,那么理论上它放在哪里都是可以启动的。

在“E.exe”的代码中,我们设置环境变量,将“B.dll”和“C.dll"所在的路径加到Path环境变量中,并启动“A.exe”,那么在启动“A.exe”时就能自然而然加载到所依赖的库了。在启动“A.exe”完成之后将Path环境变量还原。所以在启动“A.exe”前后,Path环境变量看似并没有改变,但是我们棘手的问题却解决了。

当然为了避免用户手动去点击“A.exe”弹出错误窗口的不好的用户体验,可以将“A.exe”编译成dll,提供一个能够启动程序功能的导出API,在“E.exe”中动态加载“A.dll”并调用导出API,达到启动程序的目的。

但是exe重编程dll可能引起的问题有很多,比如MFC中就会存在很多的坑,那么还有一种简单的思路,那就是直接改名,将编译完成的“A.exe”直接改名成“A.dll”,然后在“E.exe”中通过CreateProcess的方式启动“A.dll”,然后就没“E.exe”什么事,可以退出歇着去了。

下面是我自己使用的“E.exe”的实现代码,相当简单,值得注意的是,“E.exe”运行时最好不要出现窗口,不然会很难看,至于怎么让程序不出现窗口,应该网上可以找到很多教程。

//E.exe Main.cpp

class ChangePath
{
public:
	ChangePath()
	{
		size_t len = 0;
		char sz[2048] = {};
		getenv_s(&len, sz,2048,"PATH");
		m_szPath = sz;
		std::string szAddPath = "";//你的dll所在的绝对路径,使用“;”隔开
		std::string szNewPath = m_szPath + ";";
		szNewPath += szAddPath;
		_putenv_s("PATH",szNewPath.c_str());
	}
	~ChangePath()
	{
		_putenv_s("PATH",m_szPath.c_str());
	}
private:
	std::string m_szPath;
};

ChangePath changepath;//RAII修改Path环境变量

void LoadInstance(void *param)
{
#if 1//假dll
	USES_CONVERSION;
	char apppath[1024] = {};
	std::string exename = "C:/A.dll";
	strcpy_s(apppath,exename.c_str());

	char commandline[2048] = {};
	strcat_s(commandline,_countof(commandline),apppath);
	LPWSTR pszCmdLinew = GetCommandLineW();
	int argc = 0;
	CString FilePath = _T("");
	LPWSTR *argv = CommandLineToArgvW(pszCmdLinew, &argc);
	if (argv != NULL)
	{
		for (int i = 1; i < argc; ++i)
		{
			strcat_s(commandline,_countof(commandline)," ");
			strcat_s(commandline,_countof(commandline),W2A(argv[i]));
		};
		LocalFree(argv);
	}
	PROCESS_INFORMATION pi;
	STARTUPINFOA si = {sizeof(si)};
	CreateProcessA(apppath,commandline,NULL,NULL, FALSE, 0, NULL, NULL, &si, &pi);
#else//真dll
	typedef void (* InvokFunc)();//定义函数指针类型

	HINSTANCE hInst;

	hInst=LoadLibrary(_T("A.dll"));//动态加载Dll

	int error = GetLastError();
	InvokFunc invokFunc=(InvokFunc)GetProcAddress(hInst,"Entrance");//获取Dll的导出函数

	error = GetLastError();

	if(invokFunc)
	{
		invokFunc();
	}

	::FreeLibrary(hInst);//释放Dll函数
#endif
}

int main()
{
	LoadInstance(NULL);
	return 1;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

Windows下使用静态库和动态库

Windows下使用静态库和动态库
  • zhangxiao93
  • zhangxiao93
  • 2016年05月10日 23:26
  • 4564

Windows用来定位DLL的搜索路径(静态加载和动态加载)

转自http://www.2cto.com/os/201404/289687.html 《程序员面试宝典》一书中写到,windows搜索dll文件的顺序为:(1)内存(2)knowndlls...
  • kkForWork
  • kkForWork
  • 2015年06月14日 16:42
  • 1463

获得当前 程序(.exe) 以及 动态库(.dll) 所在路径

一、 获取当前程序所在路径 BOOL CLicenseCtrlDlg::GetAppPath(void) { CString strAppPath; // 保存结果 TCHAR szModule...
  • dongdan_002
  • dongdan_002
  • 2015年01月07日 10:56
  • 2468

.Net c#:配置引用程序集的路径(分离exe和dll)

按照引用程序集路径的不同,程序集DLL分为两类: 1)全局DLL(在GAC中注册,GAC——全局程序集缓存),有关GAC的详细资料可以参考一下链接: http://blog.csdn....
  • prince_lintb
  • prince_lintb
  • 2014年11月04日 18:17
  • 6813

BCB的EXE能否静态调用子目录下的DLL

现在由于某种需求,DLL不能和EXE放在一个目录下;也不希望将DLL放在System32目录下。并且之前DLL都是静态调用使用的,现在问题是能否不改变调用方式就通过建立一个子目录方法让DLL和EXE不...
  • h57020877
  • h57020877
  • 2010年10月15日 17:46
  • 636

.Net c#:配置引用程序集的路径(分离exe和dll从指定路径调用)

按照引用程序集路径的不同,程序集DLL分为两类: 1)全局DLL(在GAC中注册,GAC——全局程序集缓存),有关GAC的详细资料可以参考一下链接: http://blog.csdn.net/pr...
  • xiaominggunchuqu
  • xiaominggunchuqu
  • 2017年12月08日 11:02
  • 222

exe程序与所依赖的dll不在同一目录下的处理办法

------解决方案--------------------------------------------------------                           ...
  • htt9931
  • htt9931
  • 2013年05月07日 22:35
  • 1601

VS2015动态库静态加载时指定动态库位置的方法

在VS2015中静态加载动态库时,需要将库文件(DLL)拷贝到调用程序所在的路径下,如果所需动态库较多时,就会非常麻烦。可以在项目中指定应用程序搜索动态库的路径,这样就无需再将动态库文件进行拷贝了。 ...
  • hou09tian
  • hou09tian
  • 2017年05月27日 06:15
  • 1860

关于DLL搜索路径顺序的一个问题

作者:朱金灿来源:http://blog.csdn.net/clever101/      DLL的动态链接有两种方法。一种是加载时动态链接(Load_time dynamic linking)...
  • clever101
  • clever101
  • 2010年05月04日 22:30
  • 18254

C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁

http://www.tuicool.com/articles/mQVrUbJ 程序目录的整理 想必C#的开发者都遇到过这个问题,引用的dll都放在根目录下,随着项目的日益...
  • stableboy
  • stableboy
  • 2016年06月08日 11:36
  • 5248
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何将程序的执行文件和静态加载动态库放在不同的目录
举报原因:
原因补充:

(最多只允许输入30个字)