我使用以下方法在可执行文件中嵌入任意数量的文件
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);
}
}
非常感谢任何建议或帮助。
答案 0 :(得分: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);
//....
}
}
}
}
}
}