使用C#自制一个Windows安装包的详细过程

 更新时间:2024年07月31日 10:18:04   作者:△曉風殘月〆  
这篇文章主要介绍了如何使用C#自制一个Windows安装包,文中通过图文结合的方式给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

以前都在用InstallShield制作安装包,基本需求是能满足的,但也有一些缺点:

1、界面不能完全定制

2、不能直接调用代码里的功能

平常使用一些其它软件,觉得安装界面挺炫的,类似下面这种。

其实安装的过程主要就是解压文件,注册文件等。所以想自己封装一个简易的安装工具,实现界面的完全定制。

使用.Net Framework开发安装包美中不足的就是需要依赖.Net Framework Runtime ,像上面这种不知道是用什么技术开发的,完全不需要依赖任何运行时。

好在Windows 10及以上版本都自带了.Net Framework。

我这里主要实现以下基本安装包功能

1、释放文件

2、安装依赖

3、注册COM组件

4、创建桌面快捷方式/开机启动

5、创建控制面板卸载程序项

6、安装进度及状态显示

效果如下:

释放文件

这里我直接将需要释放的文件压缩成zip文件,然后放到工程的资源文件中去。通过解压 到指定路径的形式来完成释放功能。

主要用到ZipArchive类

这里的fileBuffer就是资源里的压缩包

代码如下:

using (MemoryStream ms = new MemoryStream(fileBuffer))
                {
                    var zipArchive = new ZipArchive(ms);

                    foreach (var item in zipArchive.Entries)
                    {
                        //创建文件夹操作

                        //文件判断操作

                        //解压
                        item.ExtractToFile(destFileName, true);

                      }
                    }
                }

安装依赖

这里主要借助依赖库安装程序自身的命令行参数来完成。

像Microsoft Visual C++ 2015-2022 Redistributable (x64) ,可以通过/install /passive来进行直接安装。

一般来说大部分的依赖库可以通过 参数 /?进行查看

如果是 .msi格式的安装包 ,可以直接通过msiexec.exe来进行安装。

注册COM组件

直接调用regsvr32.exe /s执行安静注册即可

System.Diagnostics.Process.Start("regsvr32.exe", dllPath + " /s");

创建桌面快捷方式/开机启动

创建桌面快捷方式需要用到一个COM组件Windows Script Host Object。在项目中直接引用 即可

使用代码如下:

这里的exePath就是程序释放到的路径 如D:\install\xxx.exe

shotcutPath就是快捷方式的路径,如 C:\User\xx\Desktop\xxx.lnk

private static void InternalCreateShortcut(string exePath, string shotcutPath)
        {
            try
            {
                WshShell shell = new WshShell();
                var exeName = System.IO.Path.GetFileNameWithoutExtension(exePath);
                IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath);
                shortcut.TargetPath = exePath;  //目标路径
                shortcut.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath); //工作目录
                shortcut.WindowStyle = 1;
                shortcut.Description = exeName;  //描述
                shortcut.IconLocation = exePath + ",0";  //图标位置
                shortcut.Arguments = ""; //启动参数
                shortcut.Save();
            }
            catch (Exception ex)
            {

            }
        }

创建开机自启,

直接使用上面的函数,将lnk创建到 shell:Startup路径即可。

var shortcutPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk";

创建控制面板卸载程序项

这里主要对注册表进行操作

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

增加一个GUID项,代表产品ID。

然后在项下增加图中所示的键值

这里只需要增加一些常用的属性即可。上图是微软的安装程序创建的,我是直接参考上图创建。

完整的属性可以参考 Properties (Windows Installer) - Win32 apps | Microsoft Learn

我这里定义的数据结构如下:

public class SetupProperty
    {
        public string ProductId => "{C8997941-26F4-4E38-A5BD-D6306F0A8FC2}";  //我的产品ID
        public string Comments => "描述";
        public string Contact => "";
        public string DisplayIcon => System.Reflection.Assembly.GetExecutingAssembly().Location;
        public string DisplayName => "控制面板显示名称";
        public string DisplayVersion => VersionUtil.GetVersionString();
        public int EstimatedSize { get; set; }
        public string HelpLink => "";
        public string InstallDate => DateTime.Now.ToString();
        public string InstallLocation { get; set; }
        public string InstallSource { get; set; }
        public string UninstallString { get; set; }
        public string Publisher => "发布者";
    }

创建代码如下:

public void CreateUninstallInRegistry(SetupProperty setupProperty)
        {
                try
                {
                    var productKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{setupProperty.ProductId}");

                    foreach (var property in setupProperty.GetType().GetProperties())
                    {
                        if (property.Name == nameof(setupProperty.ProductId))
                            continue;

                        if (property.Name == nameof(setupProperty.EstimatedSize))
                        {
                            productKey.SetValue(property.Name, property.GetValue(setupProperty), Microsoft.Win32.RegistryValueKind.DWord);
                        }
                        else
                        {
                            productKey.SetValue(property.Name, property.GetValue(setupProperty), Microsoft.Win32.RegistryValueKind.String);
                        }
                    }
                }
                catch
                {

                }
        }

创建完成后就可以在控制面板看到自己添加的新项目。

