VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
楼主: cykppm

EXE依赖几个DLL运行,如何把DLL打包在EXE中

[复制链接]

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-6-21 18:00:01 | 显示全部楼层
还有各位是怎么释放资源文件为dll的,我是用WriteFile重新写一个文件。
回复

使用道具 举报

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-8-2 23:15:01 | 显示全部楼层

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMoveResDlg::OnQueryDragIcon()
{
        return (HCURSOR) m_hIcon;
}

void CMoveResDlg::OnOK()
{
        // TODO: Add extra validation here
#define MAX_SEC_NUMS        16         //假设节表不超过16个
#define MAX_RES_DIR_ENTRYS        1024        //假设资源目录不超过1024个
        //
        DWORD        dwOldResStartRVA = 0;        //老的资源节的起始 RVA
        //
        IMAGE_RELOCATION        sReloc;
        char bufferSection[sizeof(IMAGE_SECTION_HEADER)*MAX_SEC_NUMS];
        memset(bufferSection,0,sizeof(IMAGE_SECTION_HEADER)*MAX_SEC_NUMS);
        //
        char        *pTempNewRes = NULL;
        //
        IMAGE_DOS_HEADER                sDogHead;
        IMAGE_NT_HEADERS                sPeHead;
        IMAGE_DATA_DIRECTORY        sPeDataDirOfResource;
        //
        IMAGE_RESOURCE_DIRECTORY                sResDir;
        IMAGE_RESOURCE_DIRECTORY_ENTRY        sResDirEntry[MAX_RES_DIR_ENTRYS];
        memset((char*)&sResDirEntry[0],0,sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)*MAX_RES_DIR_ENTRYS);
        IMAGE_RESOURCE_DATA_ENTRY                sResDataEntry;
        IMAGE_RESOURCE_DIR_STRING_U                sResDirStringU;
        IMAGE_RESOURCE_DIRECTORY_STRING        sResDirString;
        //
        CFile theFile;
        short        theErr = theFile.Open(m_szPeFile, CFile::modeReadWrite,NULL);
        if(theErr == 0)
        {
                //error.
                MessageBox("打开PE文件错误!");
                return;
        }
        //读取Dos头
        theFile.SeekToBegin();
        theErr = theFile.Read((char*)&sDogHead,sizeof(IMAGE_DOS_HEADER));
        if(theErr==0)
        {
                MessageBox("读取PE文件错误!");
                theFile.Close();
                return;
        }
        //读取PE头
        theFile.Seek(sDogHead.e_lfanew,CFile::begin);
        theErr = theFile.Read((char*)&sPeHead,sizeof(IMAGE_NT_HEADERS));
        if(theErr==0)
        {
                MessageBox("读取PE文件错误!");
                theFile.Close();
                return;
        }
        //
        if(sPeHead.Signature != 0x4550)                //"PE"
        {
                MessageBox("不是有效的PE文件!");
                theFile.Close();
                return;
        }
        //读取节表
        theErr = theFile.Read(bufferSection,sizeof(IMAGE_SECTION_HEADER) * sPeHead.FileHeader.NumberOfSections);
        if(theErr==0)
        {
                MessageBox("读取PE文件错误!");
                theFile.Close();
                return;
        }
        sPeDataDirOfResource = sPeHead.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
        if(sPeDataDirOfResource.VirtualAddress == 0 || sPeDataDirOfResource.Size == 0)
        {
                MessageBox("本PE文件没有资源表!");
                theFile.Close();
                return;
        }
        //
        if(m_dwNewResStartRVA % 4 != 0)
        {
                DWORD nAlign = 4 - (m_dwNewResStartRVA % 4);
                m_dwNewResStartRVA += nAlign;
                CString temp;
                temp.Format("%x",m_dwNewResStartRVA);
                m_EditNewResRVA.SetWindowText(temp);
                MessageBox("新的资源表起始地址不是双字边界,"\
                               "\n将强制改为4字节对齐!\n"\
                                   "新的地址RVA为:0x"+temp);
        }
        //
        dwOldResStartRVA = sPeDataDirOfResource.VirtualAddress;
        pTempNewRes = new char[sPeDataDirOfResource.Size];
        memset(pTempNewRes,0,sPeDataDirOfResource.Size);
        //
        DWORD dwPEMaxRVA = 0;
        //将老的资源 RVA 转换成 fileOffset
        DWORD dwOldResStartFileOffset = ConvertAddrToFileOffset(&sPeHead,
                                                                                                                        dwOldResStartRVA,
                                                                                                                        bufferSection,
                                                                                                                        dwPEMaxRVA,
                                                                                                                        TRUE);
        //
        if(m_dwNewResStartRVA+sPeDataDirOfResource.Size > dwPEMaxRVA)
        {
                MessageBox("PE文件新资源最大地址:(起始地址+资源大小) 越界)!");
                theFile.Close();
                return;
        }
        //将新的资源 RVA 转换成 fileOffset
        DWORD dwNewResStartFileOffset = ConvertAddrToFileOffset(&sPeHead,
                                                                                                                        m_dwNewResStartRVA,
                                                                                                                        bufferSection,
                                                                                                                        dwPEMaxRVA,
                                                                                                                        TRUE);

        if( dwOldResStartFileOffset == -1)
        {
                MessageBox("PE文件起始资源地址非法!");
                theFile.Close();
                return;
        }
        if(dwNewResStartFileOffset == -1 ||
                m_dwNewResStartRVA < sPeHead.OptionalHeader.SizeOfHeaders ||
                m_dwNewResStartRVA < 0x1000
                )
        {
                MessageBox("PE文件资源新的起始地址非法!");
                theFile.Close();
                return;
        }

        //读取全部资源到 pTempNewRes
        theFile.Seek(dwOldResStartFileOffset,CFile::begin);
        theFile.Read(pTempNewRes,sPeDataDirOfResource.Size);
        //
        //根据 m_dwNewResStartRVA 调整资源中相关 RVA
        DWORD dwDelta = dwOldResStartRVA - m_dwNewResStartRVA;
        AdjustRVA(pTempNewRes,(IMAGE_RESOURCE_DIRECTORY*)pTempNewRes,dwDelta);
        //
        //将调整后的资源写入 PE
        theFile.Seek(dwNewResStartFileOffset,CFile::begin);
        theFile.Write(pTempNewRes,sPeDataDirOfResource.Size);
        //
        //修改 PE 头,使资源指向 m_dwNewResStartRVA
        sPeHead.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = m_dwNewResStartRVA;
        //写入PE头
        theFile.Seek(sDogHead.e_lfanew,CFile::begin);
        theFile.Write((char*)&sPeHead,sizeof(IMAGE_NT_HEADERS));
        //
        if(pTempNewRes)
        {
                delete pTempNewRes;
                pTempNewRes = NULL;
        }
        theFile.Close();
        //
        //-----------------------------------------------------------------------
        /* MapFileAndCheckSum() return value.
        CHECKSUM_OPEN_FAILURE                Could not open the file.
        CHECKSUM_MAP_FAILURE                Could not map the file.
        CHECKSUM_MAPVIEW_FAILURE        Could not map a view of the file.
        CHECKSUM_UNICODE_FAILURE        Could not convert the file name to Unicode.
        */
        char buffer[255];
        strcpy(buffer,m_szPeFile);
        DWORD dwHeaderSum;
        DWORD dwCheckSum;
        DWORD dwRet = MapFileAndCheckSum(buffer,&dwHeaderSum,&dwCheckSum);
        if( dwRet == CHECKSUM_SUCCESS )
        {
                //
                theErr = theFile.Open(m_szPeFile, CFile::modeReadWrite,NULL);
                //读取Dos头
                theFile.SeekToBegin();
                theErr = theFile.Read((char*)&sDogHead,sizeof(IMAGE_DOS_HEADER));
                //读取PE头
                theFile.Seek(sDogHead.e_lfanew,CFile::begin);
                theErr = theFile.Read((char*)&sPeHead,sizeof(IMAGE_NT_HEADERS));
                //修改校验和
                sPeHead.OptionalHeader.CheckSum = dwCheckSum;
                //
                theFile.Seek(sDogHead.e_lfanew,CFile::begin);
                theFile.Write((char*)&sPeHead,sizeof(IMAGE_NT_HEADERS));
                theFile.Close();
        }
        //-----------------------------------------------------------------------
        //
        MessageBox("PE文件新资源起始地址修改成功!");
        //CDialog::OnOK();
}
回复

