65.9K
CodeProject 正在变化。 阅读更多。
Home

批处理文件编译器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.82/5 (47投票s)

2007年6月17日

CPOL

1分钟阅读

viewsIcon

173082

downloadIcon

3522

一篇文章,描述如何将批处理文件转换为可执行文件。

目录

引言

本文档展示了如何将批处理文件编译成可执行文件。编译后的可执行文件可以在不显示窗口的情况下运行,并且您可以像传递给批处理文件一样向其传递命令行参数。

程序工作原理

这个程序编译批处理文件的方式相当巧妙且奇怪,所以我称这个程序为“模拟编译器”。批处理文件甚至没有被解析。这个程序创建另一个程序,并将指定的批处理文件作为嵌入文件添加到该程序中。当生成的程序执行时,它会将嵌入的批处理文件提取到临时文件夹中,并使用 Process 类运行它。很简单,不是吗?

使用代码

为了从您的应用程序创建另一个程序,您需要创建 CSharpCodeProvider 类的一个实例。下面的代码片段展示了如何操作。

using (CSharpCodeProvider code=new CSharpCodeProvider())
{
    CompilerParameters compar = new CompilerParameters();

    string option = "/target:winexe";

    // Set the icon for executable
    if (Properties.Settings.Default.Customicon && 
        File.Exists(Properties.Settings.Default.iconpath))
    {
       option += " " + "/win32icon:" + "\"" + 
                 Properties.Settings.Default.iconpath + "\"";
    }

    compar.CompilerOptions = option;
    compar.GenerateExecutable = true;
    compar.IncludeDebugInformation = false;

    //Add the bat file as an embedded resource
    if (File.Exists(filepath))
    {
       compar.EmbeddedResources.Add(filepath); 
    }

    compar.OutputAssembly = path;
    compar.GenerateInMemory = false; 

    //Add references
    compar.ReferencedAssemblies.Add("System.dll");
    compar.ReferencedAssemblies.Add("System.Data.dll");
    compar.ReferencedAssemblies.Add("System.Deployment.dll");
    compar.ReferencedAssemblies.Add("System.Drawing.dll");
    compar.ReferencedAssemblies.Add("System.Windows.Forms.dll");
    compar.ReferencedAssemblies.Add("System.Xml.dll");

    compar.TreatWarningsAsErrors = false;

    //Compile it
    //The code is included in the executable as a resource
    CompilerResults res = 
              code.CompileAssemblyFromSource(compar, Properties.Resources.Program);

    if (res.Errors.Count > 0)
    {
       result = false;
    }
    else
       result = true;
    }

当您运行生成的可执行文件时,它将提取批处理文件,处理命令行参数(如果有的话),并运行它。如果指定,批处理文件将在不创建任何窗口的情况下运行。以下是展示如何实现此功能的代码。

//This code requires System.Reflection namespace
//Extracts the bat file
private void extract()
{
    string name = Assembly.GetExecutingAssembly().GetManifestResourceNames()[0];
    hide = name.EndsWith("hideit.bat");

    Stream theResource = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);

    BinaryReader br = new BinaryReader(theResource);
    FileStream fs = new FileStream(Environment.GetEnvironmentVariable("TEMP") + 
                    "\\it.bat", FileMode.Create);

    byte[] bt = new byte[theResource.Length];
    theResource.Read(bt, 0, bt.Length);
    fs.Write(bt, 0, bt.Length);

    br.Close();
    fs.Close();
}

//Process command line arguments
private string buildargument(string[] args)
{
    StringBuilder arg = new StringBuilder();

    for (int i = 0; i < args.Length; i++)
    {
       arg.Append(args[i] + " ");
    }

    return arg.ToString();
}

//Start the process
private void start(string[] args)
{
    ProcessStartInfo info = new ProcessStartInfo();
    info.FileName = Environment.GetEnvironmentVariable("TEMP") + "\\it.bat";

    //Specify argument
    info.Arguments = buildargument(args);

    //Hide the window if specified
    info.CreateNoWindow = hide;
    if (hide)
    {
        info.WindowStyle = ProcessWindowStyle.Hidden;
    }

    //Set the working directory for the bat file. This is important as the
    //bat file might use relative path
    info.WorkingDirectory = Application.StartupPath;

    //At last start the process
    Process proc = new Process();
    proc.StartInfo = info;
    proc.Start();
}

关注点

这个程序编译批处理文件的方式相当巧妙且有点奇怪。

历史

  • 2007年6月17日 - 初始发布。
© . All rights reserved.