C# 動態創建EXE


 動態創建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 > 0)
            {
                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 > 0)
            {
                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(0, 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM