废话不多说,直接搞起,打开vs2010,建立一个安装项目,如下图

vs打包成docker_VS2010-打包


点击setup1项目,然后点击右侧的属性

会出现如下界面,你可以在里面设置公司名称、产品名称、安装语言等:

vs打包成docker_快捷键_02


设置好后,便可以添加待安装的文件,右击项目->视图->文件系统,会出现文件系统,右击“应用系统文件夹 ”添加待打包的文件,

给打包程序建立快捷方式:如下图:

vs打包成docker_ide_03


在这里可以给程序建立一个卸载快捷键,右击“应用程序文件夹”添加文件“msiexec.exe”并建立快捷键,如下图:

vs打包成docker_System_04


右击“用户的程序菜单”,添加一个文件夹,并将先前建立快捷键移动到此文件夹内,此文件夹在安装包安装后会出现在开始菜单,再按照之前的方法建立一个程序启动快捷键,移动至“用户桌面”目录下;这是需要给这些快捷键添加图标,具体操作如下图:

vs打包成docker_System_05


vs打包成docker_System_06


除此之外,需要给卸载快捷键加一个额外的操作,进入卸载快捷键属性窗口,在”arguement”中添加“/x {FF5D1DDF-C30B-452A-83F7-9626E7BCB436}”其中“{FF5D1DDF-C30B-452A-83F7-9626E7BCB436}”为setup1属性窗口中的productcode:

vs打包成docker_System_07


这时,待打包的文件及对其的操作便进行好了,我们还需对setup1做一些操作,右击setup1,选择属性,设置系统必备(注:这里根据个人需求去添加):

vs打包成docker_vs打包成docker_08


vs打包成docker_快捷键_09


如果还需要设置启动条件,这里以设置.net4.0为启动条件为例,右击setup1,选择“视图->启动条件”弹出启动条件界面,右击“启动条件”可以添加启动条件,这里选择.net启动条件,右击属性,设置version为.net4.0。这时,启动条件便设置好。

这时简单的安装包便制作好了,如果你想在安装过程中或卸载过程中做一些处理,则需要进行如下操作:

1、在解决方案下新建一个类库项目,并在类库项目中添加一个安装程序类,具体命名可以自己定:具体操作可见下面代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;


