简体   繁体   中英

Remove code from CodeDOM compilation at runtime

I have a Windows Forms Application with a CheckBox and a button. The button will make it so the CodeDOM compiled exe will disable task manager. But if they don't want it to disable, they can uncheck the button. What I'm trying to to is make it so if they uncheck the button it will remove the block of code from the resource file that disables task manager.

This is my resource file:

using System;
using System.Windows.Forms;
using Microsoft.Win32;

static class Program
{
    [STAThread]
    static void Main()
    {
        RegistryKey regkey;
        string keyValueInt = "1";
        string subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";

        try
        {
            regkey = Registry.CurrentUser.CreateSubKey(subKey);
            regkey.SetValue("DisableTaskMgr", keyValueInt);
            regkey.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

My main code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.CodeDom.Compiler;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string source = Properties.Resources.BaseSource;

            if (checkBox1.Checked == false)
            {
                // Not sure what to put here
            }

            CompilerResults results = null;

            using (SaveFileDialog sfd = new SaveFileDialog() { Filter =     "Executable|*.exe"})
            {
                if (sfd.ShowDialog() == DialogResult.OK)
                {                  
                    results = Build(source, sfd.FileName);
                }
            }

            if (results.Errors.Count > 0)
                foreach (CompilerError error in results.Errors)
                    Console.WriteLine("{0} at line {1}",
                        error.ErrorText, error.Line);
            else
                Console.WriteLine("Succesfully compiled!");

            Console.ReadLine();
        }

        private static CompilerResults Build(string source, string fileName)
        {       
            CompilerParameters parameters = new CompilerParameters()
            {
                GenerateExecutable = true,
                ReferencedAssemblies = { "System.dll", "System.Windows.Forms.dll" },
                OutputAssembly = fileName,
                TreatWarningsAsErrors = false
            };

            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            return provider.CompileAssemblyFromSource(parameters, source);
        }        
    }
}

Instead of replacing part of the source code yourself, you could let the compiler do it for you by leveraging conditional compilation symbols.

You would modify your source file to include a conditional compilation symbol, eg DISABLETASKMGR, like this:

using System;
using System.Windows.Forms;
using Microsoft.Win32;

static class Program
{
    [STAThread]
    static void Main()
    {
#if DISABLETASKMGR
        RegistryKey regkey;
        string keyValueInt = "1";
        string subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";

        try
        {
            regkey = Registry.CurrentUser.CreateSubKey(subKey);
            regkey.SetValue("DisableTaskMgr", keyValueInt);
            regkey.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
#endif
    }
}

Then you set the CompilerOptions based on whether your check box is checked:

private static CompilerResults Build(string source, string fileName, bool disableTaskManager)
{
    CompilerParameters parameters = new CompilerParameters()
    {
        CompilerOptions = disableTaskManager ? "/define:DISABLETASKMGR" : "",
        GenerateExecutable = true,
        ReferencedAssemblies = { "System.dll", "System.Windows.Forms.dll" },
        OutputAssembly = fileName,
        TreatWarningsAsErrors = false
    };

    CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
    return provider.CompileAssemblyFromSource(parameters, source);
} 

This is probably going to be more maintainable than solutions based on text replacements or insertions later. Of course, still another option is to have two source files (one with the optional code and one without it) and select the appropriate one based on the settings selected by the user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM