动态创建EXE功能目的:

比如我们写了设计软件,可以界面设计一些东西。现在我们需要将我们设计好的东西保存成一个exe,用户打开就直接可以看到设计好的东西。也就是需要把数据保存到exe里面。

这个时候呢,我们可以动态生成一个新的程序,这个程序调用我们原先的设计软件,区别是,我们运行这个软件的时候,可以把原先设计好的数据全部写死写入到新的软件里面,

然后参数传入到设计软件。这样就可以实现双击运行软件,打开就是原先设计好的数据了。

废话讲完了,也不知道有没有讲清楚、、、、

1.创建项目SaveExe或者修改代码中SaveExe名字为自己的项目

2.添加按钮调用CreateCodeEXE,即可实现编译生成一个新的exe即 复制了自身的exe生成一个新的exe(目的就是新生的exe,我们可以增加预设参数属性之类)。

public static void CreateCodeEXE()
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = true;
parameters.CompilerOptions = "/target:winexe /optimize /win32icon:ImageView.ico";
parameters.GenerateInMemory = false;
string path = "test.exe";
parameters.OutputAssembly = path; parameters.ReferencedAssemblies.Add("SaveExe.exe");//此处是自身的exe
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("System.Data.dll");
parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
parameters.ReferencedAssemblies.Add("System.Deployment.dll");
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
parameters.ReferencedAssemblies.Add("System.Net.Http.dll");
parameters.ReferencedAssemblies.Add("System.Xml.dll");
parameters.ReferencedAssemblies.Add("System.Xml.Linq.dll"); string sourceFile = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms; namespace SaveExe
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
";
CompilerResults cr = provider.CompileAssemblyFromSource(parameters, sourceFile);
if (cr.Errors.Count > )
{
StringBuilder sb = new StringBuilder();
foreach (var er in cr.Errors)
sb.AppendLine(er.ToString());
MessageBox.Show(sb.ToString());
}
else
{
MessageBox.Show("编译成功");
}
}

以上方法有一个限制就是必须在自身的exe所在的路径下有效,即生成的exe和原本的exe要在同一个目录下。

解决方案,就是嵌入资源,将原本的exe嵌入到新生成的exe。然后使用动态加载。

例子:

程序GraphicPlay.EXE,里面有个Form1,实现生成新的程序,直接弹出Form1

