在VC下把exe文件转换成DLL文件(1)
2007-05-14 01:27
/*******************************************************************************/
本来打算是把两个*.dsp文件来对比着把一此重要的不同点标记出来的,
便是后来发现如果把这些东西都贴出来也太多了,所以后面就把对两
个*.dsp文件的标记部分没有传上来,大家结合第三部分列举出来的要改
的部分自己去看一下吧.
/*******************************************************************************/
说到这里的方法,我们不得不说一下VC是里面生成的各个文件的作用:
.dsp 工程文件,文本格式,不可丢失或损坏
.dsw 工作区文件,丢失或损坏时,可点击.dsp文件打开工程,.dsw文件自动重建
.clw ClassWizard信息文件,ini格式,ClassWizard出问题时可删除它再重建
.map 映像信息文件,编制DLL写.def文件时,若不知道函数导出顺序,可在
Prject / Settings / Link 页中选中“Generate mapfile”,重新build,
用记事本或其它类似程序打开生成的.map文件,里面可看到函数导出表
.i 在命令行环境下输入:cl ***.cpp /P (注意后面的参数P大小写敏感),
程序文件夹中会生成.i文件,用记事本或其它类似程序打开,可看到.cpp
文件经预处理后的结果
.ncb 无编译浏览文件,当自动完成功能(自动显示成员变量列表)出问题时,
可删除它,build 后自动重建。
其它:
.aps 资源辅助文件,二进制格式
.opt 开发环境参数(如工具条位置)文件
.plg 编译信息(如error和warning信息)文件,html格式
.pch 预编译文件,可加快编译速度,但改文件非常大
.pdb 记录程序相关的数据和调试信息
.**p dll信息文件,编译dll时才会生成
.bsc 用于浏览项目信息,可在
Prject / Settings / Link 页中勾掉“Generate Browse Info File”,
禁止生成.bsc文件,以加快编译速度。但若使用Source Browser的话
就必须有这个文件
说到这里其它今天对我们有用的也就是*.dsp文件,它里面存放的是工程的一些配置信息。所以为了实现今天我们今天的目的,我们就要来改变*.dsp里面的配置信息,这样就可以把一个.**e文件转换成我们需要的dll文件。
好了,下面我们就开始动手吧:
1> 我们创建三个VC工程。命名分别为:DemoDll(Dialog类生成的.**e,用来把它转换成我们想要的DLL文件)DLL(默认的MFC DLL),CallDall(Dialog类用来调用我们转换成的Dll文件)
2> 分别打开DemoDll.dsp Dll.dsp文件
DemoDll.dsp
# Microsoft Developer Studio Project File - Name="DemoDll" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=DemoDll - Win32 Debug
在VC下把exe文件转换成DLL文件(2)
2007-05-14 01:27
好了,两个文件的不同点,我已经给大家标出来了,当然这里标出来的就只是我们需要修改的,所以真正的不同点不止这此。为了实现今天我们的功能这们只要修改上面我标出来的就可以了。
这就是我修改之后的DemoDll.dsp
(1) # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
(2) !MESSAGE "DemoDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
(3) !MESSAGE "DemoDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
(4) # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
(5) # ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /c
(6) # ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386
(7) # ADD LINK32 /nologo /subsystem:windows /dll /machine:I386
(8) # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
(9) # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c
在VC下把exe文件转换成DLL文件(3)
2007-05-14 01:30
(1) # ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
(2) # ADD LINK32 /nologo /subsystem
(3) 还要把BOOL CDemoDllApp::InitInstance()文件中的:#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
给注释掉.
好的,就这些了,上面就是我修改之后的DemoDll.dsp文件的内容,总共需要修改的是13处,其实没也没有什么,只要大家好好的看清楚也就OK了。
好了,文件我们也就转换好了,就让我们来调用一下试试吧:
CallDll.exe:
void CCallDllDlg::OnOK()
{
// TODO: Add extra validation here
HINSTANCE hInstance;
hInstance=::LoadLibrary("..//DemoDll//DemoDll.dll");
if(!hInstance)
{
MessageBox("LoadLibrary is falied!");
return;
}
FreeLibrary(hInstance);
CDialog::OnOK();
}
具体执行效果我就不在这里贴出来了,大家在自己执行一下就可以看到执行效果。
VC下把.EXE源文件改成DLL文件的几个问题(二)
2007-05-14 01:30
[原创]VC下把.EXE源文件改成DLL文件的几个问题(二)
转载请说明出处.
有问题欢迎与本人联系讨论:Email:baoliangster@gmail.com
为了说明问题我们们今天来创建两个工程。DemoDLL工程(是.exe源文件,被我们转换成了DLL文件),CallDll工程用来调用我们生成的DLL文件,即DemoDll。在上一次的文档中我只给大家提到了如何用.EXE源文件来生成DLL文件,这时候我们只要用一般的方法就可以来看到我们的DLL文件的窗口,以及在里面进行一些操作。相关的调用代码,今天在这里我就不在重复了。大家可以参考第一篇文档。
问题一………………………………………………………………………………
不知道大家在调用
HINSTANCE hInstance=NULL;
hInstance=::LoadLibrary(“Dll Path”);
的时候有没有发现在载入DLL的时候,它的返回传值hInstance始终是为0的,也就是说,如果我们想在我的程序中给DLL文件中的窗口或者函数传递参数是没有办法的。因为我们没有办法来调用DLL的入口函数。所以说呢,我们这样生成的DLL文件其实意义并不是很大的,只相当于我们以另一种形式在我们的当前的程序用调用了另一个小程序或者说的窗口。
既然有问题,那我们就要解决,但还是有必要来分析一下为什么我们的LoadLibrary的返回总是为0呢,难道是说我们没有载入或者说是载入失败,不可能的如果是这样那我们的程序为什么会运行起来的,那看来还是别有蹊跷的。
大家不会忘记在InitInstance()中有下面这样一段代码吧:
CResourceDDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
看到这里的时候,想必大家已经知道引起问题的罪魁祸首是谁了吧!不错就是那个DoModal()正是由于它的存在,才使我们的程序在被成功加载的之后,没有返回我们所想要的值。因为在我们的程序在调用DLL的时候,(在MFC中程序的执行顺序我在这里就不再多说了,大家应该非常清楚的)当执行到了DoModall的时候(说到这里我感觉我还是有必要和大家讨论一下VC中的对话框:在VC中对话框分为两类一是模式对话框二是无模式对话框。两者的主要区别在于:<1>显示模式对话框需要调用CDialog::DoMaodal,而显示模式对话框则要调用CDialog::Create.DoModal要等到对话框被消除之后才返回。而和DoModal不同,一旦建立对话框,Create就返回,因此,Create返回时对话框还处于显示状态。<2>清除模式对话框要调用DestroyWindow,而不是EndDialog.禁止对无模式对话框调用CDialog::OnOk或CDialog::OnCancel,因为两者都调用EndDialog.<3>模式对话框类通常在堆栈上实例化,所以析构是自动实现的,而无模式对话框通过NEW实例化,所以该对话框对象不会过早地被消除。如果要确保消除对话框时删除无模式对话框对象,一种方法是在派生的对话框类中覆盖CDialog::PostNcDestroy并执行delete this语句.当然模式对话框我无模式对话框还是有区别的,不过今天我们就只提到对我们有用的。有兴趣的大家可以自己研究),也就是说欠产在调用一个模式对话框并且让它显示了出来,但是我们不要忘记上面提到的模式对话框的特点,DoModal一定要等到对话框被返回的时候,才被消息,所以呢当我们在执行的时候,我们的DLL文件一但进入到这里面的时候,除非清除它否则我们是无法返回的。这也就造成了为什么我们的返回值一直为空,
知道产生这个问题的原因了,接下来要解决这个问题也很简单。
造成没有返回值的原因是因为模式对话框,那好了,我们不用它了,改成无模式对话框那总好了吧。所以我们的代码修改如下:
BOOL CDemoDllApp::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
/*
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif*/
/****************利用无模式对话框*************************/
pDlg=new CDemoDllDlg;
m_pMainWnd = pDlg;
pDlg->Create(IDD_DEMODLL_DIALOG);
pDlg->ShowWindow(SW_HIDE);
// int nResponse = pDlg->DoModal();
/* if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
// {
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
// }
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
*/
return true;//一定要返回TRUE
}
修改的地方不是很多吧,好了这样问题也解决了。不信大家可以测试一下,看一看我们的调用DLL的时候有没有返回值了呢。(还有另一种办法,不过还是有点错误,等调好了再告诉大家),所以接下来我们就可以在DLL里同声明我们自己的导出函数,供我们调用了。不过还是把它做为下一次的内容吧。今天到此为止吧。时间不早了!