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

一種暫時關閉Windows彈窗函數程序的設計實現

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

張晶瑜 陳僴璀

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

關鍵詞 MessageBox 彈窗函數 程序

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

0引言

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

1研究背景和意義

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

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

void Function(lpsz path);

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

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

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

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

2研究方法

通過需求分析可知,進行二次開發時,可以在自己開發程序的進程中找到MessageBox()函數的代碼,并對其進行修改。這樣的優點在于只會影響與MessageBox()函數相關的這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的指針。

在我們獲取地址之后,需要先讀取地址處的代碼信息,將其保存起來,以便日后恢復。如果不打算恢復也可直接省略這一步。之后,把修改過的指令寫入之前獲取的地址當中,這樣,就實現了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; //讀寫字節數

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類型數組。

讀取到MessageBox()代碼后,繼續研究如何更改代碼。下面以在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采用的調用約定為stdcall。此種調用約定中,參數按照右至左的順序,返回值存放在EAX寄存器中,函數返回時,由被調用函數負責清理堆棧。

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

POP EIP

ADD ESP,0X10

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

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

將更改后指令替換掉原有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個字節的來自于MessageBoxA()的最后一條指令:

C2 1000 - ret 0010 { 16 }

3結論

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

參考文獻

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

猜你喜歡
程序
給Windows添加程序快速切換欄
電腦愛好者(2020年6期)2020-05-26 09:27:33
試論我國未決羈押程序的立法完善
人大建設(2019年12期)2019-05-21 02:55:44
失能的信仰——走向衰亡的民事訴訟程序
“程序猿”的生活什么樣
英國與歐盟正式啟動“離婚”程序程序
環球時報(2017-03-30)2017-03-30 06:44:45
基于VMM的程序行為異常檢測
偵查實驗批準程序初探
我國刑事速裁程序的構建
創衛暗訪程序有待改進
中國衛生(2015年3期)2015-11-19 02:53:32
恐怖犯罪刑事訴訟程序的完善
主站蜘蛛池模板: 免费国产小视频在线观看| 99精品久久精品| 久久美女精品国产精品亚洲| 欧美 国产 人人视频| 亚洲欧美h| 亚洲日韩AV无码一区二区三区人| 日韩成人在线视频| 欧美一区二区自偷自拍视频| 久久无码免费束人妻| 久久毛片基地| 国产成人福利在线| 久久精品人妻中文视频| 亚洲综合专区| 永久免费精品视频| 毛片国产精品完整版| 欧类av怡春院| 国产一级裸网站| 波多野结衣一区二区三区四区视频 | 日韩无码真实干出血视频| 欧美综合成人| 日韩专区欧美| 免费一级全黄少妇性色生活片| 亚洲成肉网| 香蕉伊思人视频| 国产精品自在在线午夜区app| 国产欧美精品一区aⅴ影院| 日本亚洲欧美在线| 久久精品aⅴ无码中文字幕| 亚洲区一区| 亚洲精品无码不卡在线播放| 最新加勒比隔壁人妻| 国产精品无码翘臀在线看纯欲| 中文字幕在线不卡视频| 99国产在线视频| 成人午夜天| 欧美亚洲第一页| 国产精品一区二区不卡的视频| 国产亚洲欧美在线人成aaaa| 人人爱天天做夜夜爽| 夜夜操国产| 国产精品内射视频| 成人在线观看不卡| 精品无码人妻一区二区| 国产精品亚欧美一区二区| 久久久久亚洲av成人网人人软件| 性网站在线观看| 欧美成人二区| 欧洲熟妇精品视频| 国产成人亚洲精品蜜芽影院| 国产成人亚洲综合a∨婷婷| 精品国产一区91在线| 亚洲欧洲一区二区三区| 国产亚洲欧美在线专区| 无码aaa视频| 亚洲成a人片在线观看88| 亚洲va视频| 亚洲高清无码精品| 成人一区在线| 亚洲一级无毛片无码在线免费视频| 国产成人亚洲毛片| 欧美a在线看| 又黄又湿又爽的视频| 国产精品美女自慰喷水| 手机看片1024久久精品你懂的| 久久综合丝袜长腿丝袜| 香蕉蕉亚亚洲aav综合| 在线a网站| 亚洲伊人天堂| 免费在线不卡视频| 成人国产小视频| 亚洲婷婷丁香| 日本道中文字幕久久一区| 色AV色 综合网站| 国产剧情无码视频在线观看| 亚洲一区二区三区中文字幕5566| 成人日韩精品| 强奷白丝美女在线观看| 九九热视频在线免费观看| 欧美无专区| 在线免费a视频| 午夜视频免费试看| 精品视频福利|