是否可以自制一个安装程序,将运行目录打包进exe文件?

凌乱哥 2014-04-08 08:49:06
现在要打包一个项目,做成一个安装程序,客户下载安装程序后就可以下一步下一步的安装到自己的电脑上
我会用IS12,但是领导有个比较美好但是变态的要求,要在安装过程中展示一些图片来介绍公司的其他产品,就比如QQ安装的时候会有一些QQ的新功能的图片切换,这样的话IS并不是很好操作,而且用IS打包的话,由于项目比较小,安装过程肯定很快,也展示不了多少内容。
所以想请问下各位是否有相关的资料或者建议,提供一些思路也可以,主要的问题就是将项目用到的内容打包到一个exe里,项目内容包括:
txt文本文档、pdf文档、exe文件、png图片、cfg配置文件、dll动态链接库和lib静态链接库等
就相当于运行一个exe,经过一些选项和过程,就把上述文件释放出来,形成一个运行目录,然后桌面添加快捷方式,添加注册表,添加到开始菜单等等。。。后面那3个我倒是自己能完成
...全文
1538 38 打赏 收藏 转发到动态 举报
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
落楓絮語 2016-09-12
  • 打赏
  • 举报
回复
使用WinRAR+CSS就可以實現安裝界面廣告展示,你在自解壓選項裏設置就好,在註釋裏寫HTML代碼用CSS美化就好,安裝位置固定D:\Program files\檔案夾名\運行檔案.exe
這方法基本無技術含量,簡單易用且可以優惠到WinRAR生成安裝包的系統高權限。
sumos 2014-10-29
  • 打赏
  • 举报
回复
可以把 程序包(包括图片,exe,dll)压缩成一个zip,然后作为资源插入到工程中, 安装时,先把资源读取到数据流(FindResource,LockResource), 然后使用XUnZip.h文件提供的UnZip函数来解压到目标文件夹, 至此,基本的安装就可以了。
gfm688 2014-05-27
  • 打赏
  • 举报
回复
引用 35 楼 SXJIAKE 的回复:
gfm688 都开始不推荐使用 NSIS 了,让自己做安装程序。
NSIS 虐我千百遍,我待 NSIS 如初恋
凌乱哥 2014-04-17
  • 打赏
  • 举报
回复
安装程序已完成,用的就是14楼的方法,另特别感谢一下27楼的哥们。。
chen870201 2014-04-10
  • 打赏
  • 举报
回复
打包程序有很多
凌乱哥 2014-04-10
  • 打赏
  • 举报
回复
引用 26 楼 xiaohuh421 的回复:
因为文件是可以共享读的. 即运行的时候你还可以打开文件来读取数据的. 基于这个思想, 要做这个程序就相对简单了. 先生成好一个exe, 这个exe就是负责释放文件,展示需要的图片. 然后使用另一个程序把所有的*.*文件追加到exe文件后面. 这样, exe运行时就可以读取exe后面的数据.
多谢你的建议。。。
引用 27 楼 zhllxt 的回复:
我说下我的具体过程吧:
非常感谢你提供的帮助。。
zhllxt 2014-04-10
  • 打赏
  • 举报
回复
我说下我的具体过程吧: 1、定义结构体。

typedef struct _FileInfo{
public:
	UINT	uResourceID;
	TCHAR *	ptzFileType;
	char *	pszOutputFileName;
}FileInfo, *PFileInfo;
2、将文件加入到工程中。 3、做一个全局数组,用于说明哪些资源需要释放。


FileInfo g_files[] = {
	{IDR_FILE2           ,_T("FILE"),               "..\\..\\bin\\ChnCharInfo.dll"},
	{IDR_FILE3           ,_T("FILE"),               "..\\..\\bin\\CarTypeManager.dll"},
	{IDR_FILE1           ,_T("FILE"),               "..\\..\\bin\\ZKTD.dll"},
	{IDR_FILE4           ,_T("FILE"),               "..\\..\\bin\\CKTD.dll"},
	{IDR_FILE5           ,_T("FILE"),               "..\\..\\bin\\EncryptDecrypt.dll"},
......
4、关键函数。

//创建快捷方式
BOOL CPropertyPage5::CreateLink(LPCTSTR pszFile,LPCTSTR pszDirectory)
{   
	CoInitialize(NULL);
	
	HRESULT hres;
	IShellLink* psl;
	IPersistFile* ppf;
	
	hres = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void**)&psl);
	if(FAILED(hres)) return FALSE;
	
	psl->SetPath(pszFile);//设置源文件名
