Fadi

Fadi

  • NA
  • 1
  • 2.1k

Extract Embedded Resource Files

Mar 30 2013 6:47 AM
I am using the methods below to embed any number of files inside an executable

        private void EmbedFiles(IEnumerable<string> files)
        {
            const string exePath = @"C:\SimpleApp.exe";
 
            foreach (var file in files)
                ResourceUpdate.WriteFileToResource(exePath, file);
        }
 	[DllImport("kernel32.dll", EntryPoint = "BeginUpdateResourceW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);
        [DllImport("kernel32.dll", EntryPoint = "UpdateResourceW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, short wLanguage, byte[] lpData, int cbData);
        [DllImport("kernel32.dll", EntryPoint = "EndUpdateResourceW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
        internal static void WriteFileToResource(string path, string file)
        {
           // var resourceName = Path.GetFileNameWithoutExtension(file);
            var resourceName = Path.GetFileName(file);
            using (var binaryStream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                byte[] data = null;
                var resourceLanguage = MakeLanguageID();
                try
                {
                    data = new byte[binaryStream.Length];
                    binaryStream.Read(data, 0, (int)binaryStream.Length);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error reading {0}{1}", file, ex.Message), ex);
                }
 
                var h = BeginUpdateResource(path, false);
                Write(h, "File", resourceName, resourceLanguage, data);
            }
        }
        internal static void Write(
            IntPtr h,
            string resourceType,
            string resourceName,
            short resourceLanguage,
            byte[] buffer)
        {
            try
            {
                if (UpdateResource(h, resourceType, resourceName, resourceLanguage, buffer, buffer.Length))
                    EndUpdateResource(h, false);
                else
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error writing {0}{1}", resourceName, ex.Message), ex);
            }
        }
 
        static short MakeLanguageID()
        {
            return (short)CultureInfo.CurrentUICulture.LCID;
        }

In the code below what I am trying to do is to extract the embedded files from the target exe in order to save them in a selected directory but I am not able to find the embedded resources knowing that they are there and I can see them using a tool like Resource Hacker.

            var assembly = Assembly.GetExecutingAssembly();
 
            var names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
 
            foreach (string filename in names)
            {
                MessageBox.Show(filename);
                //var stream = assembly.GetManifestResourceStream(filename);
                //var rawFile = new byte[stream.Length];
 
                //stream.Read(rawFile, 0, (int)stream.Length);
 
                //using (var fs = new FileStream(filename, FileMode.Create))
                //{
                //    fs.Write(rawFile, 0, (int)stream.Length);
                //}
            }
        }
I created a sample project to show the problem. Please find it here

Any advice or help would be much appreciated.