לאחרונה רציתי לתת ללקוח פרויקט מסוג Console Application, שבזמן ריצה הוא יעתיק מספר קבצים לתיקייה כלשהי במחשב (סוג של Installer, כאשר לא התחשק לי לכתוב פרויקט מסוג Setup), מצד שני לא ממש התחשק לי לשלוח ללקוח חמש קבצים ולהגיד לו להפעיל אחד מהם (בצורה כזו כבר יכולתי ישר לבקש ממנו להעתיק את הקבצים למקום הרלוונטי)
על כן השתמשתי במנגנון של Embedded resources.
הוספתי פיזית את הקבצים הרלוונטיים לפרויקט, כאשר במאפיינים שלהם בחרתי שהם יהיו מסוג Embedded resources (במאפיין Build Action). הושבתי אותם בתייקית בשם Matan
המשמעות היא שהקומפילציה של הפרויקט תיצור את קובץ ה – exe הרלוונטי, כאשר בתוכו מוטמעים הקבצים הרלוונטים.
כעת יש לי קובץ אחד בלבד.
בקוד עצמו (כאשר יריצו אותו) אני רוצה לחלץ החוצה את המידע ולשמור אותם היכן שהוא,
כתבתי את המתודה הבאה:
{
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
var assembly = Assembly.GetExecutingAssembly();
Write(folder, assembly, "ICSharpCode.SharpZipLib.dll");
Write(folder, assembly, "Settings.xml");
Write(folder, assembly, "WindowsUI.exe");
Write(folder, assembly, "WindowsUI.exe.config");
}
private static void Write(string folder, Assembly assembly, string fileName)
{
using (Stream stream = assembly.GetManifestResourceStream("ConsoleApplication1.Matan." + fileName))
{
using (FileStream fs = new FileStream(Path.Combine(folder, fileName), FileMode.Create))
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
fs.Write(data, 0, data.Length);
}
}
}
הקוד בדוגמה מקבל מיקום של תייקיה לשם רוצים להעתיק, במידה והתיקייה לא קיימת יוצרים אותה, ולאחר מכן אנחנו מקבלים reference ל – exe אותו אנחנו מריצים, ומפעילים מספר פעמים את פונקציית Write.
פונקציה זו מקבלת את הנתיב היכן לשמור את הקובץ, את ה – exe ושם הקובץ.
בתוך הפוקציה אנחנו משתמשים בפונקציית GetManifestResourceStream אשר מקבלת את השם המלא (שם הפרויקט, התיקיות והקובץ) כשאר אנחנו פשוט רושמים אותו ל – File System.