提取资源中嵌入的文件

时间:2013-03-28 11:45:07

标签: c# embedded-resource

我使用以下方法在可执行文件中嵌入任意数量的文件

    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 个答案:

答案 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);
                    //....
                }
            }
        }
    }
}

}