簡體   English   中英

在資源管理器中打開與我們的應用程序關聯的文件時,為什么會出現DDE錯誤?

[英]Why am I getting a DDE error when opening a file in Explorer that associated with our application?

我們的舊版MDI桌面應用程序在關聯中使用/dde開關。 當打開與之關聯的文件且應用程序尚未啟動時,資源管理器彈出以下錯誤:

There was a problem sending the command to the program.

注冊表看起來像這樣:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document]
@="App File"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\DefaultIcon]
@="d:\\Program Files (x86)\\MyApp\\version\\app.exe,1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell]

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\open]

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\open\command]
@="\"C:\\Program Files\\App\\app.exe\" /dde"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\open\ddeexec]
@="[open(\"%1\")]"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\print]

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\print\command]
@="C:\\Program Files\\App\\app.exe /dde"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\print\ddeexec]
@="[print(\"%1\")]"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\printto]

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\printto\command]
@="C:\\Program Files\\App\\app.exe /dde"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\App.Document\shell\printto\ddeexec]
@="[printto(\"%1\",\"%2\",\"%3\",\"%4\")]"

為了清楚起見,我只是從注冊表中獲取了這些條目。 我對它們的操作並不精通,但我可能會猜測它們是通過DDE接口將動詞鏈接到動作的。

請注意,如果應用程序已經啟動,則在該情況下可以正常打開文檔。 僅當應用程序尚未啟動並且必須執行該應用程序的新實例時,這才是問題。

因此,正在發生的事情是通過雙擊資源管理器打開關聯文件,並執行了關聯的應用程序。 然后,資源管理器將彈出該消息,而我們的應用程序將不執行任何操作。 再次雙擊該文件將打開文檔。

以前我們曾遇到過這個問題,但是由於沒有人真正知道這是什么,並且當時還有其他優先事項,我們只是決定忽略它幾年。 我們的解決方法是告訴用戶將/dde更改為"%1" 是的,la腳,但是效果很好。 但是,這樣做的一個問題是,它將執行該應用程序的新實例,而不管該應用程序是否已在運行。

無論如何,此問題現在已開始成為實際問題,需要解決。 我們的一位開發人員說DDE系統過時了,我們應該嘗試編寫一個將像Visual Studio一樣重定向到我們的應用程序的COM組件,因為調試此問題可能需要一段時間。 我還沒有證實這一點,也沒有研究將要付出多少努力。 但是,無論是在調試方面還是在研究方面,這可能都是資源密集型的,因此,我正在嘗試進行一些初步研究,以期找出可以挖掘的內容並確定哪種方法更好。

進入代碼,我能夠確定它到達了::SetWindowPlacement()調用,然后越過該步驟將導致彈出錯誤消息框(如果資源管理器沒有先超時)。 由於它是WINAPI,因此無法進入該功能以查看其功能。

該應用程序主要使用MFC / API和其他庫以VC / VC ++編寫。

所以我的問題是,有誰知道為什么會這樣以及如何解決?

編輯

一些其他信息:

我能夠無損地攔截所有SendMessage() / PostMessage() / DispatchMessage()函數調用,這將記錄所有消息。 這是通過使用MS Detours 3.0實現的。

我看到的是,有4個帶有WM_COPYDATA消息的SendMessage調用,該消息似乎是從shell32.dll發出的。 但是,這似乎不是錯誤消息。

在檢測到WM_COPYDATA消息時__debugbreak()不會導致錯誤,除非經過幾步。 距離取決於我是走一步還是放置斷點並將代碼運行到超出我認為出錯的地方。 使用DebugBreak()似乎將調試器的速度減慢到無法顯示錯誤的程度。

我不明白的是,對於觸發錯誤消息彈出的原因似乎沒有任何押韻或原因。 我似乎沒有超時,因為超時似乎很長,直到我開始介入代碼為止,有時代碼沒有發送/發布消息。 因此,不會將WM_DDE_ACK (或與此有關的任何消息)發送回啟動此操作的資源管理器窗口。 這非常令人沮喪。

更復雜的是,如果我使用固有的__debugbreak()調用,並且在代碼中的其他地方有一個斷點,則它有時可以在該斷點處停止,而不是在__debugbreak()處停止。 有時,當我獲得調試器的控制權后立即運行代碼時,有時會導致第二次中斷,就好像擊中了另一個__debugbreak() 那是什么意思 不一致的調試無疑會使此問題更加難以追查。 > :(

  1. 此DDE內容仍用於MDI接口。 因此,如果一個EXE打開不同的文件。
  2. 如果可以多次啟動應用程序,並且可以,對於客戶來說,將注冊表中的條目從SDI切換到普通占位符也可以。
  3. 如果EXE在特定時間內沒有准備好接受DDE命令,通常會從資源管理器顯示此消息。

因此,對您來說主要的問題是:應用程序中發生了什么更改或更改太慢,以致於DDE消息沒有被檢索到。

如果情況真的很長,直到消息循環開始,這是可能的。 DDE支持需要主窗口運行的消息循環。

SetWindowPos本身不是問題,但是可能導致數百條消息(WM_SIZE,...)被觸發到您的應用程序,這里應用程序中的每個處理程序都可能是問題。

只需在SetWindowPos前面的應用程序中放置一個小計時器,然后檢查返回需要多長時間...

檢查應用程序花費的時間,直到使用TRUE退出InitInstance為止。 在InitInstance退出后,CWinApp :: Run啟動,並且消息循環開始。

我遇到了同樣的問題。

我的解決方案是在應用程序啟動時在注冊表中添加../ddeexec/*部分,然后在應用程序退出時將其刪除。

這不是一個很好的解決方案,但是很容易做到,並且有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM