C#自行实现安装卸载程序(不使用官方组件)

十念  金牌会员 | 2023-3-11 13:11:08 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 770|帖子 770|积分 2310

正规软件建议还是使用官方的标准安装程序组件,因为官方的标准安装/卸载组件能更好的与操作系统衔接,安装和卸载流程更加规范。
今天提供一种野路子,全用代码实现安装卸载器。
需要写一个程序,包含安装器、卸载器、主程序。
在visual studio中创建一个解决方案,解决方案里创建3个项目分别对应安装器、卸载器、主程序。
如图

制作安装包目录时,将三个项目全部生成可执行程序。然后按下方文件结构组织安装包,复制最终程序文件到相应位置。
U8FileTransferIntaller
+-- U8FileTransfer
|    +-- main
|          |-- U8FileTransfer.exe
|          |-- ...
|    +-- uninstall.exe
+-- intall.exe
* Installer生成install.exe,用于拷贝U8FileTransfer目录到用户选择的安装路劲,注册表添加开机自启,启动U8FileTransfer.exe
* UnInstaller生成uninstall.exe,用于卸载程序(退出主程序,取消开机自启,删除main目录)
* U8FileTransfer是主程序。

卸载时会删除main目录,uninstall.exe无法自己删除自己,需手动删除。
下面只讲安装和卸载器的实现,不讲主程序。
安装器


功能:复制目录及文件,注册表添加开启自启,启动程序,关闭自身
Intaller.cs 代码:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.IO;
  10. using Microsoft.Win32;
  11. using System.Reflection;
  12. // using System.Diagnostics;
  13. namespace Installer
  14. {
  15.     public partial class Intaller : Form
  16.     {
  17.         private string appDirName = "U8FileTransfer";
  18.         public Intaller()
  19.         {
  20.             InitializeComponent();
  21.         }
  22.         /// <summary>
  23.         /// 复制目录(包括子目录及所有文件)到另一个地方
  24.         /// </summary>
  25.         /// <param name="sourceDirName"></param>
  26.         /// <param name="destDirName"></param>
  27.         /// <param name="copySubDirs"></param>
  28.         private void directoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
  29.         {
  30.             // Get the subdirectories for the specified directory.
  31.             DirectoryInfo dir = new DirectoryInfo(sourceDirName);
  32.             if (!dir.Exists)
  33.             {
  34.                 throw new DirectoryNotFoundException(
  35.                     "Source directory does not exist or could not be found:"
  36.                     + sourceDirName);
  37.             }
  38.             DirectoryInfo[] dirs = dir.GetDirectories();
  39.             // If the destination directory doesn't exist, create it.      
  40.             Directory.CreateDirectory(destDirName);
  41.             // Get the files in the directory and copy them to the new location.
  42.             FileInfo[] files = dir.GetFiles();
  43.             foreach (FileInfo file in files)
  44.             {
  45.                 string tempPath = Path.Combine(destDirName, file.Name);
  46.                 file.CopyTo(tempPath, true);
  47.             }
  48.             // If copying subdirectories, copy them and their contents to new location.
  49.             if (copySubDirs)
  50.             {
  51.                 foreach (DirectoryInfo subdir in dirs)
  52.                 {
  53.                     string tempPath = Path.Combine(destDirName, subdir.Name);
  54.                     directoryCopy(subdir.FullName, tempPath, copySubDirs);
  55.                 }
  56.             }
  57.         }
  58.         // 文件浏览按钮事件
  59.         private void folderBrowserButton_Click(object sender, EventArgs e)
  60.         {
  61.             DialogResult dr = folderBrowserDialog.ShowDialog();
  62.             if (dr == System.Windows.Forms.DialogResult.OK)
  63.             {
  64.                 folderPathTextBox.Text = folderBrowserDialog.SelectedPath + "\" + appDirName;
  65.             }
  66.         }
  67.         // 确认按钮事件
  68.         private void okButton_Click(object sender, EventArgs e)
  69.         {
  70.             /**
  71.              * 1.复制目录及文件
  72.              */
  73.             string sourceDirName = Application.StartupPath + "\" + appDirName;
  74.             string destDirName = @folderPathTextBox.Text;
  75.             directoryCopy(sourceDirName, destDirName, true);
  76.             /**
  77.              * 2.注册表添加开启自启
  78.              */
  79.             RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
  80.             if(key == null)//如果该项不存在的话,则创建该子项
  81.             {
  82.                 key = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
  83.             }
  84.             key.SetValue(appDirName, destDirName + "\\main\\U8FileTransfer.exe");
  85.             key.Close();
  86.             /**
  87.              * 3.启动程序
  88.              */
  89.             string start = @folderPathTextBox.Text + "\\main\\U8FileTransfer.exe";
  90.             System.Diagnostics.Process.Start(start);
  91.             //关闭自身
  92.             Application.Exit();
  93.         }
  94.     }
  95. }