使用道具 举报

0

主题

8

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
发表于 2020-8-3 15:30:01 | 显示全部楼层
总结:
把dll一块打包放到exe的文件夹下就行了。
回复

使用道具 举报

0

主题

57

帖子

27.00

积分

新手上路

Rank: 1

积分
27.00
发表于 2020-8-4 23:00:01 | 显示全部楼层
难道你不会使用静态MFC连接?
回复

使用道具 举报

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-8-5 15:15:01 | 显示全部楼层
怎么静态MFC连接?麻烦说清楚点?
回复

使用道具 举报

0

主题

57

帖子

27.00

积分

新手上路

Rank: 1

积分
27.00
发表于 2020-8-5 17:45:04 | 显示全部楼层
在工程属性里,选择MFC连接方式为静态
回复

使用道具 举报

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-8-6 18:15:02 | 显示全部楼层
选择静态编译MFC后出现错误,我拷贝了部分,重定义,怎么办?:

MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: _wcslen already defined in libcmtd.lib(wcslen.obj)
MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: _wcstombs already defined in libcmtd.lib(wcstombs.obj)
MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: _wcsrchr already defined in libcmtd.lib(wcsrchr.obj)
回复

使用道具 举报

0

主题

57

帖子

27.00

积分

新手上路

Rank: 1

积分
27.00
发表于 2020-8-6 19:45:01 | 显示全部楼层
你把libcmtd.lib这个库的连接去掉
回复

使用道具 举报

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-8-6 20:45:01 | 显示全部楼层
谢谢,去掉后错误少了,但是还有一部分:

msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::_Container_base::~_Container_base(void)" (??1_Container_base@std@@QAE@XZ) already defined in configurationdlg.obj
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in configurationdlg.obj
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in configurationdlg.obj
回复

使用道具 举报

1

主题

11

帖子

9.00

积分

新手上路

Rank: 1

积分
9.00
 楼主| 发表于 2020-8-6 21:00:01 | 显示全部楼层
继续Disable link libcpmtd.lib,还有的错误好象是关于stl容器的,什么原因
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表