WPF打包独立运行的程序

方案一:使用Costura.Fody插件将自己写的程序打包成一个可以独立运行的EXE文件

第1步:安装Costura.Fody

首先用Visual Studio 2017打开你的解决方案,依次找到“工具”---“NuGet包管理” - “管理解决方案的NuGet程序包”,到了这一步会打开NuGet-解决方案页面,在浏览选项下面的搜索框内输入“ Costura.Fody ”,会自动搜索出Costura.Fody插件,鼠标左键单击一下Costura.Fody插件,在右边的位置会出现你的项目名称,选中你的项目名称,选择安装,到这一步Costura.Fody就成功按照到你的项目上了

第2步:编译一下你的解决方案

直接按照你平常的习惯启动一下你的项目,这个时候,Costura.Fody就会完成打包,打包好的EXE文件在你的解决方案Debug根目录下,你现在可以把这个exe文件复制到任意一台电脑上去试试,完美运行

解决办法:手动添加FodyWeavers.xml文件
 
这样添加:将鼠标移动到你的解决方案上面,单击右键,依次选择“添加” - “新建项目” - “ XML文件 ”,注意在新建XML文件时将文件命名为“ FodyWeavers. xml “,然后将下面这段代码复制到 FodyWeavers.xml文件里面
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<Costura />
</Weavers>

方案二:WPF制作自己的安装程序(可定制)

安装程序原理:

1、将编译好的文件打包成zip的压缩文件,

2、然后将zip以资源的方式内嵌到安装程序中

3、在安装的时候使用ICSharpCode.SharpZipLib.dll将zip文件解压到相应的目录中

4、建立相应的快捷方式,启动主程序程序

第1步:WPF中将引用的ICSharpCode.SharpZipLib.dll文件打包到exe中

在做一个打包程序中,需要引用到一个ICSharpCode.SharpZipLib.dll的第三方库,编译之后dll需要生成到目录里面exe才能使用,但是只想给用户发送一个纯exe的安装文件,不想有关联的引用,怎么办呢?

在程序入口添加程序集解析事件(wpf的App.xaml.cs文件)

查看代码
 protected override void OnStartup(StartupEventArgs e)
{base.OnStartup(e);//添加程序集解析事件AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;}private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{Assembly executingAssembly = Assembly.GetExecutingAssembly();var executingAssemblyName = executingAssembly.GetName();var resName = executingAssemblyName.Name + ".resources";AssemblyName assemblyName = new AssemblyName(args.Name); string path = "";if (resName == assemblyName.Name){path = executingAssemblyName.Name + ".g.resources"; ;}else{path = assemblyName.Name + ".dll";if (assemblyName.CultureInfo != null && assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false){path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);}}using (Stream stream = executingAssembly.GetManifestResourceStream(path)){if (stream == null)return null;byte[] assemblyRawBytes = new byte[stream.Length];stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);return Assembly.Load(assemblyRawBytes);}
}

更改.csproj的项目文件

在Import节点后面添加如下代码

<Target Name="AfterResolveReferences">
<ItemGroup>
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Target>

原理:就是将dll文件以资源的方式嵌入包含到项目中,编译后目录里面仍然会编译出dll,我们将dll删除,发现程序仍然能运行,这是因为我们在入口注册了程序集解析事件

当程序集解析引用异常或有相关错误时,会进入事件,在事件中我们将嵌入的dll文件以流的方式映射加载,就相当于重新加载了删除的dll文件

第2步:解压核心代码

