WPF 自己动手来做安装卸载程序

原文:WPF 自己动手来做安装卸载程序

前言

说起安装程序,这也许是大家比较遗忘的部分,那么做C/S是小伙伴们,难道你们的程序真的不需要一个炫酷的安装程序么?

 

声明在先

本文旨在教大家以自己的方式实现安装,至于炫酷部分概不负责.

 

剖析

我们经常安装形形色色的程序,而碰到的安装步骤基本可概括为一下几种

1,欢迎界面 - 无剖析可言

2,选择路径页 - 无剖析可言

3,安装页 - 包括解压、添加注册表

4,完成页 - 创建快捷方式、开机启动、运行

根据实际使用不同适当修改.

经过剖析我们发现,其实一个高大上的安装程序真的没有技术可言,其实就是一个解压操作,写入注册表而已!!!

 

那么根据剖析结果我们一步一步去实现安装

 

解压

这里使用第三方的ICSharpCode.SharpZipLib.Zip进行解压,

具体用法大家可以自行搜索了解,这里贴一个现成的方法

/// <summary>
        /// 解压缩文件
        /// </summary>
        /// <param name="sourceFile">源目录</param>
        /// <param name="destinationFile">目标目录</param>
        public void DeCompressFile(string sourceFile, string destinationFile, Action call)
        {
            try
            {
                if (!System.IO.File.Exists(sourceFile))
                {
                    return;
                }

                if (Directory.Exists(destinationFile))
                {
                    Directory.Delete(destinationFile, true);
                }

                // 读取压缩文件(zip文件),准备解压缩
                ZipInputStream s = new ZipInputStream(System.IO.File.OpenRead(sourceFile.Trim()));
                ZipEntry theEntry;
                string path = destinationFile;

                // 解压出来的文件保存的路径
                string rootDir = " ";

                // 根目录下的第一个子文件夹的名称
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    rootDir = System.IO.Path.GetDirectoryName(theEntry.Name);

                    // 得到根目录下的第一级子文件夹的名称
                    if (rootDir.IndexOf("\\") >= 0)
                    {
                        rootDir = rootDir.Substring(0, rootDir.IndexOf("\\") + 1);
                    }
                    string dir = System.IO.Path.GetDirectoryName(theEntry.Name);

                    // 根目录下的第一级子文件夹的下的文件夹的名称
                    string fileName = System.IO.Path.GetFileName(theEntry.Name);

                    // 根目录下的文件名称
                    if (dir != " ")
                    // 创建根目录下的子文件夹,不限制级别
                    {
                        if (!Directory.Exists(destinationFile + "\\" + dir))
                        {
                            path = destinationFile + "\\" + dir;

                            // 在指定的路径创建文件夹
                            Directory.CreateDirectory(path);
                        }
                    }
                    else if (dir == " " && fileName != "")
                    // 根目录下的文件
                    {
                        path = destinationFile;
                    }
                    else if (dir != " " && fileName != "")
                    // 根目录下的第一级子文件夹下的文件
                    {
                        // 指定文件保存的路径
                        if (dir.IndexOf("\\") > 0)
                        {
                            path = destinationFile + "\\" + dir;
                        }
                    }

                    // 判断是不是需要保存在根目录下的文件
                    if (dir == rootDir)
                    {
                        path = destinationFile + "\\" + rootDir;
                    }

                    // 以下为解压缩zip文件的基本步骤
                    // 基本思路就是遍历压缩文件里的所有文件,创建一个相同的文件。
                    if (fileName != String.Empty)
                    {
                        FileStream streamWriter = System.IO.File.Create(path + "\\" + fileName);

                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = s.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                streamWriter.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }

                        streamWriter.Close();
                    }
                }
                s.Close();
                call.Invoke();
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }

 

注册表

相信有些同学对安装注册表这块不太了解,你可以打开控制面板-程序和功能看到你所安装的程序都出现在这里,那么是怎么出现在这里的呢?

其实就是在注册表SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall的位置添加了应用的信息,当然我们的程序也不例外,

可以根据其它程序的注册信息研究发下,如下几个节点