//	psl->SetDescription("C:\\123");//设置备注
//	psl->SetRelativePath("C:\\123",0);//目标位置
	//起始位置--这个一定要设,因为载入INI文件是在起始位置找的,不设置此值将在桌面上找
	CString strWorkingDirectory( pszFile );
	strWorkingDirectory = strWorkingDirectory.Left( strWorkingDirectory.ReverseFind('\\') + 1 );
	psl->SetWorkingDirectory( strWorkingDirectory );
	
	hres = psl->QueryInterface(IID_IPersistFile,(void**)&ppf);   
	if(FAILED(hres)) return FALSE;

	OLECHAR wszDirectory[MAX_PATH] = { 0 };
#ifdef _UNICODE
	wcscpy_s( wszDirectory,sizeof(wszDirectory)/sizeof(OLECHAR),pszDirectory );
#else
	MultiByteToWideChar(CP_ACP,0,pszDirectory,-1,wszDirectory,MAX_PATH);
#endif

	hres=ppf->Save(wszDirectory,STGM_READWRITE);//LPCOLESTR

	ppf->Release();
	psl->Release();

	CoUninitialize();
	return TRUE;
}
//释放资源文件到指定的文件
bool CPropertyPage5::ExtractResource(LPCTSTR lpName,LPCTSTR lpType,LPCTSTR lpFilePath,bool bOverWrite)
{
	if(bOverWrite==false)
	{
		CFileFind ff;
		if(ff.FindFile(lpFilePath)) return false;
	}

	HMODULE hModule = AfxGetInstanceHandle();
	HRSRC res=FindResource(hModule,lpName,lpType);
	if(res==NULL) return false;

	HGLOBAL gl=::LoadResource(hModule,res);
	if(gl==NULL) return false;

	char * lp=(char*)::LockResource(gl);   //  查找,加载,锁定资源

	if(lp==NULL) return false;

	TCHAR path[MAX_PATH] = {0};
	_tcscpy_s(path,sizeof(path),lpFilePath);
	_tcscpy_s(_tcsrchr(path,'\\')+1,sizeof(path)-(_tcsrchr(path,'\\')-path+1),_T(""));
	CreateMultiDir(path);

	HANDLE fp;
	if(bOverWrite)
        fp=CreateFile(lpFilePath,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
    else
        fp=CreateFile(lpFilePath,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_NEW,0,NULL);

	bool ret = false;
	if(fp != INVALID_HANDLE_VALUE)
	{
		CString strProgress;
		strProgress.Format( _T("正在复制文件 %s"),lpFilePath );
		SetDlgItemText(IDS_PROGRESS,strProgress);

		DWORD dwRecvWritedVolumes=0,dwWritedVolumes=0,dwTotalVolumes=::SizeofResource(hModule,res);
		while( dwWritedVolumes < dwTotalVolumes )
		{
			if( dwWritedVolumes + theApp.m_dwWriteVolumesOnce <= dwTotalVolumes )
			{
				if( WriteFile(fp,lp+dwWritedVolumes,theApp.m_dwWriteVolumesOnce,&dwRecvWritedVolumes,NULL) == FALSE )
					ret = false;
			}
			else
			{
				if( WriteFile(fp,lp+dwWritedVolumes,dwTotalVolumes-dwWritedVolumes,&dwRecvWritedVolumes,NULL) == FALSE )
					ret = false;
			}
		//	SetFilePointer(fp,0,NULL,FILE_END);//设置文件指针到文件尾

			//记录写入的数据大小
			dwWritedVolumes += dwRecvWritedVolumes;
			m_dwWritedFileVolumes += dwRecvWritedVolumes;
			m_Progress.SetPos( m_dwWritedFileVolumes );
			//做一次消息循环
			MSG msg;
			while( PeekMessage( &msg,NULL,0,0,PM_REMOVE ) )
			{
				if( !AfxGetApp()->PreTranslateMessage( &msg ) )
				{
					TranslateMessage( &msg );
					DispatchMessage( &msg );
				}
			}
		}
	}
	::CloseHandle (fp);       //关闭句柄
	::FreeResource (gl);     //释放内存
	return ret;
}
5、开始释放资源。


BOOL CPropertyPage5::StartInstall()
{
	DWORD dwTotalVolumes = GetTotalVolumes();
	m_Progress.SetRange32(0,dwTotalVolumes);

	CPropertySheet * pSheet=(CPropertySheet*)GetParent();
	CPropertyPage3 * m_page3=(CPropertyPage3*)( pSheet->GetPage(2) );
	CString strDirectory=m_page3->m_strDirectory;//安装程序目的文件夹
	BOOL bCreateShortcut=m_page3->m_bCheckShortcut;//是否创建快捷方式
	BOOL bCreateProgramFolder=m_page3->m_bCheckProgram;//是否创建开始菜单程序组
	if( strDirectory[strDirectory.GetLength()-1] != '\\' )
		strDirectory += '\\';

	CreateMultiDir( strDirectory );
	//写Uninstall.txt文件
	CFile file;
	char buf[ MAX_PATH + 8 ];
	CString strUninstallFile = strDirectory + _T("Uninstall.txt");
	BOOL bUninstallFile = file.Open( strUninstallFile,CFile::modeCreate | CFile::modeReadWrite | CFile::typeText );
	CString strFile;
	strFile.Format( _T("%s %d\r\n"),strDirectory,RES_DIRECTORY );
	if( bUninstallFile )
	{
		memset( buf,0,MAX_PATH + 8 );
#ifdef _UNICODE
		WideCharToMultiByte( CP_ACP,0,strFile,strFile.GetLength(),buf,MAX_PATH+8,0,0 );
#else
		strcpy( buf,strFile );
#endif
		file.Write( buf,strlen( buf ) );
	}
	//开始写文件
	m_dwWritedFileVolumes = 0;//所有已经写入的文件体积
	TCHAR tzOutputFileName[MAX_PATH];
	int i,nCount = sizeof(g_files)/sizeof(FileInfo);
	for( i = 0; i < nCount; i++ )
	{
#ifdef _UNICODE
		MultiByteToWideChar(CP_ACP,0,g_files[i].pszOutputFileName,-1,tzOutputFileName,MAX_PATH);
#else
		strcpy( tzOutputFileName,g_files[i].pszOutputFileName );
#endif
		CString strOutputFileName = tzOutputFileName;
		strOutputFileName.Delete( 0,_tcslen(_T("res\\Files\\")) );
		strOutputFileName.Insert( 0,strDirectory );
		ExtractResource(MAKEINTRESOURCE(g_files[i].uResourceID),g_files[i].ptzFileType,strOutputFileName,true);
		Sleep( 10 );
	}
	//创建快捷方式
	CString strAppPath,strUninstallPath,strLink;
	if( bCreateShortcut )
	{
		SetDlgItemText(IDS_PROGRESS,_T("正在建立应用程序快捷方式..."));
		//获取“桌面”所在位置
		SHGetSpecialFolderPath(m_hWnd,strLink.GetBuffer(MAX_PATH),CSIDL_COMMON_DESKTOPDIRECTORY,TRUE);
		strLink.ReleaseBuffer();
		if( strLink[strLink.GetLength()-1] != '\\' ) strLink += '\\';
		strLink += theApp.m_strTitle;
		strLink += _T(".lnk");
		strAppPath = strDirectory;
		strAppPath += theApp.m_strAppName;
		strAppPath += _T(".exe");
		CreateLink( strAppPath.GetBuffer(strAppPath.GetLength()),strLink);

		strFile.Format( _T("%s %d\r\n"),strLink,RES_FILE );
		if( bUninstallFile )
		{
			memset( buf,0,MAX_PATH + 8 );
#ifdef _UNICODE
			WideCharToMultiByte( CP_ACP,0,strFile,strFile.GetLength(),buf,MAX_PATH+8,0,0 );
#else
			strcpy( buf,strFile );
#endif
			file.Write( buf,strlen( buf ) );
		}
	}
	//创建开始菜单程序组
	if( bCreateProgramFolder )
	{
		SetDlgItemText(IDS_PROGRESS,_T("正在创建开始菜单程序组..."));
		CString strStart;//获取“开始菜单程序组”所在位置
		SHGetSpecialFolderPath( m_hWnd,strStart.GetBuffer(MAX_PATH),CSIDL_COMMON_PROGRAMS,TRUE);
		strStart.ReleaseBuffer();
		if( strStart[strStart.GetLength()-1] != '\\' ) strStart += '\\';
		strStart += theApp.m_strTitle;
		if( strStart[strStart.GetLength()-1] != '\\' ) strStart += '\\';
		CreateMultiDir(strStart);
		strLink = strStart;
		strLink += theApp.m_strTitle;
		strLink += _T(".lnk");
		CreateLink(strAppPath.GetBuffer(strAppPath.GetLength()),strLink);

		strUninstallPath = strDirectory;
		strUninstallPath += _T("Uninstall.exe");
		strLink = strStart;
		strLink += _T("\\卸载.lnk");
		CreateLink(strUninstallPath.GetBuffer(0),strLink);

		strFile.Format( _T("%s %d\r\n"),strStart,RES_DIRECTORY );
		if( bUninstallFile )
		{
			memset( buf,0,MAX_PATH + 8 );
#ifdef _UNICODE
			WideCharToMultiByte( CP_ACP,0,strFile,strFile.GetLength(),buf,MAX_PATH+8,0,0 );
#else
			strcpy( buf,strFile );
#endif
			file.Write( buf,strlen( buf ) );
		}
	}
	//写注册表
	SetDlgItemText(IDS_PROGRESS,_T("正在写入系统注册表信息..."));
	WriteRegedit( strUninstallPath );//写注册表

	//写加密狗驱动
	SetDlgItemText(IDS_PROGRESS,_T("正在写入加密锁驱动..."));
	CString strSoftDogFilePath = strDirectory + _T("SoftDogSetup.dll");
	HINSTANCE hSoftDogDll = LoadLibrary( strSoftDogFilePath );
	if( hSoftDogDll != NULL )
	{
		InstDriver = (INSTDRIVER)GetProcAddress(hSoftDogDll, "InstDriver");
		UninstallDriver = (UNINSTALLDRIVER)GetProcAddress(hSoftDogDll, "UninstallDriver");
		DriverDialog = (DRIVERDIALOG)GetProcAddress(hSoftDogDll, "DriverDialog");
		GetDogDriverInfo = (GETDOGDRIVERINFO)GetProcAddress(hSoftDogDll, "GetDogDriverInfo");

		int nRet = InstDriver(INSTALL_ONLY_USB_DOG_DRVIER);
		if(nRet)
		{
			if (nRet == 3008)
			{
				MessageBox( _T("安装加密锁驱动失败,请以管理员身份登录操作系统,然后重试!"),_T("错误"),MB_ICONERROR );
			}
			else
			{
				MessageBox( _T("安装加密锁驱动失败请重试!"),_T("错误"),MB_ICONERROR );
			}
		}

		FreeLibrary( hSoftDogDll );
	}

	SetDlgItemText( IDS_PROGRESS,_T("安装完成!") );
	m_Progress.SetPos( dwTotalVolumes );

	pSheet->SetWizardButtons(PSWIZB_FINISH);
	CancelToClose();

	return TRUE;
}
xiaohuh421 2014-04-10
  • 打赏
  • 举报
回复
因为文件是可以共享读的. 即运行的时候你还可以打开文件来读取数据的. 基于这个思想, 要做这个程序就相对简单了. 先生成好一个exe, 这个exe就是负责释放文件,展示需要的图片. 然后使用另一个程序把所有的*.*文件追加到exe文件后面. 这样, exe运行时就可以读取exe后面的数据.
凌乱哥 2014-04-10
  • 打赏
  • 举报
回复
引用 22 楼 a295281315 的回复:
Wise Installation System - Professional Edition 这个工具可以做到你的要求,你不需要自己写了。
引用 23 楼 chen870201 的回复:
打包程序有很多
还是自己写下试试吧,不行再说,用打包软件的话还得找教程学习
凌乱哥 2014-04-10
  • 打赏
  • 举报
回复
引用 21 楼 zhllxt 的回复:
自己写吧,想怎么控制就怎么控制,我的安装程序就是自己写的:把需要用到的文件全部作为资源加入到工程中,并作一个文件名和路径等记录,安装的时候从资源中取出来释放到指定的目录即可,这样安装的EXE上面你想显示什么,想显示多久都没有任何问题。我就是为了不让安装过程太快,每释放一个文件我就sleep 500 ms
我就是这样想的
「已注销」 2014-04-10
  • 打赏
  • 举报
回复
gfm688 都开始不推荐使用 NSIS 了,让自己做安装程序。
allenhiman 2014-04-10
  • 打赏
  • 举报
回复
哦 给exe压缩加个壳 应该微软有官方的工具 忘记叫啥了
allenhiman 2014-04-10
  • 打赏
  • 举报
回复
话说你说的微软的那个展示 就是这么干的 它本身就好多msi给整合到一起 然后一个exe引导分别装这些msi
赵4老师 2014-04-10
  • 打赏
  • 举报
回复
向27楼学习。
allenhiman 2014-04-10
  • 打赏
  • 举报
回复
既然你的安装包很简单 很快 又要刻意的展示一些“广告”, 那完全可以把安装包和展示分开 我不知道你说的那个IS是否支持“静默安装”反正 最标准的msi是可以的 而且支持很多参数 比如制定安装路径啥的。 如果是msi把它当资源 适当的时候释放静默执行 这个方案肯定可行 也不存在压缩解压缩的问题了 因为msi本身是压缩格式 你exe可以不压缩 因为你的exe应该很小.
kxj0o 2014-04-10
  • 打赏
  • 举报
回复
用NSIS打包工具啊,还是开源的~~~
gfm688 2014-04-09
  • 打赏
  • 举报
回复
引用 16 楼 dingxz105090 的回复:
[quote=引用 12 楼 gfm688 的回复:] 反正就是将exe 和 压缩包 合并,可以添加到资源段,可以追加到exe文件末尾 只要你在exe里实现将自己(合并了压缩包的整个exe文件)当成压缩包来解压 7-Zip 和 WinRAR 都有查找压缩包Signature的功能,以前看过将压缩包伪装成图片的东东(双击打开是图片,但可以用解压缩软件来解压),原理其实就是将压缩包追加到图片文件末尾罢了
文件合并是二进制合并吧?[/quote] 是的,用批处理就是

copy /b head.exe + data.7z Setup.exe
凌乱哥 2014-04-09
  • 打赏
  • 举报
回复
引用 12 楼 gfm688 的回复:
反正就是将exe 和 压缩包 合并,可以添加到资源段,可以追加到exe文件末尾 只要你在exe里实现将自己(合并了压缩包的整个exe文件)当成压缩包来解压 7-Zip 和 WinRAR 都有查找压缩包Signature的功能,以前看过将压缩包伪装成图片的东东(双击打开是图片,但可以用解压缩软件来解压),原理其实就是将压缩包追加到图片文件末尾罢了
文件合并是二进制合并吧?
凌乱哥 2014-04-09
  • 打赏
  • 举报
回复
多谢大家的回复,大致都是文件合成和作为资源导入的办法,从理论来说都是可行的,过两天开始尝试下。。
弱水垂钓 2014-04-09
  • 打赏
  • 举报
回复
目前做的一个测试的补丁包就是将更新的所有文件包括目录压缩成一个zip包,导入到VC程序的资源内 VC程序运行过程中使用资源,提取zip到临时目录,使用zlib解压,剩下的就随你了,想怎么展示就怎么展示,想怎么搞就怎么搞
加载更多回复(18)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