2013-03-28 82 views
0

我使用下面的方法來嵌入可執行解壓文件

private void EmbedFiles(IEnumerable<string> files) 
    { 
     const string exePath = @"C:\SimpleApp.exe"; 

     foreach (var file in files) 
      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.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; 
    } 

內任意數量的文件在下面我試圖做的是從目標提取嵌入文件的代碼exe文件,以便將它們保存在選定的目錄中,但我無法讀取這些文件。

 var assembly = Assembly.GetExecutingAssembly(); 

     var names = Assembly.GetExecutingAssembly().GetManifestResourceNames(); 

     foreach (string filename in names) 
     { 
      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); 
      } 
     } 

任何建議或幫助,將不勝感激。

+1

什麼問題?你是否遇到異常? – niemiro

+0

是的。它在哪裏失敗?你無法找到資源?你找不到一次? –

+0

我找不到資源。 GetManifestResourceNames()不會返回這些文件。 – Fadi

回答

0

GetManifestResourceStream()似乎只顯示與.resx文件對應的.Net資源。

我在UpdateResource系列中使用了其他函數。

ResourcesManager.GetResourceFromExecutable(assembly.ManifestModule.FullyQualifiedName, "PACKAGES.TXT", ResourcesManager.RT_RCDATA); 
public static class ResourcesManager 
{ 
    public const uint RT_RCDATA = 0x10; 

    [DllImport("kernel32.dll")] 
    public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); 

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern IntPtr LoadLibrary(string lpFileName); 

    [DllImport("kernel32.dll")] 
    public static extern IntPtr FindResource(IntPtr hModule, string lpName, uint lpType); 
    // public static extern IntPtr FindResource(IntPtr hModule, int lpName, uint lpType); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); 

    [DllImport("kernel32.dll")] 
    public static extern IntPtr LockResource(IntPtr hResData); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo); 


    public static string GetResourceFromExecutable(string lpFileName, string lpName, uint lpType) 
    { 
     IntPtr hModule = LoadLibrary(lpFileName); 
     if (hModule != IntPtr.Zero) 
     { 
      IntPtr hResource = FindResource(hModule, lpName, lpType); 
      if (hResource != IntPtr.Zero) 
      { 
       uint resSize = SizeofResource(hModule, hResource); 
       IntPtr resData = LoadResource(hModule, hResource); 
       if (resData != IntPtr.Zero) 
       { 
        byte[] uiBytes = new byte[resSize]; 
        IntPtr ipMemorySource = LockResource(resData); 
        Marshal.Copy(ipMemorySource, uiBytes, 0, (int)resSize); 
        //.... 
       } 
      } 
     } 
    } 
} 

}