C#自行实现安装卸载程序(不使用官方组件)
正规软件建议还是使用官方的标准安装程序组件,因为官方的标准安装/卸载组件能更好的与操作系统衔接,安装和卸载流程更加规范。
今天提供一种野路子,全用代码实现安装卸载器。
需要写一个程序,包含安装器、卸载器、主程序。
在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 代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using Microsoft.Win32; using System.Reflection; // using System.Diagnostics; namespace Installer { public partial class Intaller : Form { private string appDirName = "U8FileTransfer"; public Intaller() { InitializeComponent(); } /// <summary> /// 复制目录(包括子目录及所有文件)到另一个地方 /// </summary> /// <param name="sourceDirName"></param> /// <param name="destDirName"></param> /// <param name="copySubDirs"></param> private void directoryCopy(string sourceDirName, string destDirName, bool copySubDirs) { // Get the subdirectories for the specified directory. DirectoryInfo dir = new DirectoryInfo(sourceDirName); if (!dir.Exists) { throw new DirectoryNotFoundException( "Source directory does not exist or could not be found:" + sourceDirName); } DirectoryInfo[] dirs = dir.GetDirectories(); // If the destination directory doesn't exist, create it. Directory.CreateDirectory(destDirName); // Get the files in the directory and copy them to the new location. FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { string tempPath = Path.Combine(destDirName, file.Name); file.CopyTo(tempPath, true); } // If copying subdirectories, copy them and their contents to new location. if (copySubDirs) { foreach (DirectoryInfo subdir in dirs) { string tempPath = Path.Combine(destDirName, subdir.Name); directoryCopy(subdir.FullName, tempPath, copySubDirs); } } } // 文件浏览按钮事件 private void folderBrowserButton_Click(object sender, EventArgs e) { DialogResult dr = folderBrowserDialog.ShowDialog(); if (dr == System.Windows.Forms.DialogResult.OK) { folderPathTextBox.Text = folderBrowserDialog.SelectedPath + "\\" + appDirName; } } // 确认按钮事件 private void okButton_Click(object sender, EventArgs e) { /** * 1.复制目录及文件 */ string sourceDirName = Application.StartupPath + "\\" + appDirName; string destDirName = @folderPathTextBox.Text; directoryCopy(sourceDirName, destDirName, true); /** * 2.注册表添加开启自启 */ RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); if(key == null)//如果该项不存在的话,则创建该子项 { key = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); } key.SetValue(appDirName, destDirName + "\\main\\U8FileTransfer.exe"); key.Close(); /** * 3.启动程序 */ string start = @folderPathTextBox.Text + "\\main\\U8FileTransfer.exe"; System.Diagnostics.Process.Start(start); //关闭自身 Application.Exit(); } } }
卸载器
功能:退出运行中的主程序,删除注册表开机自启项,删除安装目录,弹出提示,退出自身
Uninstall.cs 代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using Microsoft.Win32; using System.IO; namespace Uninstaller { public partial class Uninstall : Form { public Uninstall() { InitializeComponent(); } private void cancelButton_Click(object sender, EventArgs e) { Application.Exit(); } private void confirmButton_Click(object sender, EventArgs e) { // 退出运行中的主程序 Process[] process = Process.GetProcesses(); foreach (Process prc in process) { // ProcessName为exe程序的名称,比如叫main.exe,那么ProcessName就为main if (prc.ProcessName == "U8FileTransfer") { prc.Kill(); break; } } // 删除注册表开机自启项 // 打开注册表子项 RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); if (key != null) { try { key.DeleteValue("U8FileTransfer"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } key.Close(); // 删除目录 DeleteDir(Application.StartupPath + "\\main"); // 弹出提示 MessageBox.Show("以卸载完成,Uninstall.exe需要手动删除"); // 退出自身 Application.Exit(); } /// <summary> /// 删除文件夹 /// </summary> /// <param name="file">需要删除的文件路径</param> /// <returns></returns> public bool DeleteDir(string file) { try { //去除文件夹和子文件的只读属性 //去除文件夹的只读属性 System.IO.DirectoryInfo fileInfo = new DirectoryInfo(file); fileInfo.Attributes = FileAttributes.Normal & FileAttributes.Directory; //去除文件的只读属性 System.IO.File.SetAttributes(file, System.IO.FileAttributes.Normal); //判断文件夹是否还存在 if (Directory.Exists(file)) { foreach (string f in Directory.GetFileSystemEntries(file)) { if (File.Exists(f)) { //如果有子文件删除文件 File.Delete(f); //Console.WriteLine(f); } else { //循环递归删除子文件夹 DeleteDir(f); } } //删除空文件夹 Directory.Delete(file); } return true; } catch (Exception) // 异常处理 { return false; } } } }