VC++创建msi文件的方法

采用VC++可以编写自己软件的安装程序。这里只是创建安装程序类型的msi文件,用orca打开是正确的文件格式,值得自己记录一下了,msi数据库里面的各种表关系复杂,不是一时半刻能研究清楚的。本文仅作一浅析,实现写一个程序附到软件程序的后面,这样可以在编译完成后直接会有安装程序msi文件。就像平常下载的软件,可以写注册表,创建桌面快捷方式,注册各种软件用到的组件和功能。

具体示例程序如下:

#pragma once
//CRT headers.
#include <TCHAR.H>
//windows platform headers.
#include <WINDOWS.H>
//msi headers.
#pragma comment(lib,"msi.lib")
#include <MSI.H>
#include <MSIQUERY.H>
INT APIENTRY _tWinMain(
HINSTANCE,
HINSTANCE,
LPTSTR,
INT)
{
MSIHANDLE msiHandle=NULL;
//create msi database.
UINT openResult=MsiOpenDatabase(
_T("Setup.msi"),
MSIDBOPEN_CREATEDIRECT,
&msiHandle);
//create msil database failed.
if(openResult != ERROR_SUCCESS)
{
LPVOID formatMsg=NULL;
MSIHANDLE errorCode=MsiGetLastErrorRecord();
//format error code to string.
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),
(LPTSTR)&formatMsg,
0,
NULL);
//output error message.
MessageBoxEx(
NULL,
(LPTSTR)formatMsg,
_T("tip window"),
MB_OK,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT));
//free message buffer.
LocalFree(formatMsg);
formatMsg=NULL;
return -1;
}
//commit msi database.
UINT commitResult=MsiDatabaseCommit(msiHandle);
if(commitResult != ERROR_SUCCESS)
{
LPVOID formatMsg=NULL;
MSIHANDLE errorCode=MsiGetLastErrorRecord();
//format error code to string.
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),
(LPTSTR)&formatMsg,
0,
NULL);
//output error message.
MessageBoxEx(
NULL,
(LPTSTR)formatMsg,
_T("tip window"),
MB_OK,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT));
//free message buffer.
LocalFree(formatMsg);
formatMsg=NULL;
return -1;
}
//close msi database handle.
UINT closeResult=MsiCloseHandle(msiHandle);
if(closeResult != ERROR_SUCCESS)
{
LPVOID formatMsg=NULL;
MSIHANDLE errorCode=MsiGetLastErrorRecord();
//format error code to string.
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),
(LPTSTR)&formatMsg,
0,
NULL);
//output error message.
MessageBoxEx(
NULL,
(LPTSTR)formatMsg,
_T("tip window"),
MB_OK,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT));
//free message buffer.
LocalFree(formatMsg);
formatMsg=NULL;
return -1;
}
return 0;
}
</SPAN>

本程序仅实现简单的基本功能,读者可根据自身的需要进一步开发其他个性化功能,以满足自身需求。

(0)

