如何从DLL中提取字符串资源

时间:2017-01-31 22:10:33

标签: c# dll pinvoke

我正在制作管理系统文件扩展名的应用程序,我遇到了问题。

.jpg.exe.dll.png.txt等系统扩展程序具有名为FriendlyTypeName的注册表值,例如,jpeg文件的FriendlyTypeName@%SystemRoot%\System32\shell32.dll,-30596。显示的值取决于当前语言。

如何使用C#从资源ID(例如:-30596)中提取字符串值。我猜可以使用p / invoke提取字符串(我不确定)。

1 个答案:

答案 0 :(得分:4)

可以使用LoadStringLoadIcon等提取资源。但是,hInstance必须与您的应用hInstance不同,否则,您将只能从您自己的.exe中提取资源。如果要从系统库等外部DLL中提取任何资源,则必须通过调用hInstance获取要提取的DLL的LoadLibrary,并调用FreeLibrary以完成文件使用。

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int LoadString(IntPtr hInstance, int ID, StringBuilder lpBuffer, int nBufferMax);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeLibrary(IntPtr hModule);

private string ExtractStringFromDLL(string file, int number) {
    IntPtr lib = LoadLibrary(file);
    StringBuilder result = new StringBuilder(2048);
    LoadString(lib, number, result, result.Capacity);
    FreeLibrary(lib);
    return result.ToString();
}

StringBuilder最大容量为2048(如果您希望可以更改该值)。

以下是一个例子:

string loadedString = ExtractStringFromDLL("shell32.dll", 30596);
Debug.Write(loadedString);

视窗'默认相对路径为%SystemRoot%\system32,除非您从非系统DLL中提取字符串,否则不需要包含完整路径。

请勿忘记从资源编号中删除-符号,因为负数表示FriendlyTypeName的资源ID,LoadString需要正数作为资源ID。

编辑:您还可以从.exe文件和包含资源的任何文件中提取资源。