[简介]
从这篇文章中,你将会学习到如何把一个mp3音乐文件转换成一个可执行的exe文件。
[将会学习到的知识点]
如何在运行过程中编译 C#代码
如何使用C#播放mp3文件
如何把一个文件作为一个嵌入的资源放在你的应用程序中,如何在运行时,动态地提取出已嵌入的资源。
如何实现从资源管理器中拖拽文件到你的应用程序中。
如何通过设计器把一个文件作为嵌入资源插入你的应用程序中。
[转换]
下面将描述本程序的工作原理:
首先,用户选择一个希望转换成应用程序的mp3文件,于是,一个CompilerParameters的实例会被创建,通过CompilerParameters类中的EmbeddedResources属性将选中的mp3文件添加成嵌入资源。这个过程实现在一个使用BackGroundWorker组件的工作线程中。用户可以选择可执行文件的图标,程序会通过命令行选项指示它。
我们所编译的应用程序非常简单,它不包括窗口,直接提取出已嵌入的mp3文件,并播放它。当应用程序一执行的时候,资源文件就会被提取到一个临时文件夹里。
[实现细节]
动态编译资源文件
Microsoft.CSharp.CSharpCodeProvider pr
= new Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
string pathtoicon=""; // 为应用程序,保存图标文件位置的pathtoicon变量
if (File.Exists(Application.StartupPath + "\icon.ico"))
{
pathtoicon= Application.StartupPath + "\icon.ico";
}
if (skinRadioButton2.Checked)
{
pathtoicon = this.pictureBox1.ImageLocation;
}
cp.CompilerOptions = "/target:winexe" + " " + "/win32icon:" + """ +
pathtoicon + """; // 编译选项
cp.GenerateExecutable = true; // yes 产生一个exe文件
cp.IncludeDebugInformation = false; // here we add the mp3 file as
// asn embedded resource
cp.EmbeddedResources.Add(this.textBox1.Text); // were to save the executable
// specified by savefiledialog
cp.OutputAssembly = sv.FileName;
cp.GenerateInMemory = false;
cp.ReferencedAssemblies.Add("System.dll"); // 应用程序的引用
cp.ReferencedAssemblies.Add("System.Data.dll");
cp.ReferencedAssemblies.Add("System.Deployment.dll");
cp.ReferencedAssemblies.Add("System.Drawing.dll");
cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
cp.ReferencedAssemblies.Add("System.Xml.dll");
cp.TreatWarningsAsErrors = false;
string temp = Environment.GetEnvironmentVariable("TEMP");
// compile the source file
CompilerResults cr = pr.CompileAssemblyFromFile(cp, temp + "\it.cs");
if (cr.Errors.Count>0)
{
MessageBox.Show("There was an error while converting the file","Error",
MessageBoxButtons.OK,MessageBoxIcon.Error); //error cheking
}
在运行时,提取嵌入的资源
这一部分代码来源于即将被程序编译的资源文件。下面的代码用以在程序运行的时候提取资源文件。
//代码需要引用System.Reflection 命名空间
//获取在程序集中的资源名称
string[] myassembly
= Assembly.GetExecutingAssembly().GetManifestResourceNames();
// 创建资源流
Stream theResource
= Assembly.GetExecutingAssembly().GetManifestResourceStream(myassembly[0]);
//通过数据流读取二进制数据
BinaryReader br = new BinaryReader(theResource);
//then filestream
FileStream fs = new FileStream(Environment.GetEnvironmentVariable("TEMP") +
+"\it.mp3" , FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs); //and then binary writer
byte[] bt = new byte[theResource.Length]; //read the resource
theResource.Read(bt,0, bt.Length); // 接下来,写入文件
bw.Write(bt); //别忘了关闭所有流
br.Close();
bw.Close();
因为这里只有一个资源,所以,我们给GetManifestResourceStream传递了 myassambly[0]
[拖拽功能]
为了实现从资源管理器的拖拽功能,我使用了来自这篇文章的源码
你需要创建DragAndDropFileComponent类的实例,并设置事件句柄。此处贴出了部分代码片断:
DragAndDropFileComponent drag = new DragAndDropFileComponent(this.components);
drag.BeginInit();
drag.FileDropped += new FileDroppedEventHandler(drag_FileDropped);
drag.HostingForm = this;
drag.EndInit();
下面是其事件处理代码:
void drag_FileDropped(object sender, FileDroppedEventArgs e)
{
if (e.Filenames!=null & e.Filenames.Length!=0 & e.Filenames[0].EndsWith(".mp3"))
{
this.textBox1.Text = e.Filenames[0];
}
}
[播放mp3文件]
为了在我的应用程序中播放mp3文件,我参考了http://www.codeproject.com/cs/media/MP3Example.asp文章。MP3Player类可以让你很容易地播放mp3文件,这里是其中的代码片断:
MP3Player pl = new MP3Player();
try
{
pl.Open(Environment.GetEnvironmentVariable("TEMP") + "\it.mp3");
pl.Play();
//wait until the file is played and then quit
//this no longer causes 100% cpu utilization
System.Threading.Thread.Sleep(((int)pl.AudioLength)+1);
Application.Exit();
}
catch (Exception ex)
{ }
程序将在其一开始播放mp3文件,并在播放完毕后,退出。
[想法]
做这个mp3转换成exe文件的代码,只是源于好奇和兴趣。
[历史]
May 18 最初版本
May 26 修改了当执行exe文件时,占用100%cpu的bug。
[原文作者]
Giorgi Dalakishvili