關於exe或dll檔案中的字串資源

2021-07-07 07:04:36 字數 2756 閱讀 6562

資源在windowsgui的程式中隨處可見,這也是微軟為了方便把介面和邏輯分開的優秀策略。所謂的資源就是一些用於描述介面或其他特徵的說明性字元,它們有固定的格式。這點與html有相似之處。而微軟提供了處理這些資源描述字元的函式,並上公升到win32api的高度。資源有兩種存在形式,一是編譯之前,此時的資源被存放到.rc檔案(此檔案為純文字檔案)中,在程式編譯的時候,資源編譯器rc.exe把.rc檔案編譯為.res二進位制檔案,然後鏈結器把.res檔案和.obj檔案鏈結在一起,並作為資源節存在於生成的.exe檔案中。

對於.rc檔案,相信很多程式設計師都很熟悉了,可以直接用文字編輯器編輯。為了視覺化設計,微軟和其他第三方軟體廠商還提供了視覺化編輯工具,稱之為資源編輯器。vs帶的資源編輯器,相信大家都不會陌生。

對於.res檔案或者是.exe檔案中的資源節的格式,大多數程式設計師就望而卻步了。詳細介紹.exe檔案結構的資料也不多,能夠說清楚資源節格式的資料就更少了。微軟提供了findresource(), loadresource(), lockresource(), updateresource()等函式供使用者檢視修改二進位制資源節裡的資源。但是具體的用法解釋的並不清楚,網上的例子也很少。但是這方便有做的功能很晚上的軟體,如exescope,不僅可以檢視二進位制資源,還可以修改之,可惜沒有公開源**。由於專案需要,這幾天一直找相關的例子,發現象dialog,icon等資源的處理有很多成功的例子,但是對於看似簡單的字串資源的處理卻幾乎無一成功的!!!就連老外也一樣!!!於是乎,瘋狂找資料,終於找到一位明白人寫的文章,還有源**,只是有兩點可惜:一是作者是老外,國內程式設計師不一定都喜歡英語;二是程式原始碼採用vb編寫,這讓c/c++的程式源很不舒服。於是乎,對這篇文章關於字串資源的處理的部分進行研究並重新用c/c++實現的想法湧上心頭。由於我對於vb也不是很熟悉,轉換語言的過程也不太順利,不過總算是成功轉成了c/c++。技術不敢獨享,願為大家獻上,不當之處還請見諒!

不想其他資源,字串是不能單獨處理的,像updateresource()等函式要求的最小處理單位是「串組」,這是由字串資源的存放方式決定的。每16個字串為乙個串組,字串的排序以字串的資源id號為依據,0-15為第一串組,16-31位第二串組,32-47位第三串組,...。串組id號從1開始,字串id號從0開始。由此可以得到如下公式:

串組id = (取整)(字串id/16) + 1

同一串組的字串是相鄰存放的,我們以7號串組為例說明。如下圖所示:

2      你好

5      你好abc

0  

1      你

中間省略

上圖列出了幾個代表的串,其中最開頭的串的id為96,乙個串有兩部分組成,前一部分佔2個位元組,用於描述本串的長度,以unicode字元為單位(也就是2個位元組),注意字串資源裡的字元都是採用unicode16位編碼的。後一部分是串的具體內容,注意沒有結尾標誌。從上圖可以看出,id號為96的串的長度為2個字元,內容為「你好」。下乙個串也就是id為97的串的長度為0,所以沒有內容;接著98號串長度為5,內容為「你好abc"(請注意,在unicode編碼方式下,所有字元都佔據2個位元組,英文本母也一樣)。最後乙個字串,也就是111號,長度為1,內容為「你」。

理解了字串資源的存放方式與處理單位,對於其處理方法也就不難了。基本思路是,首先根據字串的id號,找到所處的串組號,然後找到整個串組的內容,隨後定位到需要處理的串,修改其長度標示和內容。修改不會影響到前面的串,但卻會影響到後面的串,所以首先要把後面的所有串先備份,然後新增到修改後的串的尾部。

如上圖所示,需要修改的串顯示為紅色,串組以此串為分割點分成前後兩部分,這兩部分原樣複製,把需要修改的串修改後重新將其與前後兩部分銜接起來。

順著這個思路問題迎刃而解,具體**如下:

bool stringresourcemodify(cstring strre***epath, int id, cstring strnew, long langid)

} else //串組中有串非空,則修改

//至此,countx代表了本串之前的所有串所佔據的空間大小(位元組)

//讀出要修改串修改前的長度

::copymemory(&checklng, lpreaddata+countx, 2);

//至此,checklng代表修改前本串的長度

lpdata = new byte[countx+2+strnew.getlength()*2 + //從開頭到本串(修改後)結束的長度

( cbresource-(countx+2 + checklng*2)) ]; //從本串後乙個串開始到結束的總長度

::copymemory(lpdata, lpreaddata, countx); //讀入開頭到本串前乙個串結束

cbtext = strnew.getlength();

::copymemory(lpdata+countx, &cbtext, 2);  //寫入修改後串長度

if(cbtext)

if( (cbresource - (countx+2+checklng*2)) >0 )     //修改前,本串後面還有串

} ::freelibrary(hmodule);

hresource = beginupdateresource(strre***epath, false);

ret = updateresource(hresource, rt_string, makeintresource(igroup),

langid, lpdata, lenofdata);

ret = ::endupdateresource(hresource, false);

return ret; }

C 將引用的dll嵌入到exe檔案中

通過網上查詢,將引用的dll,嵌入到exe專案中,通過編譯為單一的exe檔案。1.引用dll,將引用的dll設定為不複製 是否複製不影響使用,編譯完成後,只需要exe就可以了,旁邊的dll是否存在並不影響使用 2.將引用的dll嵌入到專案中。新建乙個專案資料夾,將引用的dll複製到此資料夾中,幷包含...

LoadImage在dll與exe中的區別

hbitmap hbitmapnormal null hinstance hinstresource null find correct resource handle hinstresource afxfindresourcehandle makeintresource nbitmapnormal...

EXE中釋放DLL中分配的記憶體

在dll中分配的記憶體,如果到其呼叫者中釋放,可能會出現crash的情況,其原因在於 在dll中的code generation如果是採用了mt 靜態載入libcrtd.lib 在該庫中維護了乙個allocator的物件對記憶體分配進行管理,當exe中呼叫free等函式對記憶體進行釋放時,他自己也維...