namespace HisignInstaller
{
    [RunInstaller(true)]
    public partial class HisignInstaller : System.Configuration.Install.Installer
    {
        /// <summary>
        /// 标志是否首次添加注册表
        /// </summary>
        private bool isFirstAdd = true;
        string sourcePath = "empty";
        string path = string.Empty;
        public string zippath = string.Empty;
        public string presetConfigFile = string.Empty;
        public HisignInstaller()
        {
            InitializeComponent();

        }
        protected override void OnAfterInstall(IDictionary savedState)
        {
            try
            {
                //是在安装部署项目里自定义操作的属性中通过设置CustomActionData属性为/Path="[TARGETDIR]\"得到的,就是用户选择的路径。
                path = Context.Parameters["Path"];
                path = path.TrimEnd('\''); 
                if (path.EndsWith("\\\\"))
                {
                    path = path.Replace("\\\\", "\\");
                }
                int a = path.IndexOf("\'");
               // int b = path.LastIndexOf("\"");
                path = path.Substring(a + 1, path.Length - a - 1);

                //MSI目录,CustomActionData属性为/SourcePath="[SOURCEDIR]\"
                sourcePath = Context.Parameters["SourcePath"].TrimEnd('\'');
                sourcePath = sourcePath.TrimEnd('\\') + "\\";
                int sourcea = sourcePath.IndexOf("\'");
                //int sourceb = sourcePath.LastIndexOf("\"");
                sourcePath = sourcePath.Substring(sourcea + 1, sourcePath.Length - sourcea - 1);
               string[] presetConfigFileArr = Directory.GetFiles(sourcePath, "Configuation*.*", SearchOption.TopDirectoryOnly);
                string configFile = Path.Combine(path, "HisignVideo\\Client\\Configuation.xml");

                if (presetConfigFileArr != null && presetConfigFileArr.Length > 0) //存在预置配置文件,直接拷贝
                {
                    try
                    {
                        presetConfigFile = presetConfigFileArr[0];

                        File.Copy(presetConfigFile, configFile, true);//将安装包同级目录拷贝到安装目录
                    }
                    catch (Exception ex)
                    {

                    }
                }
                string appPath = Path.Combine(path, "HisignVideo\\Client\\ConDemoWPF.exe");
                string appkey = "Hisign\\ConDemoWPF";
                string _key = "AppPath";
                AddDecodersReg(appPath, appkey, _key);//写注册表
                string ZipPath = Path.Combine(path, "HisignVideo\\decoders.zip");
                zippath = Path.Combine(path, "HisignVideo");
                bool IsSuccess = UnZipCommonMethod(ZipPath);
                if (IsSuccess)
                {
                    string filePath = Path.Combine(path, "HisignVideo\\decoders");
                    string DestPath = GetChromeConfigurePath();
                    if (!Directory.Exists(DestPath))
                    {
                        Directory.CreateDirectory(DestPath);
                    }
                    try
                    {
                        CopyFiles(filePath, DestPath, true, true);
                        string appkeyDecode = "Visystem\\SoftCodec";
                        string _keyDecode = "PlugPath";
                        DestPath = DestPath + "\\";
                        AddDecodersReg(DestPath, appkeyDecode, _keyDecode);
                        string BatFile = Path.Combine(path, "HisignVideo\\reg_decoder.bat");
                        if (File.Exists(BatFile))
                        {
                            RunBat(BatFile);
                        }
                        ChangeFileAttributes(filePath);
                        Directory.Delete(filePath, true);
                    }
                    catch (Exception ex)
                    {

                    }

                }
            }
            catch (Exception ex)
            {

            }
            finally
            {

            }
        }
        /// <summary>
        /// 更改文件属性
        /// </summary>
        /// <param name="dirPath">文件夹路径</param>
        private void ChangeFileAttributes(string dirPath)
        {
            try
            {
                DirectoryInfo thisDic = new DirectoryInfo(dirPath);
                FileInfo[] fileInfo = thisDic.GetFiles();
                foreach (FileInfo NextFile in fileInfo)  //遍历文件
                {
                    File.SetAttributes(NextFile.FullName, FileAttributes.Normal);
                }
                foreach (DirectoryInfo NextDic in thisDic.GetDirectories())
                {
                    ChangeFileAttributes(NextDic.FullName);
                }
            }
            catch (Exception ex)
            {

            }
        }
        /// <summary>
        /// 解压文件
        /// </summary>
        /// <param name="fileName"></param>
        bool UnZipCommonMethod(string fileName)
        {
            try
            {
                //presetConfigFile = presetConfigFile.Substring(0, presetConfigFile.LastIndexOf("\\"));
                string unZipExe = Path.Combine(path, "HisignVideo\\7z.exe");
                ZipFile zipFile = new ZipFile(unZipExe);
                string outPut = string.Empty;
                bool isSucess = zipFile.UnCompress(fileName, zippath, out outPut);

                return isSucess;
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        //判断操作系统是否为WindowsXP
        public static bool IsWindowsXP
        {
            get
            {
                return (Environment.OSVersion.Platform == PlatformID.Win32NT)
                            && (Environment.OSVersion.Version.Major == 5)
                            && ((Environment.OSVersion.Version.Minor == 1)
                             || (Environment.OSVersion.Version.Minor == 2));
            }
        }
        /// <summary>
        /// 获取浏览器配置文件根目录
        /// </summary>
        /// <returns></returns>
        public static string GetChromeConfigurePath()
        {
            string filePath = string.Empty;

            if (IsWindowsXP)
            {
                filePath = Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "Application Data\\decoders");
            }

            else
            {
                filePath = Path.Combine(Environment.GetEnvironmentVariable("AppData"), "decoders");
            }

            return filePath;
        }
        /// <summary>
        /// 运行bat文件
        /// </summary>
        /// <param name="batPath"></param>
        public static void RunBat(string batPath)
        {
            Process pro = new Process();

            FileInfo file = new FileInfo(batPath);
            pro.StartInfo.WorkingDirectory = file.Directory.FullName;
            pro.StartInfo.FileName = batPath;
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.CreateNoWindow = true;
            pro.StartInfo.Verb = "runas";
            pro.Start();
            pro.WaitForExit();
        }
        /// <summary>  
        /// 复制指定目录的所有文件  
        /// </summary>  
        /// <param name="sourceDir">原始目录</param>  
        /// <param name="targetDir">目标目录</param>  
        /// <param name="isOverWrite">如果为true,覆盖同名文件,否则不覆盖</param>  
        /// <param name="isCopySubDir">如果为true,包含子目录,否则不包含</param>  
        public static void CopyFiles(string sourceDir, string targetDir, bool isOverWrite, bool isCopySubDir)
        {
            try
            {
                //复制当前目录文件  
                foreach (string sourceFileName in Directory.GetFiles(sourceDir))
                {
                    string targetFileName = Path.Combine(targetDir, Path.GetFileName(sourceFileName));

                    if (File.Exists(targetFileName))
                    {
                        if (isOverWrite)
                        {
                            File.SetAttributes(targetFileName, FileAttributes.Normal);
                            File.Copy(sourceFileName, targetFileName, isOverWrite);
                        }
                    }
                    else
                    {
                        File.Copy(sourceFileName, targetFileName, isOverWrite);
                    }
                }
                //复制子目录  
                if (isCopySubDir)
                {
                    foreach (string sourceSubDir in Directory.GetDirectories(sourceDir))
                    {
                        string targetSubDir = Path.Combine(targetDir, sourceSubDir.Substring(sourceSubDir.LastIndexOf("\\") + 1));
                        if (!Directory.Exists(targetSubDir))
                            Directory.CreateDirectory(targetSubDir);
                        CopyFiles(sourceSubDir, targetSubDir, isOverWrite, true);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 将安装目录写入注册表
        /// </summary>
        /// <param name="basePath">安装根目录</param>
        private void AddDecodersReg(string basePath, string keypath, string key)
        {
            try
            {
                bool is64 = Environment.Is64BitOperatingSystem;
                if (is64)
                {
                    Reg64Decoders(basePath, keypath, key);
                }
                else
                {
                    Reg32Decoders(basePath, keypath, key);
                }
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 64位系统修改注册表
        /// </summary>
        /// <param name="basePath"></param>
        private void Reg64Decoders(string basePath, string pcontent, string Key)
        {
            string decodersPath = basePath;
            string pathHead = "SOFTWARE\\WOW6432Node";
            //string pathContent = "Hisign\\ConDemoWPF";
            string pathContent = pcontent;
            // string keyVal = "AppPath";
            string keyVal = Key;
            RegistryKey key = null;
            RegistryKey software = null;
            RegistryKey softCodec = null;

            try
            {
                key = Registry.LocalMachine;
                software = key.OpenSubKey(pathHead, true);
                if (software == null)
                {
                    key.CreateSubKey(pathHead);
                    software = key.OpenSubKey(pathHead);
                }

                softCodec = software.OpenSubKey(pathContent, true);
                if (softCodec == null)
                {
                    software.CreateSubKey(pathContent);
                    softCodec = software.OpenSubKey(pathContent);
                }

                softCodec.SetValue(keyVal, decodersPath, RegistryValueKind.String);
                softCodec.Close();
                software.Close();
                key.Close();
            }
            catch (Exception ex)
            {
                //64位的首次添加可能失败,需在添加一次
                if (isFirstAdd)
                {
                    isFirstAdd = false;

                    if (softCodec != null)
                    {
                        softCodec.Close();
                    }

                    if (software != null)
                    {
                        software.Close();
                    }

                    if (key != null)
                    {
                        key.Close();
                    }

                    Reg64Decoders(basePath, pcontent, Key);
                    return;
                }

                if (softCodec != null)
                {
                    softCodec.Close();
                }

                if (software != null)
                {
                    software.Close();
                }

                if (key != null)
                {
                    key.Close();
                }

            }
        }
        /// <summary>
        /// 32位系统修改注册表
        /// </summary>
        /// <param name="basePath"></param>
        private void Reg32Decoders(string basePath, string pcontent, string Key)
        {
            string decodersPath = basePath;
            // string pathReg = "SOFTWARE\\Hisign\\ConDemoWPF";
            string pathReg = "SOFTWARE\\" + pcontent;
            // string keyVal = "AppPath";
            string keyVal = Key;
            RegistryKey key = null;
            RegistryKey software = null;

            try
            {
                key = Registry.LocalMachine;
                software = key.OpenSubKey(pathReg, true);
                if (software == null)
                {
                    key.CreateSubKey(pathReg);
                    software = key.OpenSubKey(pathReg, true);
                }

                software.SetValue(keyVal, decodersPath, RegistryValueKind.String);
                software.Close();
                key.Close();
            }
            catch (Exception ex)
            {

                if (software != null)
                {
                    software.Close();
                }

                if (key != null)
                {
                    key.Close();
                }

            }
        }
    }
}

这段代码是我在安装包安装过程中做的一些操作,如拷贝与安装包同级目录下的文件到安装目录下,将程序的装路径写入注册表等,
如果你想在卸载时也做一些处理,也可以建立一类库并添加一个安装程序类,卸载处理的代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;
using System.ServiceProcess;


namespace HisignUnInstaller
{
    [RunInstaller(true)]
    public partial class HisignUnInstaller : System.Configuration.Install.Installer
    {
        object pathValue = new object();
        public HisignUnInstaller()
        {
            InitializeComponent();
        }
        protected override void OnBeforeUninstall(IDictionary savedState)
        {
            try
            {
                Process[] _process = Process.GetProcesses();
                foreach (Process ps in _process)
                {
                    if (ps.ProcessName.Equals("ConDemoService"))
                    {
                        ps.Kill();
                    }
                }
                using (ServiceController sc = new ServiceController("ConAnalysisService"))
                {
                    if (sc != null)
                    {
                        if (sc.Status.Equals(ServiceControllerStatus.Running))
                        {
                            sc.Stop();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            base.OnBeforeUninstall(savedState);
        }
        protected override void OnAfterUninstall(System.Collections.IDictionary savedState)
        {
            base.OnBeforeUninstall(savedState);
            try
            {
                bool is64 = Environment.Is64BitOperatingSystem;
                if (is64)
                {
                    pathValue = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Hisign\\ConDemoWPF", "AppPath", null);
                }
                else
                {
                    pathValue = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Hisign\\ConDemoWPF", "AppPath", null);
                }
                if (pathValue != null)
                {
                    string pathReg = "Hisign\\ConDemoWPF";
                    DeleteDecodersReg(pathReg);
                }


            }
            catch (Exception ex)
            {

            }
            finally
            {

            }
            base.OnAfterUninstall(savedState);
        }
        /// <summary>
        /// 将安装目录从注册表中删除
        /// </summary>
        /// <param name="basePath">安装根目录</param>
        private void DeleteDecodersReg(string basePath)
        {
            bool is64 = Environment.Is64BitOperatingSystem;
            if (is64)
            {
                Delete64Decoders(basePath);
            }
            else
            {
                Delete32Decoders(basePath);
            }
        }
        /// <summary>
        /// 32位系统删除注册表
        /// </summary>
        private void Delete32Decoders(string pathReg)
        {
            try
            {
                string keyVal = "AppPath";
                RegistryKey key = null;
                RegistryKey software = null;
                RegistryKey softhisignkey = null;
                RegistryKey softsmallkey = null;
                string softpath = "SOFTWARE";
                string[] _pathReg = pathReg.Split('\\');
                key = Registry.LocalMachine;
                software = key.OpenSubKey(softpath, true);
                if (software == null)
                {
                    return;
                }
                softhisignkey = software.OpenSubKey(_pathReg[0], true);
                if (softhisignkey == null)
                {
                    return;
                }
                softsmallkey = softhisignkey.OpenSubKey(_pathReg[1], true);
                if (softsmallkey == null)
                {
                    return;
                }
                if (!IsRegeditKeyExist(softsmallkey, keyVal))
                {
                    return;
                }
                softsmallkey.DeleteValue(keyVal);
                softsmallkey.Close();
                softhisignkey.Close();
                software.Close();
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 64位系统删除注册表
        /// </summary>
        /// <param name="pathReg"></param>
        private void Delete64Decoders(string pathReg)
        {
            string keyVal = "AppPath";
            RegistryKey key = null;
            RegistryKey software = null;
            pathReg = "SOFTWARE\\WOW6432Node\\" + pathReg;
            key = Registry.LocalMachine;
            software = key.OpenSubKey(pathReg, true);
            if (software == null)
                return;
            //IsRegeditItemExist(software)
            if (!IsRegeditKeyExist(software, keyVal))
                return;
            software.DeleteValue(keyVal);
            software.Close();
        }
        /// <summary>
        /// 判断键值是否存在
        /// </summary>
        /// <param name="RegBoot"></param>
        /// <param name="RegKeyName"></param>
        /// <returns></returns>
        private bool IsRegeditKeyExist(RegistryKey RegBoot, string RegKeyName)
        {
            string[] subkeyNames;
            try
            {
                subkeyNames = RegBoot.GetValueNames();
                foreach (string keyName in subkeyNames)
                {
                    if (keyName.Equals(RegKeyName))  //判断键值的名称
                    {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                return false;
            }

        }
    }
}

这里只是去删除注册表,关闭某些服务等。我在这只是给出一些实例,大家可以根据自己的需求去写里面的代码。当然大家不要以为做了这些在程序包安装或卸载时就可以执行大家想做的处理了,这里还需要额外的操作,具体如下:

1、右击“setup1”选择“添加->项目输出”,会弹出一界面,选中建的类库,作为“主输出”点击确定

vs打包成docker_ide_10


2、右击“setup1”选择“视图->自定义操作”,会弹出自定义操作界面,如果你想在安装时做一些处理,右击“安装”,选择“添加自定义”,如下图:

vs打包成docker_ide_11


在查找范围中选择“应用程序文件夹”选中“主输出来自Installer1(活动)”点击确定,添加自定义成功,右击此自定义操作,选择属窗口,在“CustomActiondata”中添加“/Path=”’[TARGETDIR]\’” /SourcePath=”’[SOURCEDIR]\’””。最后点击生成,即完成打包所有操作。