且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何FindResource(PInvoke的)在C#中的字符串资源?

更新时间:2023-02-12 16:33:23

  

@C:\ Users \用户myuser的\桌面\ skin.dll

显然,DLL无法加载。得到一个更好的诊断写这样的:

  IntPtr的HMOD = LoadLibraryEx(@C:\ Users \用户myuser的\桌面\ skin.dll,IntPtr.Zero,LOAD_LIBRARY_AS_DATAFILE);
   如果(HMOD == IntPtr.Zero)抛出新System.ComponentModel.Win32Exception();
 

默认构造函数Win32Exception类已经采取挖了Marshal.GetLastWin32Error()错误code和产生相应的消息为它的照顾。

找不到文件很可能在这里。你必须要留意的桌面文件夹,外壳实际上并没有显示出C含量:\ Users \用户提供yourname \桌面文件夹,你会得到一个融合的几个文件夹。当你引用的文件夹中的code这种混合不会发生。一个可能的位置,该文​​件是C:\用户\公用\桌面。解决这个问题的正确途径,确保DLL位于同一目录作为主EXE。项目+添加现有项目,导航到DLL,以便它被添加到您的项目。选择它,并设置复制到输出目录属性为复制,如果新。

修改后:资源类型参数可能有麻烦了。无论是用#23或声明的参数类型为整数,这样你就可以通过23。

I've searched a lot, but I couldn't find how to load a resource which ID is a string. The tutorial Here is good, but doesn't do that. Does someone know how to make it? Here's my structure. I want to load the pngs.



And the code:

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[DllImport("kernel32.dll")]
static extern IntPtr FindResource(IntPtr hModule, int lpID, string lpType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);

const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;

void LoadSkin() {
    IntPtr hMod = LoadLibraryEx(@"C:\Users\myuser\Desktop\skin.dll", IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);            
    IntPtr hRes = FindResource(hMod, "BACK.PNG", "23");

    MessageBox.Show(hRes.ToString()); // <- 0 here.

    uint size = SizeofResource(hMod, hRes);
    IntPtr pt = LoadResource(hMod, hRes);

    Bitmap bmp;
    byte[] bPtr = new byte[size];
    Marshal.Copy(pt, bPtr, 0, (int) size);
    using (MemoryStream m = new MemoryStream(bPtr))
        bmp = (Bitmap) Bitmap.FromStream(m);
}

EDIT:

Fixed it. The problem was in the declaration of FindResource. For my case the correct one was:

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, uint 

lpType);

@"C:\Users\myuser\Desktop\skin.dll"

Clearly the DLL could not be loaded. Get a better diagnostic by writing it like this:

   IntPtr hMod = LoadLibraryEx(@"C:\Users\myuser\Desktop\skin.dll", IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
   if (hMod == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();

The default constructor for the Win32Exception class already takes care of digging up the Marshal.GetLastWin32Error() error code and generating the appropriate message for it.

File not found is likely here. You have to watch out for the Desktop folder, the shell doesn't actually show the content of the c:\users\yourname\desktop folder, you get a blend of several folders. This blending doesn't happen when you refer to the folder in your code. One possible location for the file is c:\users\public\desktop. Solve this problem the right way, ensure that the DLL is located in the same directory as your main EXE. Project + Add Existing Item, navigate to the DLL so it is added to your project. Select it and set the Copy to Output Directory property to "Copy if newer".

After edit: the resource type argument could be trouble too. Either use "#23" or declare the argument type as integer so you can pass 23.