相关推荐

  • 用VC++6.0实现石头剪刀布游戏的程序

    源程序是从网上看到的, geek_monkey于2015年3月3日修改了bug(输入字符非石头剪刀布都算是玩家赢) 编译环境为VC++6.0 增加"上帝模式"和数据统计,纯属娱乐. 我是C语言初学者,轻喷 复制代码 代码如下: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> int exist_in(char *arr1[][2],

  • VC++实现CStdioFile写入及读取文件并自动换行的方法

    本文所述CStdioFile可实现在VC++中主要用来写入及读出文件的功能,继承自CFile类,它会自动处理 "\r\n",遇到"\n"自动添加\r并设置光标在当前行,它同时可以自动换行,不过使用CStdioFile在处理大文件时速度有些慢, 用CStdioFile写入读取文件实现代码如下: LPTSTR filter=_T("Playlist Files(.txt)|*.txt|"); CString tempPath; CFileDialog

  • VC++开发中完美解决头文件相互包含问题的方法解析

    所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数. 一般情况下,C/C++要求所有的类型必须在使用前被定义,但是在一些特殊情况下,这种要求无法满足,例如,在类CMyView中保留了一个非模式对话框对象指针,该对象用于显示/修改一些信息.为了实现对话框"应用"按钮,把对话框做的修改立刻更新到view界面上,为此,需要在对话框类中需要保存view类的指针,这样定义关系就变成如下的代码: 复制代码 代码如下: #ifndef __MYVIEW_H__   #define __MY

  • VC++ 使用 _access函数判断文件或文件夹是否存在

    _access函数 int _access( const char *path, int mode ); int _waccess( const wchar_t *path, int mode ); 参数 path 文件或目录路径. mode 读/写特性. 返回值   如果文件包含特定模式,每个函数返回 0. 函数返回 - 1,则名称文件不存在或不具有特定模式:在这种情况下,如下表errno 所示设置. EACCES 访问被拒绝:文件权限的设置不允许指定的访问权限. ENOENT 未找到文件名或

  • 用VC++6.0的控制台实现2048小游戏的程序

    首先感谢这位大侠的无私分享,仔细学习这个程序以后收获很多,试着添加一些注释 源程序是从开源中国看到的,原作者是 刘地(sir?) 地址为http://www.oschina.net/code/snippet_593413_46040 geek_monkey于2015年3月5日为拜读该程序,受益匪浅 为了方便自己,以及更多初学者阅读,我试着写了写了注释供参考 我是C语言初学者,如有错误希望指正.轻喷 复制代码 代码如下: #include <stdlib.h> #include <stdi

  • VC++在TXT文件指定位置追加内容的方法

    本文实例讲述了VC++操作文本文件的方法,实现在txt文件指定位置插入内容.对于VC++爱好者有一定的学习参考价值. 主要功能代码如下: void CGoToFileDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon

  • VC++实现文件与应用程序关联的方法(注册表修改)

    本文实例讲述了VC++实现文件与应用程序关联的方法.分享给大家供大家参考,具体如下: 日常工作中,doc文件直接双击后,就能启动word软件,并读取该文档的内容在软件中显示,这都得益于注册表的配置,我们的软件也需要实现这样的功能,该如何写注册表以及写入哪些内容呢?下面的两个函数就能实现这个功能.CheckFileRelation是检查注册表中是否已经将我们期待的文件格式与相应软件关联了:RegisterFileRelation是直接往注册表中写入相关的key和value. /**********

  • 浅析VC++中的头文件包含问题

    在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用(不满足继承关系,而是组合关系).也就是需要互相声明.好了,这时候会带来一些混乱.如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已的处理办法: 编码时,我们一般会尽量避免include头文件,而是采用声明 class XXX.但有时候还是必须用Include头文件,那么,两者的划分在于什么呢? 应该是很明确的,但书上好像都少有提及. 首先:我们要明白为什么要用声明取代头文件包含:对了,是为了避免无必要的重编译(在头文件发生变更

  • VC++基于Dx实现的截图程序示例代码

    本文所述的程序示例为VC++图象特效的截图示例,需要DirectX 3.0以上版,代码中的GetScreen函数是本截图程序的关键.运行这个程序可用Esc键结束.代码中需要ddutil.h与ddutil.cpp文件,请自行下载添加.关于InitDDraw()函数,功能是初始化DirectDraw环境,创建换页链(主页面,一个后台缓冲区),以及创建一个定时器. 具体的功能代码如下: #include <windows.h> #include <windowsx.h> #include

  • VC++实现程序开机启动运行的方法

    本文所述实例主要介绍如何在VC++下让程序开机自动运行的方法.一般而言添加到开机启动项,这是很多程序都有的做法,具体实现思路是利用win.in文件实现相关程序的开机自动启动.主要是通过WritePrivateProfileString函数来实现.下面来看这一功能的实现方法. 主要功能代码如下: HCURSOR CAutoRunDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CAutoRunDlg::OnBrowse() { //

随机推荐