999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

一種暫時關閉Windows彈窗函數(shù)程序的設計實現(xiàn)

2019-04-08 09:06:04張晶瑜陳僴璀
科教導刊·電子版 2019年2期
關鍵詞:程序

張晶瑜 陳僴璀

摘 要 本文介紹了一種在程序運行過程當中,暫時關閉Windows 系統(tǒng)中MessageBox()彈窗函數(shù)的方法。該方法能夠處理程序運行過程中Windows彈窗函數(shù)彈出過多導致的程序運行效率低下問題,進而實現(xiàn)程序運行過程中的無人值守。

關鍵詞 MessageBox 彈窗函數(shù) 程序

中圖分類號:TP311 文獻標識碼:A

0引言

MessageBox()消息框函數(shù)是指user32.dll中MessageBox() API提供的彈出消息提示框,其作用主要為顯示文本消息。某些程度上,MessageBox()函數(shù)還明確了程序運行的步驟,促進了使用者對程序本身的了解,也使得使用者與程序開發(fā)者之間的交流變得更加順暢。然而,MessageBox()函數(shù)的使用,有時也會給程序的運行效率帶來一些影響。

1研究背景和意義

計算機用戶經(jīng)常使用的應用軟件(如辦公軟件、行業(yè)專用軟件)通常是軟件開發(fā)商針對某一類用戶的普遍需求所設計。如遇用戶有一些特殊需求,應用軟件不能很好滿足時,用戶自己通常會在原有軟件基礎上進行二次開發(fā)。為了便于用戶進行二次開發(fā),部分應用會軟件設計一些API接口,供二次開發(fā)用戶調(diào)用。在二次開發(fā)過程中,往往會遇到MessageBox API所帶來的一些負面影響。

舉例如下,假設有一個運行于Windows系統(tǒng)中的應用軟件APP 1.0,開發(fā)商為其設計了一個API,可供用戶使用。API所屬模塊DLL文件為“C:\APP 1.0\abcapi.dll”,API對應函數(shù)名稱為Function,該API的主要功能是對指定文件進行特定操作(如讀取文件內(nèi)容、修改文件內(nèi)容)。該API聲明如下:

void Function(lpsz path);

其中path代表需要處理文件的完整路徑。

而用戶在進行二次開發(fā)時,所寫程序(用戶軟件)需要調(diào)用Function函數(shù)對一系列文件進行逐個處理。當用戶軟件使用者點擊了“開始工作”按鈕之后,在處理到第i個文件時,F(xiàn)unction函數(shù)遇到了異常,會調(diào)用MessageBox()彈出一個模態(tài)對話框,對此異常情況進行提示。此時,使用者必須點擊彈出對話框的“確定”按鈕之后,整個程序才能繼續(xù)工作,程序才能繼續(xù)處理第i+1個文件。當異常情況很多時,程序運行效率就會很低,而且這樣無法實現(xiàn)程序的無人值守運行。Function函數(shù)的具體代碼是由APP 1.0的開發(fā)商提供,無論從技術層面還是法律層面上說,要想通過修改其編譯后的程序代碼達到消除彈窗的目的都不是明智之舉。

因此,在用戶軟件開發(fā)過程中,需要找到一種方法,實現(xiàn)在程序運行過程中,暫時關閉MessageBox()的功能。

本文針對以上問題,提出了一種暫時關閉MessageBox()彈出對話框的方法,本文所述代碼示例均采用C++ .net所寫。

2研究方法

通過需求分析可知,進行二次開發(fā)時,可以在自己開發(fā)程序的進程中找到MessageBox()函數(shù)的代碼,并對其進行修改。這樣的優(yōu)點在于只會影響與MessageBox()函數(shù)相關的這1個進程,不會影響其他程序,而且需要時也可以恢復。

首先要做的是,找到MessageBox()的地址。在user32.dll中,大部分API都有2個版本,對應Ansi和Unicode字符集。MessageBox()也是如此,這2個版本分別是MessageBoxA和MessageBoxW。用kernel32.dll中的GetProcAddress API可以獲取到MessageBox()的地址。它的聲明如下:

[DllImport("kernel32.dll", CharSet = CharSet::Ansi)]

static IntPtr GetProcAddress(IntPtr hModule, String^ procName);

其中,hModule是目標dll文件的指針,這里就是user32.dll的指針。

在我們獲取地址之后,需要先讀取地址處的代碼信息,將其保存起來,以便日后恢復。如果不打算恢復也可直接省略這一步。之后,把修改過的指令寫入之前獲取的地址當中,這樣,就實現(xiàn)了MessageBox()的暫時關閉功能。代碼的讀、寫分別采用kernel32.dll中的ReadProcessMemory和WriteProcessMemory API。它們聲明如下:

[DllImport("kernel32.dll", CharSet = CharSet::Auto)]

static bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, array^ lpBuffer, int nSize, int% lpNumberOfBytesRead);

[DllImport("kernel32.dll", CharSet = CharSet::Auto)]

static bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, array^ lpBuffer, int nSize, int% lpNumberOfBytesWritten);

讀取MessageBox()指令的具體代碼如下:

IntPtr thisProc; //本進程的Handle

IntPtr hModule; //user32.dll的handle

IntPtr baseAddrA, baseAddrW; //MessageBox()方法的handle

int readOrWrite; //讀寫字節(jié)數(shù)

thisProc = Diagnostics::Process::GetCurrentProcess()->Handle;

ProcessModuleCollection^ modules = Process::GetCurrentProcess()->Modules;

for each(ProcessModule^ m in modules){

if(m->ModuleName->ToLower() == "user32.dll"){

hModule = m->BaseAddress;

}

}

baseAddrA = GetProcAddress(hModule, "MessageBoxA" );

baseAddrW = GetProcAddress(hModule, "MessageBoxW" );

ReadProcessMemory(thisProc, baseAddrA, CodeMBA, 32, readOrWrite);

ReadProcessMemory(thisProc, baseAddrW, CodeMBW, 32, readOrWrite);

上述代碼中CodeMBA與CodeMBW是事先聲明過的全局Byte類型數(shù)組。

讀取到MessageBox()代碼后,繼續(xù)研究如何更改代碼。下面以在Windows 7中讀取到的MessageBoxA()代碼為例,將其轉換為匯編語言后,代碼如下:

8B FF - mov edi,edi

55 - push ebp

8B EC - mov ebp,esp

6A 00 - push 00 { 0 }

FF 75 14 - push [ebp+14]

FF 75 10 - push [ebp+10]

FF 75 0C - push [ebp+0C]

FF 75 08 - push [ebp+08]

E8 A0FFFFFF - call USER32.MessageBoxExA

5D - pop ebp

C2 1000 - ret 0010 { 16 }

90 - nop

90 - nop

90 - nop

90 - nop

90 - nop

Win32 API采用的調(diào)用約定為stdcall。此種調(diào)用約定中,參數(shù)按照右至左的順序,返回值存放在EAX寄存器中,函數(shù)返回時,由被調(diào)用函數(shù)負責清理堆棧。

通過對MessageBoxA()匯編代碼的分析,我們不難發(fā)現(xiàn),其最后一條有效指令為ret 0010{16}。這是一條返回指令,完成了堆棧清理的工作,其等效于以下2條指令:

POP EIP

ADD ESP,0X10

運行該指令除了會改變EIP寄存器外,還會使得 ESP = ESP+0X10,也就是堆棧指針向棧頂移動16個字節(jié)。

我們可以把這一條指令直接放到MessagBoxA代碼的最開始,這樣,程序運行到MessagBoxA方法時,會直接返回調(diào)用它的上一級代碼,于是,模態(tài)對話框就不會再彈出了。

將更改后指令替換掉原有MessageBox()指令的具體代碼如下:

array^ codeNull = gcnew array(32){0xC2, 0x10, 0x00};

WriteProcessMemory(thisProc, baseAddrA, codeNull, 3, readOrWrite);