复制代码
 
卸载器


功能:退出运行中的主程序,删除注册表开机自启项,删除安装目录,弹出提示,退出自身
Uninstall.cs 代码:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Diagnostics;
  10. using Microsoft.Win32;
  11. using System.IO;
  12. namespace Uninstaller
  13. {
  14.     public partial class Uninstall : Form
  15.     {
  16.         public Uninstall()
  17.         {
  18.             InitializeComponent();
  19.         }
  20.         private void cancelButton_Click(object sender, EventArgs e)
  21.         {
  22.             Application.Exit();
  23.         }
  24.         private void confirmButton_Click(object sender, EventArgs e)
  25.         {
  26.             // 退出运行中的主程序
  27.             Process[] process = Process.GetProcesses();
  28.             foreach (Process prc in process)
  29.             {
  30.                 // ProcessName为exe程序的名称,比如叫main.exe,那么ProcessName就为main
  31.                 if (prc.ProcessName == "U8FileTransfer")
  32.                 {
  33.                     prc.Kill();
  34.                     break;
  35.                 }
  36.             }
  37.             // 删除注册表开机自启项
  38.             // 打开注册表子项
  39.             RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
  40.             if (key != null)
  41.             {
  42.                 try
  43.                 {
  44.                     key.DeleteValue("U8FileTransfer");
  45.                 }
  46.                 catch (Exception ex)
  47.                 {
  48.                     MessageBox.Show(ex.Message);
  49.                 }
  50.             }
  51.             key.Close();
  52.             // 删除目录
  53.             DeleteDir(Application.StartupPath + "\\main");
  54.             // 弹出提示
  55.             MessageBox.Show("以卸载完成,Uninstall.exe需要手动删除");
  56.             // 退出自身
  57.             Application.Exit();
  58.             
  59.         }
  60.         /// <summary>
  61.         /// 删除文件夹
  62.         /// </summary>
  63.         /// <param name="file">需要删除的文件路径</param>
  64.         /// <returns></returns>
  65.         public bool DeleteDir(string file)
  66.         {
  67.             try
  68.             {
  69.                 //去除文件夹和子文件的只读属性
  70.                 //去除文件夹的只读属性
  71.                 System.IO.DirectoryInfo fileInfo = new DirectoryInfo(file);
  72.                 fileInfo.Attributes = FileAttributes.Normal & FileAttributes.Directory;
  73.                 //去除文件的只读属性
  74.                 System.IO.File.SetAttributes(file, System.IO.FileAttributes.Normal);
  75.                 //判断文件夹是否还存在
  76.                 if (Directory.Exists(file))
  77.                 {
  78.                     foreach (string f in Directory.GetFileSystemEntries(file))
  79.                     {
  80.                         if (File.Exists(f))
  81.                         {
  82.                             //如果有子文件删除文件
  83.                             File.Delete(f);
  84.                             //Console.WriteLine(f);
  85.                         }
  86.                         else
  87.                         {
  88.                             //循环递归删除子文件夹
  89.                             DeleteDir(f);
  90.                         }
  91.                     }
  92.                     //删除空文件夹
  93.                     Directory.Delete(file);
  94.                 }
  95.                 return true;
  96.             }
  97.             catch (Exception) // 异常处理
  98.             {
  99.                 return false;
  100.             }
  101.         }
  102.    
  103.     }
  104. }
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

十念

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表