jjzjj

c++ - 有谁知道免注册 COM 和拖放功能之间可能存在哪种关系?

coder 2024-02-05 原文

有谁知道免注册 COM 和拖放功能之间可能存在哪种关系?

具体来说,我们有一个庞大的 C++ CAD/CAM 应用程序,其中包含大量 EXE 和数百个 DLL。其中许多充当 COM 服务器(进程内和进程外)和/或客户端,并且还实现 ActiveX 控件。

大多数 ActiveX 控件和其中一个 EXE 的基于 CMDIFrameWnd 的主要窗口都实现了拖放功能。 ActiveX 控件实现了拖放源和拖放目标,主窗口只是拖放目标,特别是对于来自 Windows 资源管理器的文件。

拖放实现非常标准,基于从 COleDataSourceCOleDropTarget 派生的两个数据成员,分别用于放置源和放置目标。 COleDropTarget 派生成员在窗口的 OnCreate 方法中注册到相应的窗口。它还以类似的方式覆盖 OnDragEnterOnDragOverOnDrop 方法。即,系统提供的 COleDataObject 参数被要求提供特定格式(特别是 CF_HDROP),在肯定回答的情况下,数据(例如,文件路径)从剪贴板中提取。代码如下所示:

static FORMATETC g_FileFmt = {CF_HDROP, 0, DVASPECT_CONTENT, 0, TYMED_HGLOBAL};
    ....
// Inside OnDragEnter, OnDragOver or OnDrop method
STGMEDIUM stgmedium = {0,0,0};
if (pDataObject->IsDataAvailable(g_FileFmt.cfFormat))
{
    HRESULT hr = pDataObject->GetData(g_FileFmt.cfFormat, &stgmedium);
    HDROP hdrop = (HDROP)GlobalLock(stgmedium.hGlobal);
    if (hdrop != 0)
    {
        int FilesCount = DragQueryFile(hdrop, (UINT)-1, 0, 0);
        if (FilesCount != 0)
        {
            TCHAR FileName[_MAX_PATH];
            DragQueryFile(hdrop, 0, FileName, _MAX_PATH);
            // Check file extension and store the file name for farther use.
        }
        GlobalUnlock(hdrop);
    }
}

放置源的实现也很简单,如下所示:

void CDmDocListCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    if (pNMListView->iItem != -1 && m_pOleDataSource && prv_BeginDrag())
    {
        DROPEFFECT DE = m_pOleDataSource->DoDragDrop(
            DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK, 0);
    }
    *pResult = 0;
}

其中 prv_BeginDrag() 函数通过从 m_pOleDataSource 对象的 调用 SetData 方法收集拖动的数据,将其打包并放入剪贴板>IDataObject 接口(interface)。

在决定使整个应用程序免注册之前,所有这些东西都运行良好。我花了三个月的时间通过嵌入 list 、按需启动进程外 COM 服务器和更改某些类的 CLSID 来强制隔离运行应用程序(不注册 COM 组件),以便将同一服务器的实例从不同的服务器启动文件夹。它终于开始工作了——但没有拖放功能,尽管它甚至没有被我的更改所触及。

在放置目标端,当我从 Windows 资源管理器拖动文件时,上面描述的对 COleDataObject::IsDataAvailable 的调用返回 false,尽管在我的更改返回 true 之前。同时,如果我在主窗口的 OnCreate 方法中添加一行代码“DragAcceptFiles();”,拖放操作将通过标准 CFrameWnd 的 WM_DROPFILE 开始工作消息处理程序。

在放置源端,拖动的数据成功打包并放置在剪贴板上,但是 COleDataSource::DoDragDrop 方法失败,因为调用了 ::DoDragDrop MFC 实现中的 API 返回 REGDB_E_CLASSNOTREG“类未注册”结果。

这意味着,COM 激活的变化会以某种方式影响拖放行为。怎么办?

附言1) 我将文件从 Windows 资源管理器拖到其中的 EXE 在其项目属性中具有“UAC 执行级别 = asInvoker”。据我所知,它告诉我,当通过双击文件启动时,EXE 将在与 Windows 资源管理器相同的 UAC 级别运行。

2) 非常令人惊讶的是,虽然拖放停止工作并出现上述症状,但复制/粘贴继续工作良好,尽管这两种技术具有相似的实现。

3) 我相信,如果找出::DoDragDrop API 何时返回“Class not registered”错误,以及它正在寻找哪个类,就可以解决问题。

感谢帮助, 伊利亚。

最佳答案

按照 MartinBa 的建议,我在 Process Monitor 的帮助下解决了这个问题。 Process Monitor 向我显示,当我在 ActiveX 控件(问题中提到)中拖动一个项目时,系统尝试访问注册表中的类 ID 失败。找那个ID,发现还真不是类ID,而是IDataObject接口(interface)ID。它在我的一个 list 文件中被引用。

大部分 list 是我手写的,但也有少数 list ,尤其是在项目开始时没有这方面的经验,是由 Visual Studio 从现有类型库自动生成的。其中一个 Studio 包含用于几个系统接口(interface)的 comInterfaceExternalProxyStub 语句,其中 proxyStubClsid32 元素(错误地)等于接口(interface) ID。

我仍然不确定这些系统接口(interface)是否应该出现在 list 中;例如,IDataObject 在一个 IDL 定义中仅作为方法的参数被提及。无论如何,我只更正了 proxyStubClsid32 值,问题就消失了......

这个对我来说非常痛苦的故事的寓意是始终检查自动工具的输出...

关于c++ - 有谁知道免注册 COM 和拖放功能之间可能存在哪种关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22791292/

有关c++ - 有谁知道免注册 COM 和拖放功能之间可能存在哪种关系?的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  6. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  7. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

    我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

  8. ruby-on-rails - rspec - 如何检查方法是否存在? - 2

    我的模型有defself.empty_building//stuffend我怎样才能对这个现有的进行rspec?,已经尝试过:describe"empty_building"dosubject{Building.new}it{shouldrespond_to:empty_building}endbutgetting:Failure/Error:it{shouldrespond_to:empty_building}expected#torespondto:empty_building 最佳答案 你有一个类方法self.empty_bu

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

随机推荐