WriteProcessMemory(thisProc, baseAddrW, codeNull, 3, readOrWrite);

其中{0xC2, 0x10, 0x00}這3個字節(jié)的來自于MessageBoxA()的最后一條指令:

C2 1000 - ret 0010 { 16 }

3結論

通過以上方法實現(xiàn)了在程序運行過程當中,暫時關閉Windows 系統(tǒng)中MessageBox()彈窗函數(shù)的功能。從某種程度上解決了程序運行效率低下的問題,進而實現(xiàn)了程序運行過程中的無人值守。

參考文獻

[1] 李海雁.一個更為靈活的MessageBox()函數(shù)[J].電腦編程技巧與維護,1996(01):34-35+38.

猜你喜歡
程序
給Windows添加程序快速切換欄
電腦愛好者(2020年6期)2020-05-26 09:27:33
試論我國未決羈押程序的立法完善
人大建設(2019年12期)2019-05-21 02:55:44
失能的信仰——走向衰亡的民事訴訟程序
“程序猿”的生活什么樣
英國與歐盟正式啟動“離婚”程序程序
基于VMM的程序行為異常檢測
偵查實驗批準程序初探
我國刑事速裁程序的構建
創(chuàng)衛(wèi)暗訪程序有待改進
恐怖犯罪刑事訴訟程序的完善
主站蜘蛛池模板: 久久综合伊人 六十路| 国产高潮流白浆视频| 国产第一页免费浮力影院| 精品超清无码视频在线观看| 国产精品福利在线观看无码卡| 亚洲天堂视频在线观看| 国产精品蜜臀| 国产乱人乱偷精品视频a人人澡| 国产啪在线91| 中文字幕在线一区二区在线| 四虎永久在线精品国产免费 | 亚洲欧美成人在线视频| 欧美三级自拍| 丰满人妻一区二区三区视频| 狠狠五月天中文字幕| 99久视频| 国产经典免费播放视频| 凹凸国产分类在线观看| 久久窝窝国产精品午夜看片| 无码日韩人妻精品久久蜜桃| 亚洲天堂日韩在线| 欧美亚洲一区二区三区导航| 亚亚洲乱码一二三四区| 欧美成人在线免费| 亚洲男人天堂2018| 欧美亚洲国产一区| 亚洲天堂视频在线观看免费| 国产大片喷水在线在线视频| 黄色不卡视频| 九九精品在线观看| 无码久看视频| 亚洲精品无码AⅤ片青青在线观看| 尤物精品视频一区二区三区| 国产成人高清在线精品| 激情综合五月网| 国产成人高清在线精品| 国产日韩欧美精品区性色| 久久精品亚洲热综合一区二区| 午夜三级在线| 伊人久久精品无码麻豆精品| 久久精品女人天堂aaa| 婷婷99视频精品全部在线观看| 夜夜操天天摸| 人人看人人鲁狠狠高清| 狂欢视频在线观看不卡| 欧美在线精品怡红院| 亚洲一区色| 亚洲一区二区精品无码久久久| 色综合中文| 丁香婷婷综合激情| 亚洲色图欧美一区| 男女男免费视频网站国产| 免费看a毛片| 国产成人久久777777| 天天综合网色中文字幕| 老司机午夜精品网站在线观看| 国产黄在线免费观看| 国产乱人伦偷精品视频AAA| 亚洲色欲色欲www网| 99尹人香蕉国产免费天天拍| 无码人妻免费| 国产精品2| 成年人国产视频| 国产综合另类小说色区色噜噜| 69av免费视频| 欧美成人一级| 久久人体视频| 久久综合色天堂av| 国产一级二级在线观看| 亚洲精品黄| 成人免费午间影院在线观看| 四虎亚洲国产成人久久精品| 国产丝袜无码精品| 欧美日韩精品综合在线一区| 亚洲无码视频喷水| 亚洲欧美不卡| 久久毛片网| 国产精品免费福利久久播放| 成人午夜久久| 色久综合在线| 亚洲无码熟妇人妻AV在线| 亚洲第一香蕉视频|