用C#写程序安装包
前段日子由于团队开发需要,写了一个用C#代码写的安装包!首先说一下背景,之所以写这个,是因为我们在完成一个winform程序之后,需要部署到其他电脑上时发现:部署需要搭建的环境例如系统用到的外设驱动,数据库环境。还有将该系统部署到其他电脑上选择路径和写入注册表。有点类似于QQ安装程序。
1.初始界面如下:
当然,界面有点丑,还没有LOGO之类的美化。
2.环境检测安装(即安装外设的驱动和搭建好数据库环境)
这里的安装外设驱动说白了就是用C#代码实现调用一个.exe程序并执行安装,搭建数据库环境也就是系统需要用到本地数据库作为服务器存放数据(因为需要部署的系统是一个单机版的程序)。
(1)用C#代码调用exe程序
(2)安装一个数据库实例(搭建数据库环境)
代码如下:
private void Detect() { //复制文件到C盘根目录下 string sourcePath = @"文件名"; string targetPath = @"C:\文件名"; bool isrewrite = true; // true=覆盖已存在的同名文件,false则反之 File.Copy(sourcePath, targetPath, isrewrite);
//以上提供了把指定文件复制到某个目录下的方法
//在调用exe文件安装该应用程序之前先检测一下电脑中是否已经安装了该程序,由于正规的程序安装时都会将程序信息写入注册表,因此我们可以通过检测注册表来判断电脑中
//是否已经安装了该程序。 RegistryKey idCard = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey(@"SDTtelecom", true); if (idCard == null) {
Install("XXXX.exe"); //需要安装的XXXX.exe程序应该放在与安装向导程序同一个目录下
idCard = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey(@"SDTtelecom", true);
//再次检测,如果为null说明前面安装不成功,则退出安装向导程序 if (idCard == null) { System.Environment.Exit(0); } }
//在这里我直接安装了一个简化的数据库环境SQL server,以下参数是采用静默安装方法是创建的一个数据库实例。
Install("SQLEXPR32_x86_ENU.exe", @"/qb INSTANCENAME=""VeinDBInstance"" ADDLOCAL=ALL SECURITYMODE=SQL SAPWD=""123456"" SQLAUTOSTART=1"); } private void Install(string file,string param=null) { Process myProcess = new Process(); string fileName = @file; ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(fileName); if (!string.IsNullOrEmpty(param)) myProcessStartInfo.Arguments = param; myProcessStartInfo.UseShellExecute = false; myProcess.StartInfo = myProcessStartInfo; myProcess.Start(); myProcess.WaitForExit();//关键,等待外部程序退出后才能往下执行 }
2.安装(环境搭建好之后把winform程序部署到电脑上并写入注册表)
/// <summary>写入注册表函数 /// 写入注册表 /// </summary> /// <param name="name">版本</param> /// <param name="tovalue">1.0</param> private void WTRegedit(string name, string tovalue) { RegistryKey hklm = Registry.LocalMachine; RegistryKey software = hklm.OpenSubKey("SOFTWARE", true); RegistryKey aimdir = software.CreateSubKey("写入注册表的公司命名,例如Tencent"); RegistryKey soft = aimdir.CreateSubKey("写软件名,例如Intergration"); soft.SetValue(name, tovalue); soft.SetValue("Path", this._installPath + "\\Intergration"); soft.SetValue("DBName", "数据库名"); } /// /// 创建VBS代码 /// /// private string CreateVBS(string name, string strexe) { string vbs = string.Empty; vbs += ("set WshShell = WScript.CreateObject(\"WScript.Shell\")\r\n"); vbs += ("strDesktop = WshShell.SpecialFolders(\"Desktop\")\r\n"); vbs += ("set oShellLink = WshShell.CreateShortcut(strDesktop & \"\\" + name + ".lnk\")\r\n"); //目标路径,也就是我们程序所在的路径 vbs += ("oShellLink.TargetPath = \"" + this._installPath + "\\" + "Intergration" + "\\" + strexe + "\"\r\n"); vbs += ("oShellLink.WindowStyle = 1\r\n"); vbs += ("oShellLink.Description = \"" + name + "\"\r\n"); vbs += ("oShellLink.WorkingDirectory = \"" + this._installPath + "\\" + "Intergration" + "\"\r\n"); vbs += ("oShellLink.Save"); return vbs; } /// /// 写入临时文件 /// private static string WriteToFile(string vbs) { if (string.IsNullOrEmpty(vbs)) return null; //临时文件 string tempFile = Environment.CurrentDirectory + "\\" + DateTime.Now.Ticks + "emp.vbs"; //写入文件 FileStream fs = new FileStream(tempFile, FileMode.Create, FileAccess.Write); try { //这里必须用UnicodeEncoding. 因为用UTF-8或ASCII会造成VBS乱码 System.Text.UnicodeEncoding uni = new UnicodeEncoding(); byte[] b = uni.GetBytes(vbs); fs.Write(b, 0, b.Length); fs.Flush(); fs.Close(); } catch (Exception ex) { //Console.WriteLine("写入临时文件出错"); } finally { //释放资源 fs.Dispose(); } return tempFile; } /// /// 执行VBS中的代码 /// private static void RunProcess(string file) { string tempFile = file; if (File.Exists(tempFile)) { //执行VBS Process.Start(tempFile); } } /// <summary>安装过程 /// 安装过程 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Install_Shown(object sender, EventArgs e) { //复制到安装目录,这里的this._installPath变量存的就是界面上选择的安装路径 string installPath = this._installPath; //这里的Intergration就是一个部署文件夹,里面包含exe和dll文件
string sourcePath = @"Intergration";
CopyFolder(sourcePath, installPath); //运行数据库脚本 RunSQLScript runSql = new RunSQLScript(); runSql.Run(); //写注册表 WTRegedit("Version", "1.0"); //以下均为创建桌面快捷键 //生成VBS代码 string vbs = CreateVBS("XX系统", "XX.exe"); //以文件形式写入临时文件夹 string file = WriteToFile(vbs); //调用Process执行 RunProcess(file); } /// <summary> /// 实现从一个目录下完整拷贝到另一个目录下。这里其实就是一个拷贝一个部署包,里面包括可执行文件exe和dll文件之类的。 /// </summary> /// <param name="strFromPath">源地址</param> /// <param name="strToPath">目标地址</param> public static void CopyFolder(string strFromPath, string strToPath) { //取得要拷贝的文件夹名 string strFolderName = strFromPath.Substring(strFromPath.LastIndexOf("\\") + 1, strFromPath.Length - strFromPath.LastIndexOf("\\") - 1); //如果目标文件夹中没有源文件夹则在目标文件夹中创建源文件夹 if (!Directory.Exists(strToPath + "\\" + strFolderName)) { Directory.CreateDirectory(strToPath + "\\" + strFolderName); } //创建数组保存源文件夹下的文件名 string[] strFiles = Directory.GetFiles(strFromPath); //循环拷贝文件 for (int i = 0; i < strFiles.Length; i++) { //取得拷贝的文件名,只取文件名,地址截掉。 string strFileName = strFiles[i].Substring(strFiles[i].LastIndexOf("\\") + 1, strFiles[i].Length - strFiles[i].LastIndexOf("\\") - 1); //开始拷贝文件,true表示覆盖同名文件 File.Copy(strFiles[i], strToPath + "\\" + strFolderName + "\\" + strFileName, true); } //创建DirectoryInfo实例 DirectoryInfo dirInfo = new DirectoryInfo(strFromPath); //取得源文件夹下的所有子文件夹名称 DirectoryInfo[] ZiPath = dirInfo.GetDirectories(); for (int j = 0; j < ZiPath.Length; j++) { //获取所有子文件夹名 string strZiPath = strFromPath + "\\" + ZiPath[j].ToString(); //把得到的子文件夹当成新的源文件夹,从头开始新一轮的拷贝 CopyFolder(strZiPath, strToPath + "\\" + strFolderName); } }
至此,一个简易安装向导程序的核心代码都在这了。新手刚学,代码乱,还请指正!
总结一下以上代码能实现什么功能:
1.将指定文件或指定文件夹拷贝到某一个指定的目录下
2.拷贝完之后能将软件信息写入注册表,完成注册
3.调用exe文件,运行
4.创建桌面快捷方式