/// <summary>
        /// 注册应用信息
        /// </summary>
        /// <param name="setupPath">安装路径</param>
        public void AddRegedit(string setupPath)
        {
            try
            {
                RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", true);
                RegistryKey software = key.CreateSubKey(RegeditKey);

                // 图标
                software.SetValue("DisplayIcon", setupPath + "\\" + AppExe);

                // 显示名
                software.SetValue("DisplayName", DisplayName);

                // 版本
                software.SetValue("DisplayVersion", Version);

                // 程序发行公司
                software.SetValue("Publisher", Publisher);

                // 安装位置
                software.SetValue("InstallLocation", setupPath);

                // 安装源
                software.SetValue("InstallSource", setupPath);

                // 帮助电话
                // software.SetValue("HelpTelephone", "123456789");

                // 卸载路径
                software.SetValue("UninstallString",setupPath + "/uninstall.exe");                software.Close();                key.Close();                } catch (Exception) { } }

可对应写入自己程序信息,这里重点说一下UninstallString,这个值为卸载程序的指向,即在控制面板-程序和功能里选择卸载时调用的程序

原则上来说,我们有安装那么就需要对应的写一个卸载程序(用来删除注册表,程序目录,快捷等等)这里不做赘述

 

创建快捷方式

/// <summary>
        /// 创建快捷方式
        /// </summary>
        /// <param name="setupPath">安装目录</param>
        /// <param name="isDesktop">是否创建到桌面(默认创建到安装目录)</param>
        public void CreateLnk(string setupPath, bool isDesktop)
        {
            string path = setupPath;

            if (isDesktop)
            {
                path = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory);
            }

            // 注:如果桌面有现准备创建的快捷键方式,当程序执行创建语句时会修改桌面已有快捷键方式,程序不会出现异常

            WshShell shell = new WshShell();

            // 快捷键方式创建的位置、名称
            IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(path + "\\" + DisplayName + ".lnk");

            // 目标文件
            shortcut.TargetPath = setupPath + "\\" + AppExe;

            // 该属性指定应用程序的工作目录,当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
            shortcut.WorkingDirectory = setupPath;// System.Environment.CurrentDirectory;

            // 目标应用程序的窗口状态分为普通、最大化、最小化【1,3,7】
            // shortcut.WindowStyle = 1; 

            // 描述
            shortcut.Description = Description;

            // 快捷方式图标
            shortcut.IconLocation = setupPath + "\\" + AppIco;

            shortcut.Arguments = "";

            // 快捷键
            //shortcut.Hotkey = "CTRL+ALT+F11"; 

            // 保存
            shortcut.Save();
        }

 

开机启动

而开机启动无非也就是在在注册表的指定位置去添加启动

我这里开机启动的时候调用的是快捷方式,而非exe程序

/// <summary>
        /// 添加开机启动
        /// </summary>
        /// <param name="setupPath">安装目录</param>
        public void AddRun(string setupPath)
        {
            try
            {
                RegistryKey runkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);

                // 打开注册表子项
                if (runkey == null)

                // 如果该项不存在的话,则创建该子项
                {
                    runkey = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                }

                // 设置为开机启动
                runkey.SetValue(RegeditKey, "\"" + setupPath + "\\" + DisplayName + ".lnk\"");
                runkey.Close();
            }
            catch (Exception)
            {

            }
        }

 

运行

public void RunApp(string setupPath)
        {
            System.Diagnostics.Process.Start(setupPath + "\\" + DisplayName + ".lnk");
        }

做完安装后,你会想我最终其实只想得到一个安装的exe程序,而非安装程序的整个文件列表,对于这里我也没找到太好的解决方案,只能通过WinRar等程序把这个包压缩成一个可执行程序.

 

完结

至此我们炫酷的安装程序就结束了,怎么又提炫酷,好的好的,这篇文章根本就没提界面的事情~!

需要注意一下,因涉及到注册表操作,所以我们的安装程序是需要以管理员身份运行的(设置程序以管理员身份运行的方法自行搜索).

 

如有需要demo的同学可以留下邮箱,一星期左右发出(现在没有现成的demo).如果你觉得这篇文章写的可以不妨推荐一下.

时间: 2024-10-24 20:04:28

WPF 自己动手来做安装卸载程序的相关文章

谁能给我讲讲:程序安装或者卸载时,安装/卸载程序通常会进行哪些“秘密”的操作