public class SaveEXE
{
public static void CreateCode(string filename, string source)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = true;
parameters.CompilerOptions = "/target:winexe /optimize /win32icon:Image.ico";//这里增加了图标,没有对应图标的可以删除
parameters.GenerateInMemory = false;
string path = filename;
parameters.OutputAssembly = path; parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("System.Data.dll");
parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
parameters.ReferencedAssemblies.Add("System.Deployment.dll");
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
parameters.ReferencedAssemblies.Add("System.Net.Http.dll");
parameters.ReferencedAssemblies.Add("System.Xml.dll");
parameters.ReferencedAssemblies.Add("System.Xml.Linq.dll");
parameters.EmbeddedResources.Add(Application.ExecutablePath);//这里添加嵌入资源 CompilerResults cr = provider.CompileAssemblyFromSource(parameters, source);
if (cr.Errors.Count > )
{
StringBuilder sb = new StringBuilder();
foreach (var er in cr.Errors)
sb.AppendLine(er.ToString());
throw new Exception(sb.ToString());
}
}
}
SaveEXE.CreateCode(save.FileName,(@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO; namespace GraphicPlay
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream(""GraphicPlay.EXE"");
if(stream==null)
throw new Exception(""加载资源失败"");
byte[] buffer = new byte[(int)stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
Assembly asm = Assembly.Load(buffer);
if(stream==null)
throw new Exception(""加载程序集失败"");
Type t = asm.GetType(""GraphicPlay.Form1"");
var form = asm.CreateInstance(t.FullName) as Form;
Application.Run(form);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}"));

有时需要动态引用DLL,可以参考以下方法:(需要先将DLL添加到资源文件中,然后加载资源文件)

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string dllName = args.Name.Contains(",") ? args.Name.Substring(, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
            dllName = dllName.Replace(".", "_");
            if (dllName.EndsWith("_resources")) return null;
            System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
            byte[] bytes = (byte[])rm.GetObject(dllName);
            return System.Reflection.Assembly.Load(bytes);
        }         public Form1()//看清楚这是窗体本来的初始化函数
        {
            //在InitializeComponent()之前调用     AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            InitializeComponent();
        }

参考文章:https://www.iteye.com/problems/72159

https://blog.csdn.net/lin381825673/article/details/39122257?tdsourcetag=s_pcqq_aiomsg

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/target-compiler-option

C# 动态创建EXE的更多相关文章

  1. 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...

  2. WCF 动态调用(动态创建实例接口)

    很多时候,服务地址都不止一个的,这个时候就要动态去配置地址.配置Web.config,很麻烦 下面就看看怎样实现动态调用WCF. 首先看看动态创建服务对象的代码: using System; usin ...

  3. JavaScript dom 动态创建标记

    此前的大多数DOM都是用来查找元素,getElementById和getElementsByTagName都可以方便快捷的找到文档中的某个或者某些特定的元素节点,这些元素随后可以用诸如setAttri ...

  4. ios动态创建类Class

    [Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...

  5. winform 用户控件、 动态创建添加控件、timer控件、控件联动

    用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...

  6. python动态创建类的声明

    动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...

  7. Python 动态创建函数【转】

    知乎上也有相似的问题 偶然碰到一个问题,初想是通过动态创建Python函数的方式来解决,于是调研了动态创建Python函数的方法. 定义lambda函数 在Python中定义lambda函数的写法很简 ...

  8. WinForm用户控件、动态创建添加控件、timer控件--2016年12月12日

    好文要顶 关注我 收藏该文 徐淳 关注 - 1 粉丝 - 3       0 0     用户控件: 通过布局将多个控件整合为一个控件,根据自己的需要进行修改,可对用户控件内的所有控件及控件属性进行修 ...

  9. 动态创建DAL层类的实例

    为了可扩展性,方便以后对于代码的修改维护,使用动态创建DAL层对象. 1.首先在webconfig中的configuration下添加配置项 <appSettings> <add k ...

随机推荐

  1. zabbix--远程执行命令

    zabbix 远程执行命令 重启应用 服务器 使用远程执行命令可以在某些时候帮我做一些事情,达到轻量级的自动化,比如当 nginx.mysql.php.redis.tomcat.等等应用挂掉时帮我们自 ...

  2. python3在win10运行CGI

    痛苦是保持清醒最好的方式 --秦时明月·奶盖   CGI是什么 CGI是目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway interface),通用网关接口,它是一段 ...

  3. Vue开发之项目创建

    1.编辑器配置 习惯使用VScode进行开发时,可以安装EditorConfig for Visual Studio Code插件,然后在项目中新建.editorconfig文件,来配置编辑器的使用习 ...

  4. seaborn---调色板

    一.样式控制 1.set([context,style,palette,font,...]) 一步设定美学参数. 2.axes_style([style,rc]) 返回参数字典,用于绘图的美学风格. ...

  5. 《团队名称》第八次团队作业:Alpha冲刺day4

    项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8-软件测试与ALPHA冲刺 团队名称 快活帮 作业学习目标 (1)掌握 ...

  6. 项目Beta冲刺(团队) ——随笔集合

    课程名称:软件工程1916|W(福州大学) 作业要求:项目β冲刺(团队) 团队名称:葫芦娃队 作业目标:汇总这次冲刺项目的所有随笔文件. 队员学号 队员昵称 博客地址 041602421 der hi ...

  7. APP——Ruby开源分发平台搭建

    前言 蒲公英,维护后把我上传的包清除了,所以想自己搭建一个用下. 步骤 项目用ruby语言写的,部署起来也很简单支持源码和Docker部署 GitHub | https://github.com/pl ...

  8. 【Postgres】Windows2012 不能启动

    PG启动错误-不知道什么错误 等待 postgresql-x64- 服务的连接超时( 毫秒). 由于下列错误,postgresql-x64- 服务启动失败: 服务没有及时响应启动或控制请求. 编写ba ...

  9. python 的 lambda使用笔记

    无参数匿名函数: f=lambda: none f() 输出:none 带参数匿名函数: 带一个参数: f=lambda x:x+1 f(1) 输出:2 带多个参数: f=lambda a,b,c:a ...

  10. Spring AOP中JoinPoint的用法

    Spring JoinPoint的用法 JoinPoint 对象 JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的 ...