查看代码
 /// <summary>/// ZIP助手类/// </summary>public static class ZIPHelper{public static Action<double, double, string> ActionProgress;/// <summary>/// 解压缩zip文件/// </summary>/// <param name="zipFile">解压的zip文件流</param>/// <param name="extractPath">解压到的文件夹路径</param>/// <param name="bufferSize">读取文件的缓冲区大小</param>public static void Extract(byte[] zipFile, string extractPath, int bufferSize){extractPath = extractPath.TrimEnd('/') + "//";byte[] data = new byte[bufferSize];int size;//缓冲区的大小(字节)double max = 0;//带待压文件的大小(字节)double osize = 0;//每次解压读取数据的大小(字节)using (ZipInputStream s = new ZipInputStream(new System.IO.MemoryStream(zipFile))){ZipEntry entry;while ((entry = s.GetNextEntry()) != null){max += entry.Size;//获得待解压文件的大小}}using (ZipInputStream s = new ZipInputStream(new System.IO.MemoryStream(zipFile))){ZipEntry entry;while ((entry = s.GetNextEntry()) != null){string directoryName = Path.GetDirectoryName(entry.Name);string fileName = Path.GetFileName(entry.Name);//先创建目录if (directoryName.Length > 0){Directory.CreateDirectory(extractPath + directoryName);}if (fileName != String.Empty){using (FileStream streamWriter = File.Create(extractPath + entry.Name.Replace("/", "//"))){while (true){size = s.Read(data, 0, data.Length);if (size > 0){osize += size;System.Windows.Forms.Application.DoEvents();streamWriter.Write(data, 0, size);string text = Math.Round((osize / max * 100), 0).ToString() + "%";ActionProgress?.Invoke(max + 5, osize, text);System.Windows.Forms.Application.DoEvents();}else{break;}}}}}}}}

创建快捷方式