这里需要注意的的UninstallString这个值就是在控制面板点击卸载时,系统执行的操作。文末的如何制作卸载程序这部分会说明如何设置UninstallString。

安装进度及状态显示

界面上放置一个progressbar,将每个阶段划分一定的比例,然后再计算tick,显示到progressbar上即可。

如何制作卸载程序

像微软的msi安装包安装后,都会缓存在

C:\ProgramData\Package Cache\{ProductId}\Installers

一些应用软件的msi安装包会缓存 在

C:\Users\x\AppData\Local\Downloaded Installations

之所以要缓存 ,因为后面卸载是需要用到这些安装包的,这里不做详细介绍,可以自行查找资料了解。

我这里也在安装完成后,将安装包缓存在C:\Users\x\AppData\Local\Downloaded Installations目录下。

然后在程序中增加一个卸载的命令行参数判断

public enum SetupType
    {
        Install,
        UnInstall
    }


 public partial class App : Application
    {
        public static SetupType SetupType = SetupType.Install;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            if (e.Args.Length > 0 && e.Args[0].ToUpper() == nameof(SetupType.UnInstall).ToUpper())
                SetupType = SetupType.UnInstall;
        }
    }

当程序以uninstall参数启动时,执行卸载。

在删除依赖库时,依旧是通过程序的命令行参数或msiexec来执行卸载。

像Microsoft Visual C++ 2015-2022 Redistributable (x64) 的卸载参数是/uninstall /passive

msiexec.exe的卸载参数是/uninstall {0} /qn

所以我们在安装完成后在设置注册表项的UninstallString键值时,需要设置为带uninstall的值。

假设产品id是{02A54AEC-9C54-4BAC-AAC7-FBA39DDC8381},安装程序的名称为setup.exe,UninstallString就设置为"C:\Users\x\AppData\Local\Downloaded Installations\setup.exe uninstall"

这样在控制面板中就能正确卸载。

最后需要注意的就是,像注册COM,创建注册表都是需要管理员权限 的,可以将程序设置为管理员权限运行。

示例代码

GitHub - zhaotianff/CustomInstaller: Simple custom installer

//还有一个64位系统下32位软件的注册表路径

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

以上就是使用C#自制一个Windows安装包的详细过程的详细内容,更多关于C#自制Windows安装包的资料请关注脚本之家其它相关文章!

相关文章

  • C#实现百度网站收录和排名查询功能思路及实例

    C#实现百度网站收录和排名查询功能思路及实例

    这篇文章主要介绍了C#实现百度网站收录和排名查询功能思路及实例,本文思路同样适用必应、搜狗、搜搜、360等搜索引擎,需要的朋友可以参考下
    2015-01-01
  • c# Winform 程序自动更新实现方法

    c# Winform 程序自动更新实现方法

    Winform程序自动更新我也是第一次做,网上找了自动更新的源码,后来又根据在网上看到的一些方法,自己试了很久,最终还是有写错误,所以花了钱让别人帮忙调试成功的,下面是我自己捣腾出来的,方便大家借鉴,如果有什么错误的地方欢迎指正
    2017-02-02
  • C# FileStream复制大文件功能

    C# FileStream复制大文件功能

    这篇文章主要为大家详细介绍了C# FileStream复制大文件功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • C#图片按比例缩放实例

    C#图片按比例缩放实例

    这篇文章主要为大家详细介绍了C#图片按比例缩放的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • 使用C#验证PDF数字签名有效性的方法示例

    使用C#验证PDF数字签名有效性的方法示例

    数字签名作为PDF文档中的重要安全机制,不仅能够验证文件的来源,还能确保文件内容在传输过程中未被篡改,本文将详细介绍如何使用免费.NET控件通过C#验证PDF签名的有效性以及验证PDF文档是否被修改,需要的朋友可以参考下
    2024-07-07
  • C#生成随机验证码代码分享

    C#生成随机验证码代码分享

    这篇文章主要分享了C#生成随机验证码代码,另外附上使用示例,非常的简单实用,有需要的朋友可以参考下
    2014-10-10
  • 深入了解c# 设计模式之简单工厂模式

    深入了解c# 设计模式之简单工厂模式

    这篇文章主要介绍了c# 设计模式之简单工厂模式的的相关资料,文中代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • C#温故而知新系列教程之闭包

    C#温故而知新系列教程之闭包

    闭包是将一些执行语句的封装,可以将封装的结果像对象一样传递,在传递时,这个封装依然能够访问到原上下文。下面这篇文章主要给大家介绍了关于C#中闭包的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-05-05
  • C#给Word不同页面设置不同背景

    C#给Word不同页面设置不同背景

    这篇文章主要介绍了C#给Word不同页面设置不同背景,文章图文讲解的很清晰,有对于这方面不懂得同学可以学习下
    2021-02-02
  • C#数字图像处理之图像二值化(彩色变黑白)的方法

    C#数字图像处理之图像二值化(彩色变黑白)的方法

    这篇文章主要介绍了C#数字图像处理之图像二值化(彩色变黑白)的方法,可实现图像从彩色转变为黑白的效果,非常具有实用价值,需要的朋友可以参考下
    2015-04-04

最新评论