• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

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

      2019-04-08 09:06:04張晶瑜陳僴璀
      科教導(dǎo)刊·電子版 2019年2期
      關(guān)鍵詞:程序

      張晶瑜 陳僴璀

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

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

      中圖分類號:TP311 文獻(xiàn)標(biāo)識(shí)碼:A

      0引言

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

      1研究背景和意義

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

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

      void Function(lpsz path);

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

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

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

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

      2研究方法

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

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

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

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

      其中,hModule是目標(biāo)dll文件的指針,這里就是user32.dll的指針。

      在我們獲取地址之后,需要先讀取地址處的代碼信息,將其保存起來,以便日后恢復(fù)。如果不打算恢復(fù)也可直接省略這一步。之后,把修改過的指令寫入之前獲取的地址當(dāng)中,這樣,就實(shí)現(xiàn)了MessageBox()的暫時(shí)關(guān)閉功能。代碼的讀、寫分別采用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; //本進(jìn)程的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()代碼為例,將其轉(zhuǎn)換為匯編語言后,代碼如下:

      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ù)返回時(shí),由被調(diào)用函數(shù)負(fù)責(zé)清理堆棧。

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

      POP EIP

      ADD ESP,0X10

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

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

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

      C2 1000 - ret 0010 { 16 }

      3結(jié)論

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

      參考文獻(xiàn)

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

      猜你喜歡
      程序
      給Windows添加程序快速切換欄
      電腦愛好者(2020年6期)2020-05-26 09:27:33
      試論我國未決羈押程序的立法完善
      失能的信仰——走向衰亡的民事訴訟程序
      “程序猿”的生活什么樣
      英國與歐盟正式啟動(dòng)“離婚”程序程序
      基于VMM的程序行為異常檢測
      偵查實(shí)驗(yàn)批準(zhǔn)程序初探
      我國刑事速裁程序的構(gòu)建
      淺析德國刑事訴訟程序之調(diào)查程序
      人間(2015年23期)2016-01-04 12:47:46
      創(chuàng)衛(wèi)暗訪程序有待改進(jìn)
      梓潼县| 东山县| 乐清市| 蓬安县| 宜昌市| 阳江市| 大厂| 临清市| 都昌县| 长沙市| 定兴县| 乌兰察布市| 乌拉特后旗| 东方市| 天气| 寻乌县| 盐津县| 清丰县| 凤冈县| 龙南县| 安康市| 武威市| 特克斯县| 高雄市| 抚宁县| 普宁市| 长汀县| 依安县| 寻甸| 叶城县| 错那县| 阳东县| 江孜县| 和硕县| 朔州市| 湖北省| 板桥市| 鹤峰县| 乃东县| 龙泉市| 临泽县|