Visual c++ 为什么在资源管理器中打开与应用程序关联的文件时会出现DDE错误?

Visual c++ 为什么在资源管理器中打开与应用程序关联的文件时会出现DDE错误?,visual-c++,mfc,windows-explorer,dde,Visual C++,Mfc,Windows Explorer,Dde,我们的传统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_L

我们的传统
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\")]" Windows注册表编辑器5.00版 [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document] @=“应用程序文件” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\DefaultIcon] @=“d:\\ProgramFiles(x86)\\MyApp\\version\\app.exe,1” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell] [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\open] [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\open\command] @=“C:\\Program Files\\App\\App.exe\”/dde” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\open\DDExec] @=“[打开(\%1\”)” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\print] [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\print\command] @=“C:\\Program Files\\App\\App.exe/dde” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\print\DDExec] @=“[打印(\%1\”)” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\printto] [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\printto\command] @=“C:\\Program Files\\App\\App.exe/dde” [HKEY\U LOCAL\U MACHINE\SOFTWARE\Classes\App.Document\shell\printto\ddeexec] @=“[打印到(\%1\,\%2\,\%3\,\%4\”)” 为了清楚起见,我刚从注册表中取出了这些条目。我不太了解它们是做什么的,但我可以冒昧地猜测,它们通过语法把动词和动作联系起来

请注意,如果应用程序已经启动,则文档在该实例中可以正常打开。只有当应用程序尚未启动且必须执行应用程序的新实例时,才会出现此问题。

因此,所发生的事情是,通过双击资源管理器打开关联的文件,并执行关联的应用程序。浏览器将弹出该消息,而我们的应用程序将什么也不做。再次双击该文件将打开该文档

我们以前也遇到过这个问题,但我们只是决定忽略它几年,因为没有人真正知道它是什么,我们当时还有其他优先事项。我们的解决方法是告诉用户将
/dde
更改为
“%1”
。是的,很差劲,但效果很好。但这样做的一个问题是,它将执行应用程序的新实例,而不管应用程序是否已经在运行

无论如何,这个问题现在开始成为一个实际问题,需要解决。我们的一位开发人员说DDE系统已经过时,我们应该尝试编写一个COM组件,像Visual Studio那样重定向到我们的应用程序,因为调试这个问题可能需要一段时间。我还没有证实这一点,也没有研究这需要付出多少努力。然而,无论是在调试还是在研究方面,两者都可能是资源密集型的,所以我正在尝试做一些初步研究,看看我能挖掘出什么,并确定哪种方法更好

在代码中,我能够确定它将进入一个
::SetWindowPlacement()
调用,并单步执行,这将导致弹出错误消息框(如果资源管理器没有首先超时)。由于它是一个WINAPI,我无法进入该函数查看它在做什么

该应用程序主要使用MFC/API和其他库在VC/VC++中编写

所以我的问题是,有人知道为什么会发生这种情况,以及如何解决它吗

编辑 一些补充资料:

我能够以非破坏性方式截获所有
SendMessage()
/
PostMessage()
/
DispatchMessage()
函数调用,该函数将记录所有消息。这是通过使用MS Detours 3.0实现的

我看到的是,有4个
SendMessage
调用带有
WM\u COPYDATA
消息,该消息似乎来自
shell32.dll
。然而,似乎并不是这些信息出了问题

当检测到
WM\u COPYDATA
消息时,放置
\u debugbreak()
不会导致错误,直到执行几步之后。多远取决于我是单步执行还是设置断点并将代码运行到我认为会出现错误的地方。使用
DebugBreak()

我无法理解的是,似乎没有任何押韵或理由来说明是什么触发了错误消息的弹出。我似乎没有超时,因为在我开始输入代码之前,超时似乎很长,有时代码没有发送/发布消息。因此,不会有
WM\u DDE\u ACK
(或任何与此相关的消息)被发送回启动此操作的资源管理器窗口。这是非常令人沮丧的

更复杂的是,如果我使用内在的
\uu debugbreak()
调用,并且代码中的其他地方有一个断点,它有时会在该断点处停止,而不是在
\uu debugbreak()
处停止。有时,当我控制调试器后立即运行代码时,有时会导致第二次中断,就像它碰到另一个
\uu debugbreak()
。这是怎么回事?不一致的调试无疑使此问题更加难以追踪。>:(

  • MDI接口仍然使用这种DDE功能。因此,如果一个EXE打开不同的文件
  • 如果您可以多次启动应用程序,并且这是可以的,那么对于客户来说,将注册表中的条目从SDI切换到普通的占位符也是可以的