如何使用C#自制一个Windows安装包

原文链接:https://www.cnblogs.com/zhaotianff/p/17387496.html

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

1、界面不能完全定制

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

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

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

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

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

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

1、释放文件

2、安装依赖

3、注册COM组件

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

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

6、安装进度及状态显示

效果如下:

释放文件

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

主要用到ZipArchive类

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

代码如下:

 1   using (MemoryStream ms = new MemoryStream(fileBuffer))
 2                 {
 3                     var zipArchive = new ZipArchive(ms);
 4 
 5                     foreach (var item in zipArchive.Entries)
 6                     {
 7                         //创建文件夹操作
 8 
 9                         //文件判断操作
10 
11                         //解压
12                         item.ExtractToFile(destFileName, true);
13 
14                       }
15                     }
16                 }

安装依赖

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

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

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

如果是 .msi格式的安装包 ,可以直接通过msiexec.exe来进行安装。可以参考https://www.cnblogs.com/zhaotianff/p/11558602.html

注册COM组件

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

1 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

 1      private static void InternalCreateShortcut(string exePath, string shotcutPath)
 2         {
 3             try
 4             {
 5                 WshShell shell = new WshShell();
 6                 var exeName = System.IO.Path.GetFileNameWithoutExtension(exePath);
 7                 IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath);
 8                 shortcut.TargetPath = exePath;  //目标路径
 9                 shortcut.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath); //工作目录
10                 shortcut.WindowStyle = 1;
11                 shortcut.Description = exeName;  //描述
12                 shortcut.IconLocation = exePath + ",0";  //图标位置
13                 shortcut.Arguments = ""; //启动参数
14                 shortcut.Save();
15             }
16             catch (Exception ex)
17             {
18                 
19             }
20         }

创建开机自启,

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

1  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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/870251.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【宝藏系列】模/数转换十大常用滤波算法

【宝藏系列】模/数转换十大常用滤波算法 文章目录 【宝藏系列】模/数转换十大常用滤波算法👨‍🏫ADC(Analog-to-Digital Converter,模数转换器)1️⃣限幅滤波法2️⃣中位值滤波法3️⃣算术平均滤波法4️⃣递推平均滤波…

AI学习记录 - 图像识别的基础入门

代码实现,图像识别入门其实非常简单,这里使用的是js,其实就是把二维数组进行公式化处理,处理方式如上图,不同的公式代表的不同的意义,这些意义网上其实非常多,这里就不细讲了。 const getSpecif…

Webshell管理工具:AntSword(中国蚁剑)

中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。 通俗的讲:中国蚁剑是 一 款比菜刀还牛的shell控制端软件。 一、中国蚁剑下载 1. 下载 AntSword-Loader https://github.com/AntSwordP…

(十九)原生js案例之h5地里位置信息与高德地图的初使用

