各位大师,如何从资源dll中枚举字符串资源?更精确的是如何从一个第三方dll中得到字符串资源的id?谢谢大家!

解决方案 »

  1.   

    你需要了解PE文件的格式,明白了格式别的好处理了
    见http://www.csdn.net/develop/article/17/17421.shtm,PE文件格式的介绍
      

  2.   

    MSDN例程char szBuffer[80]; // print buffer for EnumResourceTypes 
    DWORD cbWritten;   // number of bytes written to res. info. file 
    int cbString;      // length of string in sprintf 
     
    // Declare callback functions. 
    BOOL EnumTypesFunc( 
        HANDLE hModule, 
        LPTSTR lpType, 
        LONG lParam); 
     
    BOOL EnumNamesFunc( 
        HANDLE hModule, 
        LPCTSTR lpType, 
        LPTSTR lpName, 
        LONG lParam); 
     
    BOOL EnumLangsFunc( 
        HANDLE hModule, 
        LPCTSTR lpType, 
        LPCTSTR lpName, 
        WORD wLang, 
        LONG lParam); 
     
    // Load the .EXE whose resources you want to list. 
    hExe = LoadLibrary("hand.exe"); 
     
    if (hExe == NULL) 

        ErrorHandler("Could not load .EXE."); 

     
    // Create a file to contain the resource info. 
    hFile = CreateFile("resinfo.txt",      // name of file 
        GENERIC_READ | GENERIC_WRITE,      // access mode 
        0,                                 // share mode 
        (LPSECURITY_ATTRIBUTES) NULL,      // no security 
        CREATE_ALWAYS,                     // create flags 
        FILE_ATTRIBUTE_NORMAL,             // file attributes 
        (HANDLE) NULL);                    // no template 
    if (hFile == INVALID_HANDLE_VALUE) { 
        ErrorHandler("Could not open file."); 

     
    // Find all of the loaded file's resources. 
    cbString = sprintf(szBuffer, 
        "The file contains the following resources:\n\n"); 
     
    WriteFile(hFile,           // file to hold resource info. 
        szBuffer,              // what to write to the file 
        (DWORD) cbString,      // number of bytes in szBuffer 
        &cbWritten,            // number of bytes written 
        NULL);                 // no overlapped I/O 
     
    EnumResourceTypes(hExe,              // module handle 
        (ENUMRESTYPEPROC)EnumTypesFunc,  // callback function 
        0);                              // extra parameter 
     
    // Unload the executable file whose resources were 
    // enumerated and close the file created to contain 
    // the resource information. 
     
    FreeLibrary(hExe); 
    CloseHandle(hFile); 
     
    //    FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG) 
    // 
    //    PURPOSE:  Resource type callback 
     
    BOOL EnumTypesFunc( 
        HANDLE hModule,   // module handle 
        LPTSTR lpType,    // address of resource type 
        LONG lParam)      // extra parameter, could be 
                          // used for error checking 

        int cbString; 
     
        // Write the resource type to a resource information file. 
        // The type may be a string or an unsigned decimal 
        // integer, so test before printing. 
     
        if ((ULONG)lpType & 0xFFFF0000) 
        { 
            cbString = sprintf(szBuffer, "Type: %s\n", lpType); 
        } 
        else 
        { 
            cbString = sprintf(szBuffer, "Type: %u\n", (USHORT)lpType); 
        } 
     
        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 
     
        // Find the names of all resources of type lpType. 
        EnumResourceNames(hModule, 
            lpType, 
            (ENUMRESNAMEPROC)EnumNamesFunc, 
            0); 
     
        return TRUE; 

     
    //    FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG) 
    // 
    //    PURPOSE:  Resource name callback 
     
    BOOL EnumNamesFunc( 
        HANDLE hModule,   // module handle 
        LPCTSTR lpType,   // address of resource type 
        LPTSTR lpName,    // address of resource name 
        LONG lParam)      // extra parameter, could be 
                          // used for error checking 

        int cbString; 
     
         // Write the resource name to a resource information file. 
         // The name may be a string or an unsigned decimal 
         // integer, so test before printing. 
     
        if ((ULONG)lpName & 0xFFFF0000) 
        { 
            cbString = sprintf(szBuffer, "\tName: %s\n", lpName); 
        } 
        else 
        { 
            cbString = sprintf(szBuffer, "\tName: %u\n", 
                (USHORT)lpName); 
        } 
     
        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 
     
         // Find the languages of all resources of type 
         // lpType and name lpName. 
     
        EnumResourceLanguages(hModule, 
            lpType, 
            lpName, 
            (ENUMRESLANGPROC)EnumLangsFunc, 
            0); 
     
        return TRUE; 

     
    //    FUNCTION: EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG) 
    // 
    //    PURPOSE:  Resource language callback 
     
    BOOL EnumLangsFunc( 
        HANDLE hModule,  // module handle 
        LPCTSTR lpType,  // address of resource type 
        LPCTSTR lpName,  // address of resource name 
        WORD wLang,      // resource language 
        LONG lParam)     // extra parameter, could be 
                            used for error checking 

        HANDLE hResInfo; 
        char szBuffer[80]; 
        int cbString = 0; 
     
        hResInfo = FindResourceEx(hModule, lpType, lpName, wLang); 
     
        // Write the resource language to the resource information file. 
        cbString = sprintf(szBuffer, "\t\tLanguage: %u\n", USHORT)wLang); 
     
        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 
     
        // Write the resource handle and size to buffer. 
        cbString = sprintf(szBuffer, 
            "\t\thResInfo == %lx,  Size == %lu\n\n", 
            hResInfo, 
            SizeofResource(hModule, hResInfo)); 
     
        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 
     
        return TRUE; 

      

  3.   

    谢谢大家,我把我的例子贴在下面,请高手看看:#define EXEEXAMPLE "C:\\temp\\shutdown.exe"HANDLE hFile;
    char szBuffer[256]; // print buffer for EnumResourceTypes 
    DWORD cbWritten;   // number of bytes written to res. info. file 
    int cbString;      // length of string in sprintf // Declare callback functions. 
    BOOL EnumTypesFunc( 
       HANDLE hModule, 
       LPTSTR lpType, 
       LONG lParam); BOOL EnumNamesFunc( 
       HANDLE hModule, 
       LPCTSTR lpType, 
       LPTSTR lpName, 
       LONG lParam); BOOL EnumLangsFunc( 
       HANDLE hModule, 
       LPCTSTR lpType, 
       LPCTSTR lpName, 
       WORD wLang, 
       LONG lParam); char* ReadIconFromEXEFile( LPCTSTR szFileName,LPTSTR lpID , UINT uID)
    {
        char*     lpIR = NULL, lpNew = NULL;
        HINSTANCE         hLibrary;


        // Load the DLL/EXE - NOTE: must be a 32bit EXE/DLL for this to work
        if( (hLibrary = LoadLibraryEx( szFileName, NULL, LOAD_LIBRARY_AS_DATAFILE )) == NULL )
        {
            // Failed to load - abort
            MessageBox(AfxGetMainWnd()->m_hWnd , "装入文件时出错 - 请选择一个WIN32的DLL或EXE文件!", szFileName, MB_OK );
            return NULL;
        }

    HRSRC         hRsrc = NULL;
    HGLOBAL         hGlobal = NULL;
    UINT            i;

    // Find the group icon resource
    if( (hRsrc = FindResource( hLibrary, lpID, RT_STRING )) == NULL )
    {
    FreeLibrary( hLibrary );
    return NULL;
    }
    if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL )
    {
    FreeLibrary( hLibrary );
    return NULL;
    }

    memset (szBuffer, 0, 1000);
    //###################################################################
    //这样也读不到字符串内容. why???????????????????????????
    //###################################################################
    memcpy(szBuffer, LockResource(hGlobal),100);
    ////cbString = sprintf(szBuffer, "\tresource = %s\n", szBuffer);
    //WriteFile(hFile, szBuffer, (DWORD) 100,   &cbWritten, NULL); 


    memset (szBuffer, 0, 1000);
    //###################################################################
    //uID不是从vc中读出的id. why???????????????????????????
    //###################################################################
    LoadString(hLibrary,  // handle to resource module
    uID,             // resource identifier
    szBuffer,      // resource buffer
    256        // size of buffer
    );
    TRACE0(szBuffer);

    cbString = sprintf(szBuffer, "\t %s\n", szBuffer);
    WriteFile(hFile, szBuffer, (DWORD) cbString,   &cbWritten, NULL); 

        FreeLibrary( hLibrary );
        return lpIR;
    }
    //    FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG) 
    // 
    //    PURPOSE:  Resource type callback 
    BOOL EnumTypesFunc( 
       HANDLE hModule,   // module handle 
       LPTSTR lpType,    // address of resource type 
       LONG lParam)      // extra parameter, could be 
       // used for error checking 

        int cbString; 
        // Write the resource type to a resource information file. 
        // The type may be a string or an unsigned decimal 
        // integer, so test before printing. 
    if ((ULONG)lpType & 0xFFFF0000) 
        { 
    cbString = sprintf(szBuffer, "Type: %s \n", lpType,(lpType == RT_STRING?"STRING!":"")); 
        } 
        else 
        { 
            cbString = sprintf(szBuffer, "Type: %u %s\n", (USHORT)lpType,(lpType == RT_STRING?"STRING!":"")); 
        } 


        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 



        // Find the names of all resources of type lpType. 
        EnumResourceNames((struct HINSTANCE__ *)hModule, 
            lpType, 
            (ENUMRESNAMEPROC)EnumNamesFunc, 
            0); 

        return TRUE; 
    } //    FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG) 
    // 
    //    PURPOSE:  Resource name callback 
    BOOL EnumNamesFunc( 
       HANDLE hModule,   // module handle 
       LPCTSTR lpType,   // address of resource type 
       LPTSTR lpName,    // address of resource name 
       LONG lParam)      // extra parameter, could be 
       // used for error checking 

        int cbString; 
    // Write the resource name to a resource information file. 
    // The name may be a string or an unsigned decimal 
    // integer, so test before printing. 
        if ((ULONG)lpName & 0xFFFF0000) 
        { 
            cbString = sprintf(szBuffer, "\tName: %s\n", lpName); 

    if (lpType == RT_STRING){
    ReadIconFromEXEFile( EXEEXAMPLE,  lpName, 0);
    };
        } 
        else 
        { 
    //######################################################
    // 为什么这儿得不到正确的id.????????????
    //
    //######################################################
            cbString = sprintf(szBuffer, "\tName: %u\n", 
                (USHORT)lpName); 
    if (lpType == RT_STRING){
    ReadIconFromEXEFile( EXEEXAMPLE,  lpName, (USHORT)lpName);
    };
        } 


        WriteFile(hFile, szBuffer, (DWORD) cbString, 
            &cbWritten, NULL); 
    // Find the languages of all resources of type 
    // lpType and name lpName. 
    /*
        EnumResourceLanguages((struct HINSTANCE__ *)hModule, 
            lpType, 
            lpName, 
            (ENUMRESLANGPROC)EnumLangsFunc, 
            0); 
    */
        return TRUE; 

    void CResReaderDlg::OnOK() 
    {
    char szBuffer[256]; // print buffer for EnumResourceTypes 
    DWORD cbWritten;   // number of bytes written to res. info. file 
    size_t cbString;      // length of string in sprintf
    HRESULT hResult;
    HINSTANCE hExe;


    // Load the .EXE whose resources you want to list. 
    hExe = LoadLibrary(EXEEXAMPLE); 
    if (hExe == NULL) 

    TRACE0("Could not load .EXE."); 


    // Create a file to contain the resource info. 
    hFile = CreateFile("resinfo.txt",      // name of file 
    GENERIC_READ | GENERIC_WRITE,      // access mode 
    0,                                 // share mode 
    (LPSECURITY_ATTRIBUTES) NULL,      // no security 
    CREATE_ALWAYS,                     // create flags 
    FILE_ATTRIBUTE_NORMAL,             // file attributes 
    (HANDLE) NULL);                    // no template 
    if (hFile == INVALID_HANDLE_VALUE) { 
    TRACE0("Could not open file."); 


    // Find all of the loaded file's resources. 
    cbString = sprintf(szBuffer, 
    "The file contains the following resources:\n\n"); 
    WriteFile(hFile,           // file to hold resource info. 
    szBuffer,              // what to write to the file 
    (DWORD) cbString,      // number of bytes in szBuffer 
    &cbWritten,            // number of bytes written 
    NULL);                 // no overlapped I/O 

    EnumResourceTypes(hExe,              // module handle 
    (ENUMRESTYPEPROC)EnumTypesFunc,  // callback function 
    0);                              // extra parameter 
    // Unload the executable file whose resources were 
    // enumerated and close the file created to contain 
    // the resource information. 
    FreeLibrary(hExe); 
    CloseHandle(hFile); 

    CDialog::OnOK();
    }
      

  4.   

    如何理解?Creating a Resource List
    The following example creates a list of every resource in the Hand.exe file. The list is written to the Resinfo.txt file. The code demonstrates how to load the executable file, create a file in which to write resource information, and call the EnumResourceTypes function to send each resource type found in the module to the application-defined callback function EnumTypesFunc. See EnumResTypeProc for information on callback functions of this type. This callback function uses the EnumResourceNames function to pass the name of every resource within the specified type to another application-defined callback function, EnumNamesFunc. See EnumResNameProc for information on callback functions of this type. EnumNamesFunc uses the EnumResourceLanguages function to pass the language of every resource of the specified type and name to a third callback function, EnumLangsFunc. See EnumResLangProc for information on callback functions of this type. EnumLangsFunc writes information about the resource of the specified type, name, and language to the Resinfo.txt file. Note that the lpszType in EnumResTypeProc is either a resource identifier (ID) or a pointer to a string (containing a resource ID or type name); lpszType and lpszName in EnumResNameProc are similar. To use an enumerated resource, take the resource name or ID and call the appropriate function. For example, to load a string resource (RT_STRING), if lpszName in EnumResNameProc gives the resource ID (either directly or in a string that starts with the pound sign (#)), call LoadString. Otherwise, lpszName points to a string containing the resource name, so do the following: call FindResource or FindResourceEx with the resource name to get the resource handle; 
    call LoadResource with the resource handle to get the global handle; 
    call LockResource with the global handle to get a pointer to the resource data.
      

  5.   

    依msdn所说:to load a string resource (RT_STRING), if lpszName in EnumResNameProc gives the resource ID (either directly or in a string that starts with the pound sign (#)), call LoadString. Otherwise, lpszName points to a string containing the resource name, so do the following: 我读出的却不是,为什么?请大家看看用#####表示的代码。
      

  6.   

    //######################################################
    // 为什么这儿得不到正确的id.????????????
    //
    //######################################################
    此处读取的是资源的名称,而不是ID,
      

  7.   

    请问 yndfcd(YNDFCD): 如何得到资源id?您说的对,我发现我紧接着用方法:
    1。call FindResource or FindResourceEx with the resource name to get the resource handle; 
    2。call LoadResource with the resource handle to get the global handle; 
    3。call LockResource with the global handle to get a pointer to the resource data
    得到了数据,它是unicode格式,每一段前面都有一些0字符,如何知道它的结构?还有我发现它的lpName和真实的resource id似乎有关系。但这些数据里没有resource id, 为什么?请问各位大师:lpName由谁决定,是编译器吗?与resource id有关吗?
      

  8.   

    我有一个办法!很有用,我自己也是这么做的!
    并不要什么高深的PE格式!只需看看就会了!
    1:我们先用VC把DLL或EXE文件打开(以资源编辑的形式打开),并找出你要获取的资源的ID号,并记下!
    2:在你的代码中用LoadLibrary(DLL或EXE) 来获得句柄,然后再用LoadString, LoadCursor,LoadImage 等等的函数去得到你要的资源!
    这不是很简单吗?下面是我刚才做的例子:我要从test.exe中得到字符串资源。于是我用VC把test.exe打开,得到ID号是101和102两个。
    于在我的代码中将这样的取资源:
    #include "stdafx.h"
    #include <windows.h>
    #include <iostream.h>#define STR1 101
    #define STR2 102char *filename="test.exe";
    int _tmain(int argc, _TCHAR* argv[])
    {
    HMODULE m_h=::LoadLibrary(filename);
    char *pstr = new char[50];
    if (m_h!=NULL)
    {

    int m_size=LoadString((HINSTANCE)m_h,STR1,pstr,50);
    if( m_size>0 )
    {
    cout<<pstr<<endl;
    }
    else
    {
    cout<<"failed LoadString"<<endl;
    }
    }else
    {
    cout<<"LoadLibrary failed"<<endl;
    }
    return 0;
    }大家不妨去试一试!
      

  9.   

    资源"ID"是一个DWORD或者LPCSTR,如果最高位为1表明这是一个序号,把最高位的1去掉,再用LoadResource((LPCSTR)ID)就可以找到它;如果最高位是0,表明它是一个LPCSTR
      

  10.   

    你只要看一看资源的二进制格式的说明就知道了,资源的前面是一个入口,它由一个header和存放的数据组成。一个资源入口的内容如下:
       A DWORD that contains the size of the resource header 
       A DWORD that contains the size of the resource data 
       The resource type 
       The resource name 
       Additional resource information 
    由于LockResource将指针直接指向了Additional resource information所以得不到name和ID。可以直接读资源文件到得到ID。不过MSDN上没有介绍,可能要找一些非正式文档。
    参看MSDN:Win32 Resource File Formats
      

  11.   

    衷心祝愿各位帮我的人长命百岁! To jiagh(无会): 这种办法不是我想要的。我的问题是发现一些工具(包括VC)都可以读到resource id,而调用这些api则不行。DoItFreely(Freely),yndfcd(YNDFCD)说的有道理,我再去试试。等这个问题解决了,我一定写篇FAQ来报答各位的帮助!
      

  12.   

    函数
    EnumResourceLanguages / EnumResourceTypes / EnumResourceNames回调
    BOOL CALLBACK EnumResNameProc(
      HMODULE hModule,   // module handle
      LPCTSTR lpszType,  // resource type
      LPTSTR lpszName,   // resource name
      LONG_PTR lParam    // application-defined parameter
    );回调函数返回的 lpszName 有几种情况:
    1、(lpszName  & 0xFFFF0000) == 0 即 (UINT)lpszName < 65536 则
    Resource Id = (UINT)lpszName;2、否则,lpszName 指向一个 String , 如果 lpszName[0] == _T("#") 且 lpszName[1] 以后完全为数字,如 "#1024" ,则 
    Resource Id = _ttoi(&lpszName[1]); // "#1024" --> id = 10243、此时该资源没有 id ,仅有名称 lpszName