2013-02-21 69 views
1

我的fingers are hurtin'。我試圖從我的exe使用WinApi(FindResource)加載資源。我已經使用WinApi成功創建了一個字符串資源,並驗證了它們與PE Explorer,Resource Hacker和Hex Editor存在。FindResource找不到資源雖然他們存在

我不能做的是通過FindResource找到它們。該函數完成後,返回一些指針並將LastError設置爲0.但指針b指向無效內存。我嘗試以4種不同的方式導入FindResource,並且都有相同的結果(b1,b2,b3,b4表示每個聲明的b)。我發現我需要調用LoadLibrary率先做出FindResource找到「東西」(A1 = A2 2個相同的模塊處理該點正是 exe文件的開頭在內存中加載後,就具有不同的功能獲得) 。


我以爲 a(a = a1 = a2)和 b必須位於相同的存儲空間(偏移到模塊開始?)。但b與a的差別始終是相同的16568.在十六進制編輯器中,我發現我的字符串在8000左右的某個位置,並且在創建每個資源之後會有所不同。我有想法可能是錯誤的,但我不知道:

  • MAKELANGID(0, 0)〜我的理解是0和0立場中立的,我讀的地方,有可能是一些關於*.mui文件?
  • 創建資源破碎資源?其實這兩個資源編輯器都沒有問題顯示我的資源
  • 進口聲明可能是錯誤的,但我已經嘗試了這麼多的可能性,那些是最好的
  • 資源需要打開/鎖定/不管?

如何成功找到資源?我的代碼中是否有錯誤?


public static class MyClass 
{ 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
    public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string fileName); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
    public static extern bool FreeLibrary(IntPtr module); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
    public static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPStr)] string filename); 

    [DllImport("kernel32.dll")] 
    public static extern IntPtr BeginUpdateResource([MarshalAs(UnmanagedType.LPStr)] string filename, bool deleteExistingResources); 
    [DllImport("kernel32.dll")] 
    public static extern bool UpdateResource(IntPtr resource, [MarshalAs(UnmanagedType.LPStr)] string type, [MarshalAs(UnmanagedType.LPStr)] string name, ushort language, IntPtr data, uint dataSize); 
    [DllImport("kernel32.dll")] 
    public static extern bool EndUpdateResource(IntPtr resource, bool discard); 

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)] 
    public static extern IntPtr FindResource1(IntPtr module, [MarshalAs(UnmanagedType.LPStr)]string name, [MarshalAs(UnmanagedType.LPStr)] string type); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)] 
    public static extern IntPtr FindResource2(IntPtr module, IntPtr name, IntPtr type); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)] 
    public static extern IntPtr FindResource3(IntPtr module, [In, MarshalAs(UnmanagedType.LPStr)]string name, [In, MarshalAs(UnmanagedType.LPStr)] string type); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)] 
    public static extern IntPtr FindResource4(IntPtr module, string lpName, string lpType); 

    public static ushort MAKELANGID(ushort primaryLanguage, ushort subLanguage) 
    { 
     return Convert.ToUInt16((subLanguage << 10) | primaryLanguage); 
    } 

    private static void test() 
    { 
     string filename1 = "MyApp.exe"; 
     string filename2 = "MyApp2.exe"; 
     //if (!File.Exists(filename2)) 
     { 
      // creating resource: name = TEST, type = SYSO, lang-id = neutral 
      File.Copy(filename1, filename2, true); 
      IntPtr res = BeginUpdateResource(filename2, false); 
      string s = "aaahello world"; 
      UpdateResource(res, "SYSO", "TEST", MAKELANGID(0, 0), Marshal.StringToHGlobalAnsi(s), (uint) (s.Length)); 
      EndUpdateResource(res, false); 
     } 
     // find resource 
     IntPtr a1 = LoadLibrary(filename2); 
     IntPtr a2 = GetModuleHandle(filename2); 
     IntPtr hInstance = Marshal.GetHINSTANCE(typeof(MyClass).Module); 
     if (a1 == a2) 
      Console.WriteLine("a1 = a2 = " + a2 + ", hInstance: " + hInstance); 
     else 
      Console.WriteLine(a1 + " != " + a2); 

     for (int i = 0; i < 10; i++) 
      Console.WriteLine("." + Marshal.ReadByte(a2 + i)); 

     IntPtr b1 = FindResource1(a2, "TEST", "SYSO"); 
     IntPtr b2 = FindResource2(a2, Marshal.StringToHGlobalAnsi("TEST"), Marshal.StringToHGlobalAnsi("SYSO")); 
     IntPtr b3 = FindResource3(a2, "TEST", "SYSO"); 
     IntPtr b4 = FindResource4(a2, "TEST", "SYSO"); 

     Console.WriteLine(" -> res: " + b1 + ", " + (b1.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b1)); 
     Console.WriteLine(" -> res: " + b2 + ", " + (b2.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b2)); 
     Console.WriteLine(" -> res: " + b3 + ", " + (b3.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b3)); 
     Console.WriteLine(" -> res: " + b4 + ", " + (b4.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b4)); 

     for (int i = 0; i < 10; i++) 
      Console.WriteLine("." + Marshal.ReadByte(b1 + i)); 
    } 

    [STAThread] 
    public static void Main() 
    { 
     test(); 
     Console.ReadKey(); 
    } 
} 


我知道有很多很多,大約FindResource很多帖子在互聯網上,我讀了很多人,但什麼都沒有這個問題解決。

回答

3

FindResource()返回句柄,而不是指向資源的指針;它需要更多的步驟來獲取數據。您需要LoadResource()然後LockResource()以獲取指向實際資源字節的指針。

據我可以告訴這是從16位的舊天保留。

+0

這是正確的謝謝!問題解決了!只有SizeofResource的提示丟失了!只需要挖出來。 – Bitterblue 2013-02-22 08:52:47