h5 地里位置信息 1. 获取当前位置信息 window.onload function () {const oBtn document.querySelector("#btn");const oBox document.querySelector("#box");oBtn.onclick function () {window.navigator.geolocation.getCurrentPosition(function (…

STM32CubeIDE(CAN)

目录 一、概念 1、简述 2、CAN 的几种模式 二、实践 1、环回模式轮询通信 1.1 软件配置 1.2 代码编写 2、环回模式中断通信 2.1 软件配置 2.2 代码编写 一、概念 1、简述 STM32微控制器系列包含多个型号,其中一些型号集成了CAN(Controller Are…

如何在 Mac 上下载安装植物大战僵尸杂交版? 最新版本 2.2 详细安装运行教程问题详解

植物大战僵尸杂交版已经更新至2.2了,但作者只支持 Windows、手机等版本并没有支持 MAC 版本,最近搞到了一个最新的杂交 2.2 版本的可以在 Macbook 上安装运行的移植安装包,试了一下非常完美能够正常在 MAC 上安装运行,看图&#x…

菜鸟从0学微服务——MyBatis-Plus

关于“菜鸟从0学微服务” 针对有编程基础,开始学习微服务的同学,我们陆续推出从0学微服务的笔记分享。力求从各个中间件的使用来反思这些中间件的作用和优势。 会分享的比较快,会记录demo演算和中间件的使用过程,至于细节的理论…

SSIS_SQLITE

1.安装 SQLite ODBC 驱动程序 2.添加SQLite数据源 在“用户DSN”或“系统DSN”选项卡中,点击“添加”。选择“SQLite3 ODBC Driver”,然后点击“完成”。在弹出的配置窗口中,设置数据源名称(DSN),并指定S…

k8s核心知识总结

写在前面 时间一下子到了7月份尾;整个7月份都乱糟糟的,不管怎么样,日子还是得过啊, 1、7月份核心了解个关于k8s,iceberg等相关技术,了解了相关的基础逻辑,虽然和数开主线有点偏,但是…

二、【Python】入门 - 【PyCharm】安装教程

往期博主文章分享文章: 【机器学习】专栏http://t.csdnimg.cn/sQBvw 目录 第一步:PyCharm下载 第二步:安装(点击安装包打开下图页面) 第三步:科学使用,请前往下载最新工具及教程&#xff1a…

FreeSWITCH 1.10.10 简单图形化界面26-在网页上播放SIP设备视频

​ FreeSWITCH 1.10.10 简单图形化界面26-在网页上播放SIP设备视频 1、前言2、大概流程3、测试环境4、安装流媒体服务器5、设置流媒体服务器接口6、简单写个web接口7、测试一下1、web播放在线播放器1在线播放器2本地video控件 2、vlc播放vlc播放rtmpvlc播放rtsp 8、总结 1、前…

Jmeter三种方式获取数组中多个数据并将其当做下个接口参数入参【附带JSON提取器和CSV格式化】

目录 一、传统方式-JOSN提取器获取接口返回值 1、接口调用获取返回值 2、添加JSON提取器 3、调试程序查看结果 4、添加循环控制器 5、设置count计数器 6、添加请求 7、执行请求 二、CSV参数化 1、将结果写入后置处理程序 2、设置循环处理器 3、添加CSV文件 4、设置…

前端面试项目细节重难点分享(十三)

面试题提问:分享你最近做的这个项目,并讲讲该项目的重难点? 答:最近这个项目是一个二次迭代开发项目,迭代周期一年,在做这些任务需求时,确实有很多值得分享的印象深刻的点,我讲讲下面…

【中项】系统集成项目管理工程师-第5章 软件工程-5.3软件设计

前言:系统集成项目管理工程师专业,现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试,全称为“全国计算机与软件专业技术资格(水平)考试”&…

设计模式|观察者模式

观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时,它的所有观察者都会收到通知并更新。观察者模式常用于实现事件处理系统、发布-订阅模式等。在项目中&#xff0c…

【spring boot】初学者项目快速练手

项目视频:一小时带你从0到1实现一个SpringBoot项目开发_哔哩哔哩_bilibili 注解视频:10、Java高级技术:注解:认识注解_哔哩哔哩_bilibili 一、基础知识 1.注解Annotation (1)定义 注解是Java代码里的特…

Wordpress安装到win10(2024年7月)

目录 1.wordpress介绍 2下载应用 2.1.wordpress 2.2XAMPP 2.3 PHPmyadmin 3.配置应用 3.1XAMPP进程 3.2 文件配置 3.3 phpmyadmin配置 4.配置网页 4.1 数据库创建 4.2 安装wordpress 5.进入面板 6.总结 1.wordpress介绍 WordPress是一个开源内容管理系统&#xff0…

Node.js知识点总结

Node.js知识点总结 Node.js其本质和浏览器一样是一个JavaScript运行环境。浏览器的运行环境为V8引擎浏览器内置API(BOM、DOM、Canvas);而node.js的运行环境是V8引擎node提供的API(fs、path、http)。它使JavaScript可以编写后端。 基本知识 fs文件系统模块 它提供一…

C语言·分支和循环语句(超详细系列·全面总结)

前言:Hello大家好😘,我是心跳sy,为了更好地形成一个学习c语言的体系,最近将会更新关于c语言语法基础的知识,今天更新一下分支循环语句的知识点,我们一起来看看吧~ 目录 一、什么是语句&#xf…

剪画小程序:短视频搬运必备!去除视频字幕!

在这个人人都自媒体的盛世,新人想要创作爆款视频那里难上加难,所以搬运视频就成了很多新手自媒体人的不二选择。 搬运优质内容成为许多人的需求。但原视频中的字幕往往成为困扰大家的难题。 你是否曾为了搬运一个精彩的短视频,却因为无法去除…