问题描述 我只知道有些程序安装时会修改注册表,别的什么的就不知道了,谁给揭示下其中的这些不为人知的秘密啊? 解决方案 解决方案二:我看到分数就进来了楼主你对秘密操作的定义是怎样的?解决方案三:都是自己写的脚本.解决方案四:解压.复制.更改注册表.删除文件.初始化.注册服务,还有很多可以做的事情--解决方案五:安装.卸载时你可能认为的秘密操作都可能会有,安装或卸载的同时就可以执行.启动相应的程序,这些程序有的会成为服务,有的会修改注册表,有的一系列过程会执行批处理,有的可能植入木马,当然这个是被别

卸载程序

问题描述 C# 做的卸载程序,运行时出现上面的框是怎么回事以下为卸载程序classProgram{staticvoidMain(string[]args){stringsysroot=System.Environment.SystemDirectory;System.Diagnostics.Process.Start(sysroot+"\msiexec.exe","/x{1D347776-01DD-4F8B-A9DC-A10D0A4E7871}/qr");} 解决方

软件-卸载程序显示未正确安装

问题描述 卸载程序显示未正确安装 软件做了个卸载程序,就是删除文件,快捷方式,注册表.结果卸载完成后弹出个对话框显示This Program Might Not Have Installed Correctly.这个是什么情况啊 解决方案 你用的什么打包工具?估计不兼容,用installshield的新版本 解决方案二: 这个程序可能没有正确的安装好~ 你肯定还是没有完全卸载好,仔细看看,或者用一些智能卸载软件,帮你一键搞定 解决方案三: 1 打包工具的问题2 你使用打包工具的问题具体是什么原因

用自删除dll实现应用程序的安装/卸载代码

[译者]:本文译自 Alex Tilles 在 Windows Developer Network (2003 第12期)发表的一篇文章:"Writing Your Own Install and Uninstall Code".这是一篇具有一定技术含量的文章,相信许多开发人员都需要本文介绍的技术,其中包括几个重要的技术点: Rundll32.exe 实用程序的使用方法: DLL 或 EXE 的自删除技术: 嵌入资源的处理技巧: LZCOPY API 使用示范: compress.ex

Android 静默方式实现批量安装卸载应用程序的深入分析_Android

前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分API是隐藏的,所以必须在ubuntu下下载Android系统源码,并编译之后使用MM命令编译生成APK文件,其实也难. 思路是这样的,在XX/packages/apps目录下有一个PackageInstaller的应用程序,Android机器中安装卸载都是由这个应用程序完成的.但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考PakcageInstaller里面的安装卸

Android 静默方式实现批量安装卸载应用程序的深入分析

前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分API是隐藏的,所以必须在ubuntu下下载Android系统源码,并编译之后使用MM命令编译生成APK文件,其实也难. 思路是这样的,在XX/packages/apps目录下有一个PackageInstaller的应用程序,Android机器中安装卸载都是由这个应用程序完成的.但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考PakcageInstaller里面的安装卸

迅雷显示“先前程序的安装/卸载未完成”

原因:安装时出现如下情况, 先前程序的安装/卸载未完成.您需要重新启动您的电脑才能完成安装. 在重新启动电脑后,在完成 迅雷 的安装. 安装程序无法继续.请单击"取消"退出. 解决办法: 开始 - 运行 - regedit - HKEY_LOCAL_MACHINESYSTEMControlSet001ControlSession Manager 找到根目录里面的 PendingFileRenameOperations. 删除它即可! 总结:出现其它类似问题参照该方法!

Aura下如何安装或卸载程序

  操作步骤: 如何下载安装程序: 在桌面找到"Aura"图标; 左键双击打开后,即可看到下面的界面,然后找到"乐商店"打开应用商店; 打开后我们可以看到,在左右各有三个选项.左侧的三个选项为下载程序的分类; 找到自己需要的程序后,点击直接选择"下载"即可; 如果需要搜索某程序,可以在右侧选择"搜索",输入要搜索的名称即可. 如何卸载程序: 点击右侧的"应用管理",打开后左侧是已安装的程序,右侧为正在下载程

c++ 客户端-安装与卸载程序存在兼容性问题?

问题描述 安装与卸载程序存在兼容性问题? 使用C++开发的windows客户端安装与卸载程序,运行在部分win7系统时,有时会提 示存在兼容性问题,很是恼人.我现在怀疑是写组测表不成功或者写的不全导致这个问题,但不是很确定.这个问题该怎么解决??? 解决方案 用VC++ 2010或者更新版本编译,用InstallShield 20以上打包. 解决方案二: 如果你的程序访问注册表等,需要权限,需要启用uac http://blog.csdn.net/whatday/article/details/