2007年5月20日 星期日

(C#)MP3 轉 EXE 的方法
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.05.21 建立

測試環境
1. Windows XP Pro SP2
2. Visual Studio 2005

原理
[1]提供的方法是動態編譯產生播放 MP3 的程式。這個程式樣板存放在 Resource 中,當產生 MP3 的 EXE 檔案時,從資源檔中萃取出該樣板,並將 MP3 內嵌到 EXE 檔的 Resource 中,當 EXE 執行時,再從 Resource 中取出 MP3 來播放。

程式碼剖析

產生 EXE 的程式片段
// 指定存放 EXE 的檔名和目錄
SaveFileDialog sv = new SaveFileDialog();
sv.RestoreDirectory = true;
sv.OverwritePrompt = true;
sv.Filter = "exe file (*.exe)|*.exe";
sv.DefaultExt = "exe";
if (sv.ShowDialog() == DialogResult.OK)
{
// 1. 建立 C# 程式碼產生和編譯的物件
Microsoft.CSharp.CSharpCodeProvider pr = new Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
string pathtoicon="";
if (File.Exists(Application.StartupPath + "\icon.ico"))
{
pathtoicon= Application.StartupPath + "\icon.ico";
}
if (skinRadioButton2.Checked)
{
pathtoicon = this.pictureBox1.ImageLocation;
}

// 2. 設定編譯器參數
// 2.1 叫用編譯器時,要使用之選擇性的其他命令列引數字串
// 產生 windows 的 EXE 檔,並使用指定 icon 檔
cp.CompilerOptions = "/target:winexe" + " " + "/win32icon:" + """ + pathtoicon + """;
// 2.2 產生可執行檔
cp.GenerateExecutable = true;
// 2.3 不包含除錯資訊
cp.IncludeDebugInformation = false;
// 2.4 內嵌 MP3 資源
cp.EmbeddedResources.Add(this.textBox1.Text);
// 2.5 輸出的 EXE 檔名
cp.OutputAssembly = sv.FileName;
// 2.6 不在記憶體中產生輸出
cp.GenerateInMemory = false;
// 2.7 EXE 參照的 Assembly
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");
// 2.8 不將警告當做錯誤
cp.TreatWarningsAsErrors = false;

// 3. 編譯 *.cs 產生 *.exe
CompilerResults cr = pr.CompileAssemblyFromFile(cp, Environment.GetEnvironmentVariable("TEMP") + "\it.cs");
if (cr.Errors.Count>0)
{
MessageBox.Show("There was an error while converting the file","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}


播放 MP3 的程式樣板核心片段
// 隱藏程式 UI
this.Hide();
this.ShowInTaskbar = false;

// 從 Resource 取出 mp3
string[] a = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
Stream theResource = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(a[0]);
BinaryReader br = new BinaryReader(theResource);
FileStream fs = new FileStream(Environment.GetEnvironmentVariable("TEMP")+"\it.mp3", FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
byte[] bt = new byte[theResource.Length];
theResource.Read(bt,0, bt.Length);
bw.Write(bt);
br.Close();
bw.Close();

// 播放 mp3
MP3Player pl = new MP3Player();
try
{
pl.Open(Environment.GetEnvironmentVariable("TEMP") + "\it.mp3");
pl.Play();
while (pl.CurrentPosition != pl.AudioLength)
{ }
Application.Exit();
}
catch (Exception ex)
{ }
Application.Exit();


MP3Player 在 [1] 中是使用 Win32 API 的 mciSendString() 來實作,這部份並非本文的重心,故有興趣者自行參考[1]的原始碼或 MSDN 說明。

結語
由於 .NET 提供將 C# 產生 EXE 的類別,且又支援 Reflection 因此可以很容易達到任意資源轉換成 EXE 檔的方法,透過上述說明,你應該知道如何自行擴充將圖檔或其他檔案轉成 EXE 。

參考資料
[1] http://www.codeproject.com/useritems/mp3toexe.asp
[2] CSharpCodeProvider Class (Microsoft.CSharp)
[3] CompilerParameters Class (System.CodeDom.Compiler)

沒有留言:

搜尋此網誌