今天有個小需求, 程序要求執行一個檢測操做, 若是檢測失敗的話則彈出信息而且關閉程序html
因爲檢測代碼是封裝到一個獨立進程裏的, 因此直接使用TerminateProcess(GetCurrentProcess, 0);來關閉當前進程java
但是在測試時卻發現, 本來使用MessageBox來彈出消息卻會阻塞結束進程的操做git
通常咱們在系統裏彈出對話框都是調用Windows.MessageBox, 這個方法在通常狀況下, 能夠不阻塞本程序的操做(雖然在代碼層面仍然是阻塞的)github
你們能夠用一個小例子試試api
procedure TForm1.Button1Click(Sender: TObject); begin MessageBox(0, '測試內容1', '測試標題', MB_OK); MessageBox(0, '測試內容2', '測試標題', MB_OK); end;
實際狀況執行之後, 點擊按鈕彈出第一個對話框, 這時, 雖然程序界面仍然能夠移動輸入等執行其餘操做, 可是測試內容2卻沒有彈出session
只有吧第一個對話框關閉之後, 第2個對話框才能彈出來函數
因此, 猜想MessageBox的非阻塞只是在內部處理了對當前進程的消息循環, 可是代碼層面並無返回並向後執行, 因此並非真正意義上的非阻塞測試
那需求怎麼辦呢.......spa
偉大的Google, 碼農們須要你的時候來了(雖然這幾天Google又被偉大的GFW給牆了...不過我們能夠換IP...嘿嘿 你懂的: 啦啦啦)code
終於搜到一個相關的文章, 關於在win7下若是讓一個服務向用戶界面推送消息的問題: 穿透Session0隔離
其中有一個關鍵性函數: WTSSendMessage, 能夠向指定的Session發送消息
既然是想Session發送消息, 那確定是桌面級的, 和應用程序無關了唄, 我們再看看他的定義: WTSSendMessage function
顯然, 最後一個參數是控制是否阻塞等待的, 看來這就是我要的東西了, 立刻寫代碼試試:
補充一下, 不知道爲何 這個自從XP就出現的函數, 直到Delphi XE5都沒有被定義到Windows單元中, 而其餘的2個WTS相關函數卻定義了(也許定義到其餘單元我沒找到?)
const WTS_CURRENT_SERVER_HANDLE = 0; function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar; TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD; Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSSendMessageA'; function WTSGetActiveConsoleSessionId: DWORD; stdcall; external kernel32 name 'WTSGetActiveConsoleSessionId'; procedure TForm1.Button1Click(Sender: TObject); var nTitle, nMessage: string; nResponse: DWORD; begin nTitle := '測試標題'; nMessage := '測試內容1'; WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId, PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage), MB_OK, 0, nResponse, False); nMessage := '測試內容2'; WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId, PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage), MB_OK, 0, nResponse, False); end;
執行測試一下, 我擦....竟然仍是必須先吧內容1肯定了之後才能彈出內容2? 難道是我理解錯了不成?
單步跟蹤一下...#^&%^*
不對啊, 彈出了內容1立刻就執行到內容2的代碼了啊, 而後就直接end結束了, 但是爲何只彈出了1個對話框呢?
再補充一下測試
const WTS_CURRENT_SERVER_HANDLE = 0; function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar; TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD; Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSSendMessageA'; function WTSGetActiveConsoleSessionId: DWORD; stdcall; external kernel32 name 'WTSGetActiveConsoleSessionId'; procedure TForm1.Button1Click(Sender: TObject); var nTitle, nMessage: string; nResponse: DWORD; begin nTitle := '測試標題'; nMessage := '測試內容1'; WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId, PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage), MB_OK, 0, nResponse, False); nMessage := '測試內容2'; WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId, PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage), MB_OK, 0, nResponse, False); TerminateProcess(GetCurrentProcess, 0); end;
看看這樣, 執行結果, 果真 程序關閉了, 可是隻有內容1的對話框, 肯定之後才彈出內容2的
我的猜想, 應該是WTSSendMessage以相似消息隊列方式給Session發對話框消息, 而對於Session的處理, 則必須是阻塞的, 估計是爲了可以讓用戶知道多條消息的前後順序吧
無所謂啦, 只要程序不阻塞就行, 搞定....嘿嘿嘿嘿.......
http://www.cnblogs.com/hs-kill/p/3797103.html