查看代码
 /// <summary>/// 执行软件安装/// </summary>private void Setup(){try{IsFinished = false;//获取用户选择路径中的最底层文件夹名称string fileName = this.txtInstallationPath.Text.Split('\\')[this.txtInstallationPath.Text.Split('\\').Count() - 1];//当用户选择的安装路径中最底层的文件夹名称不是“XthkDecryptionTool”时,自动在创建一个“XthkDecryptionTool”文件夹,防止在删除的时候误删别的文件if (!fileName.Equals(InstallEntity.InstallFolderName)){this.txtInstallationPath.Text = this.txtInstallationPath.Text + @"\" + InstallEntity.InstallFolderName;}//安装路径InstallPath = this.txtInstallationPath.Text;//显示安装进度界面//this.tcMain.SelectedIndex = 1;this.grid_one.Visibility = Visibility.Collapsed;this.grid_two.Visibility = Visibility.Visible;this.grid_three.Visibility = Visibility.Collapsed;//检测是否已经打开Process[] procCoursewareDecryptionTool = Process.GetProcessesByName(InstallEntity.AppProcessName);if (procCoursewareDecryptionTool.Any()){if (MessageBox.Show("“" + InstallEntity.DisplayName + "”正在运行中,是否强制覆盖程序?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes){Common.IsAppKill(InstallEntity.AppProcessName);}else{Application.Current.Shutdown();}}//创建用户指定的安装目录文件夹Directory.CreateDirectory(InstallPath);ZIPHelper.ActionProgress -= ActionProgressResult;ZIPHelper.ActionProgress += ActionProgressResult;this.pbSchedule.Value = 0;this.txtSchedule.Text = "0%";//将软件解压到用户指定目录ZIPHelper.Extract(Install.SetupFiles.Setup, InstallPath, 1024 * 1204);//将嵌入的资源释放到用户选择的安装目录下面(卸载程序)string uninstallPath = this.txtInstallationPath.Text + @"\" + InstallEntity.UninstallName;FileStream fsUninstall = System.IO.File.Open(uninstallPath, FileMode.Create);fsUninstall.Write(Install.SetupFiles.Uninstall, 0, Install.SetupFiles.Uninstall.Length);fsUninstall.Close();//将嵌入的资源释放到用户选择的安装目录下面(快捷图标)string InstallIcoPath = this.txtInstallationPath.Text + InstallEntity.IconDirectoryPath;FileStream fsInstallIcoPath = System.IO.File.Open(InstallIcoPath, FileMode.Create);var InstallIco = Install.SetupFiles.IcoInstall;byte[] byInstall = Common.ImageToByteArray(InstallIco);fsInstallIcoPath.Write(byInstall, 0, byInstall.Length);fsInstallIcoPath.Close();//将嵌入的资源释放到用户选择的安装目录下面(快捷卸载图标)string UninstallIcoPath = this.txtInstallationPath.Text + InstallEntity.UninstallIconDirectoryPath;FileStream fsUninStallIco = System.IO.File.Open(UninstallIcoPath, FileMode.Create);var UnInstallIco = Install.SetupFiles.IcoUninstall;byte[] byUnInstall = Common.ImageToByteArray(UnInstallIco);fsUninStallIco.Write(byUnInstall, 0, byUnInstall.Length);fsUninStallIco.Close();//释放卸载程序完成,更新进度条this.pbSchedule.Value = this.pbSchedule.Value + 1;this.txtSchedule.Text = Math.Round((this.pbSchedule.Value / this.pbSchedule.Maximum * 100), 0).ToString() + "%";//添加开始菜单快捷方式RegistryKey HKEY_CURRENT_USER = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders");string programsPath = HKEY_CURRENT_USER.GetValue("Programs").ToString();//获取开始菜单程序文件夹路径Directory.CreateDirectory(programsPath + InstallEntity.MenuFolder);//在程序文件夹中创建快捷方式的文件夹//更新进度条this.pbSchedule.Value = this.pbSchedule.Value + 1;this.txtSchedule.Text = Math.Round((this.pbSchedule.Value / this.pbSchedule.Maximum * 100), 0).ToString() + "%";//快捷方式名称";string IconPath = InstallPath + InstallEntity.IconDirectoryPath;string UninstallIconPath = InstallPath + InstallEntity.UninstallIconDirectoryPath;string InstallExePath = InstallPath + @"\" + InstallEntity.AppExeName;string ExeUnInstallPath = InstallPath + @"\" + InstallEntity.UninstallName;//开始菜单打开快捷方式shortName = programsPath + InstallEntity.MenuFolder + InstallEntity.ShortcutName;Common.CreateShortcut(shortName, InstallExePath, IconPath);//创建快捷方式//更新进度条this.pbSchedule.Value = this.pbSchedule.Value + 1;this.txtSchedule.Text = Math.Round((this.pbSchedule.Value / this.pbSchedule.Maximum * 100), 0).ToString() + "%";//开始菜单卸载快捷方式Common.CreateShortcut(programsPath + InstallEntity.MenuFolder + InstallEntity.UninstallShortcutName, ExeUnInstallPath, UninstallIconPath);//创建卸载快捷方式//更新进度条this.pbSchedule.Value = this.pbSchedule.Value + 1;this.txtSchedule.Text = Math.Round((this.pbSchedule.Value / this.pbSchedule.Maximum * 100), 0).ToString() + "%";//添加桌面快捷方式string desktopPath = HKEY_CURRENT_USER.GetValue("Desktop").ToString();//获取桌面文件夹路径shortName = desktopPath + @"\" + InstallEntity.ShortcutName;Common.CreateShortcut(shortName, InstallExePath, IconPath);//创建快捷方式//常见控制面板“程序与功能”//可以往root里面写,root需要管理员权限,如果使用了管理员权限,主程序也会以管理员打开,如需常规打开,需要在打开进程的时候做降权处理RegistryKey CUKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32);var currentVersion = CUKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall");Dictionary<string, string> dic = new Dictionary<string, string>();dic.Add("DisplayIcon", InstallExePath);//显示的图标的exedic.Add("DisplayName", InstallEntity.DisplayName);//名称dic.Add("Publisher", InstallEntity.Publisher);//发布者dic.Add("UninstallString", ExeUnInstallPath);//卸载的exe路径dic.Add("DisplayVersion", InstallEntity.VersionNumber);RegistryKey CurrentKey = CUKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + InstallEntity.DisplayName, true);if (CurrentKey == null){//说明这个路径不存在,需要创建CUKey.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + InstallEntity.DisplayName);CurrentKey = CUKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + InstallEntity.DisplayName, true);}foreach (var item in dic){CurrentKey.SetValue(item.Key, item.Value);}CurrentKey.Close();//更新进度条this.pbSchedule.Value = this.pbSchedule.Value + 1;this.txtSchedule.Text = Math.Round((this.pbSchedule.Value / this.pbSchedule.Maximum * 100), 0).ToString() + "%";//安装完毕,显示结束界面this.grid_one.Visibility = Visibility.Collapsed;this.grid_two.Visibility = Visibility.Collapsed;this.grid_three.Visibility = Visibility.Visible;IsFinished = true;}catch (Exception){//安装完毕,显示结束界面this.grid_one.Visibility = Visibility.Visible;this.grid_two.Visibility = Visibility.Collapsed;this.grid_three.Visibility = Visibility.Collapsed;throw;}}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物联网平台推荐:ThingsKit

ThingsKit物联网平台 随着物联网技术的不断进步,企业和开发者对于一个可靠、高效且易于使用的物联网平台的需求日益增长。在这样的背景下,ThingsKit物联网平台以其卓越的性能和丰富的功能,成为了市场上的一股清流。 一、ThingsKit物联网平台概述 ThingsKit是一个功能强大、易…

