最近有人問我下面這個問題,我們依然可以使用之前我提到的 “思維調試” 來研究研究。
我們碰到了一個技術問題。當在資源管理器中雙擊打開文檔時,資源管理器不會啟動我們的應用程序。
更加奇怪的是,如果我們將一個調試器掛接到資源管理器進程,并在 kernel32 模塊的 CreateProcessW 處下斷點,然后等待 CreateProcess 返回,并在調試器中繼續執行,則文檔可以正常打開。但是,如果我們不做任何等待,應用程序也可以正常打開,但是它不會加載文檔,在這種情況下,我們得到了這樣的錯誤信息:windows 找不到 ‘abc.lit’。請確保你輸入了正確的文檔名稱,然后重試。
下面是我們使用的命令行:
“F:Program FilesLitSoftLitWareLitWare.exe” /dde
到底是哪里出了問題呢?
如果你仔細研究過 DDE 初始化的工作原理文章,那么我想你應該已經知道原因了。
回想一下,通過 DDE 打開文檔是通過首先查找 DDE 服務器來完成的,如果未找到,則手動啟動服務器并重試。上面的命令行顯然已注冊為與 ddeexec 關聯的命令。
我們有兩個線索:首先是文檔名稱本身在命令行上不存在。(這不可能是直接執行,因為程序不知道它應該打開什么文檔!但是這條線索是命令行上的短語 /dde。
顯然,資源管理器嘗試第二個 DDE 對話打開文檔時出現問題。讓資源管理器等待幾秒鐘可以解決問題的事實使原因顯而易見:DDE 服務器初始化和偵聽自身的速度很慢。資源管理器啟動服務器并嘗試與其通信,但服務器尚未準備就緒,因此不響應 DDE 啟動。
如何解決這個問題?
外殼程序假定 DDE 服務器在輸入空閑時已準備好接受連接。一旦 DDE 服務器上的 WAItForInputIdle 返回,資源管理器將第二次嘗試啟動 DDE 會話。此修復程序是讓應用程序在開始處理消息之前啟動并運行其 DDE 服務器。
我的猜測是應用程序將其 DDE 服務器移動到后臺線程以提高啟動性能,因為 DDE 服務器不參與正常的程序操作。
但是這太糟糕了,當傳遞 /dde 標志時,程序忘記在輸入空閑之前啟動并運行 DDE 服務器。讓 DDE 服務器運行很重要,但它錯過了正確的時間點。
總結
如果你要實現了一個 DDE 服務器,請確保在主線程開始處理消息之前就啟動它。否則,應用程序啟動和嘗試與之通信的外殼之間存在競爭條件。
最后
Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,里面有很多關于Windows的小知識,對于廣大Windows平臺開發者來說,確實十分有幫助。
本文來自:《Psychic debugging: Understanding DDE initiation》