面试官:单核服务器可以不加锁吗?

今天有位同学问了磊哥一个问题,大概的意思是“单核服务器可以不加锁吗?”,我觉得很有意思,所以在这里就和各位探讨一下:1. 问题答案 先说我的理解,单核服务器仍然需要加锁。因为在单核服务器上也会有线程切换,如果不加锁,那么线程切换后,另一个线程就可以访问其他线程…

[CTFshow] 文件包含 78~88,116~117

web78 if(isset($_GET[file])){$file = $_GET[file];include($file); }else{highlight_file(__FILE__); }php伪协议,data:// 数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码 ?file=data://text/plain,<?=system(ls)?> ?file=data://text/plain,<?…

如何获取并展示PDD商品的详细信息?

在数字化时代,获取并展示PDD商品的详细信息对于电商运营者来说至关重要。这不仅有助于提升用户体验,还能增强商品的转化率。以下是一些有效的方法和策略,可以帮助你获取并展示PDD商品的详细信息。利用API接口 PDD提供了丰富的API接口,允许开发者获取商品的详细信息。通过AP…

重点区域人员徘徊识别监测系统

重点区域人员徘徊识别监测系统对监控画面中重要区域进行实时检测分析。当重点区域人员徘徊识别监测系统检测到一些人徘徊停留时,SuiJi-Ai系统立即报警,并提醒相关负责人妥善处理同时将报警截图和视频保存到数据库中生成表格。SuiJi-Ai重点区域人员徘徊识别监测系统主要通过现…

章13——包装类——Math类

常用方法 均为静态1、random 默认下返回 0 到 1 的随机数(前闭后开) 2、如取 2->7 之间的随机数: int a = (int)(2 + (5+1)*Math.random()); //+1的原因:(int)会舍去小数,且 random 的取值前闭后开,如果不 +1 最大只能取到6

新能源汽车如何更好地落地供应商伙伴协同系统管理?

近年来,我国新能源汽车业得到快速发展,从新能源汽车制造的产业链来说,包括上中下游,其中: 上游产业主要包括原材料供应和关键零部件生产两大部分: 原材料供应:主要为矿产资源和化工材料。 关键零部件生产:包括动力电池、电机及控制器、电池管理系统(BMS)等。中游产业…

安全帽佩戴识别算法

安全帽佩戴识别算法采用SuiJi-AI人工智能深度学习技术+计算机智能视觉识别算法,且通过规模化的安全帽数据识别训练。安全帽佩戴识别算法借助现场已有的监控摄像头对监控画面中人员着装行为进行实时分析识别。假如检测人员不戴安全帽,SuiJiAi将立即记录和警报,并可将纪录数据…

徘徊行为AI智能分析预警系统

徘徊行为AI智能分析预警系统可以立即对视频监测区域进行实时分析,自动识别监测监控画面中同一角色的来回进出频率,徘徊行为AI智能分析预警系统对多次进出徘徊人员实时检测预警,弥补人为因素的监督盲点。徘徊行为AI智能分析预警系统真正提高了安全监控的效率,可以尽快发现违…

人员徘徊识别系统

人员徘徊识别系统利用现场已有监控摄像头可以实时剖析监控画面中人员异常徘徊行为,当人员徘徊识别系统识别到特殊重要区域(危险区域)附近出现人员来回反复停留时,系统会立即搜抓拍预警并同步异常违规信息到后台,及时通告有关人员留意出现异常的目标,方便及时到现场处理。…

设置socks5代理:访问远程设备所在网络中的所有服务

部署Gemini Gemini使用教程 - 迅捷网络[来送福利] - 博客园 (cnblogs.com) 1.http和socks5代理的区别 2.哪些系统和软件支持socks5代理 1. 操作系统 许多操作系统本身就提供对 SOCKS5 代理的支持,或者可以通过配置或额外的软件来实现 SOCKS5 代理功能。Windows:Windows 原生网…

WiFi基础(四):WiFi工作原理及WiFi接入过程

liwen01 2024.09.16 前言 802.11 无线 WiFi 网有三类帧:数据帧、管理帧、控制帧。与有线网相比,无线 WiFi 网会复杂很多。大部分应用软件开发对 WiFi 的控制帧和管理帧了解得并不多,因为它们在物理层和数据链路层就已经被处理了,上层应用很少能感知到。 一般是在设备出现 W…