草庐IT

c++ - 如何用C++编写Shell扩展?

coder 2023-06-01 原文

这似乎是一个常见的问题,但是在进行了一些搜索之后,我才真正找不到答案。这里有一篇文章:

http://www.codeproject.com/KB/shell/shellextguide1.aspx

但这是针对非常旧版本的Visual Studio的。我使用的是VS 2008,因此说明和界面似乎与我所看到的不匹配。

我想使用C++创建一个简单的shell扩展,它为扩展名为.GZ的文件创建一个上下文菜单。右键单击这些文件时,我应该能够单击上下文菜单项,并在代码中进行回调以对该文件执行某种操作。

其他上下文菜单项将执行诸如生成无模式对话框之类的操作,以在执行某些操作之前接受用户输入。

从我所见,ATL用于此目的,但我从未使用过ATL,因此所有对象类型和接口(interface)都令我感到困惑。如果我有合适的教程或文档可以阅读,那还不错。

谁能帮我吗?那里有没有10年历史的教程吗?

最佳答案

我无法确切告诉您如何编写Shell扩展,但是我将提供许多技巧。与更简单的“仅注册”方法相比,编写Shell Extension具有一些明显的优势:

  • 使用Shell Extension,您可以动态创建与所选文件更相关的上下文菜单项(或子菜单)。例如,如果您正在为zip文件编写Shell Extension,则可以在上下文菜单中创建一个子菜单,以显示zip的全部内容。
  • 您可以同时处理多个文件,这可能不仅对提高性能有好处,而且还使您可以基于整体选择而不是每个文件来确定要做什么。

  • Shell扩展的一些缺点是:
  • 大大增加了复杂性。准备为此花费很多精力以使其正常运行。在计算机旁边安装家用咖啡机和/或雇人为您煮咖啡。
  • 大大增加了调试难度。同理咖啡。

  • 编写Shell扩展很困难,因为它们很难调试。
  • Shell扩展由explorer.exe进程加载,并且在没有特定的Explorer配置的情况下,您需要强制退出explorer.exe进程,以便可以安装更高版本的Shell Extension。有一种方法可以使资源管理器卸载不再使用的DLL,但是您只能在开发计算机上而不是在部署目标上执行此操作:
  • 在RegEdit中,浏览到以下键:
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
  • 添加一个名为“AlwaysUnloadDLL”的新DWORD key ,并将其值设置为1。
  • 重新启动资源管理器。

  • 在大多数情况下,这是可行的,但是由于Shell Extension尚未卸载,因此有时仍然需要关闭Explorer。
  • 请记住,您的Shell Extension可能会被其他应用程序加载,例如,如果右键单击带有应用程序“打开文件”对话框的文件,则您的Shell Extension将被加载到该应用程序中,而不是资源管理器中。
  • 如果Shell扩展程序导致运行时错误,则结果通常只是不显示上下文菜单项,很少会告诉您Shell扩展程序加载失败或导致运行时错误。
  • 即使进行安装,配置也可能很困难,需要在多个位置创建注册表数据,并且根据您希望上下文菜单显示的位置,注册表的位置在Windows的不同版本之间可能会有所不同。

  • 您需要做的是:
  • Visual Studio提供了一些用于创建Shell扩展的快捷方式,但是基本上您需要创建一个COM DLL。上下文菜单项的Shell Extension必须同时实现 IContextMenu 接口(interface)和 IShellExtInit 接口(interface)。
  • IShellExtInit::Initialize()方法中,您可以从IDataObject参数获取所选文件。从内存中,数据为“Drag-n-Drop”格式,因此您需要从HDROP获取IDataObject句柄,然后从那里查询文件(这是从内存中获取的,实际上可能与我在这里描述的有所不同,因此请谨慎操作)。
  • 准备好“安装”您的DLL后,您必须将其复制到某个地方,然后运行regsvr32以确保已注册。
  • 按照this guide知道将注册表项放在哪里。
  • 64位Windows可能存在问题,如果您构建32位DLL,则它可能无法在64位资源管理器中加载...因此,如果在使用64位Windows时遇到问题,请记住这一点。
  • 您的DLL实际上将具有两个与其关联的GUID。我不记得它是如何工作的,但是一个GUID指的是DLL本身,而另一个GUID指的是实际的Shell扩展。在需要GUID的注册表中创建注册表项时,请确保使用实际Shell Extension的GUID。

  • 考虑了所有事物…(tl; dr)
    权衡一下Shell扩展是否值得的成本。如果要基于所选文件动态创建菜单项,则Shell扩展可能是唯一的方法。如果要同时处理所有文件,则可能还需要Shell扩展。
    上下文菜单方法的另一种选择是在用户的桌面上放置一个拖放目标。探索其他让用户将文件提交到应用程序的方法,因为Shell Extension往往要付出更多的努力。我发现这很困难,我想其他人也都有。

    关于c++ - 如何用C++编写Shell扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8811621/

    有关c++ - 如何用C++编写Shell扩展?的更多相关文章

    1. ruby - 在 Ruby 中编写命令行实用程序 - 2

      我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

    2. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

      我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

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

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

    4. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

      这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

    5. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

      我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

    6. c - mkmf 在编译 C 扩展时忽略子文件夹中的文件 - 2

      我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。

    7. 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.你能做的最好的事情是:

    8. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

      我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

    9. ruby - 如何计算 Liquid 中的变量 +1 - 2

      我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

    10. ruby - 从 Ruby : capturing the output while displaying the output? 运行 shell 命令 - 2

      我有一个问题。我想从另一个ruby​​脚本运行一个ruby​​脚本并捕获它的输出信息,同时让它也输出到屏幕。亚军#!/usr/bin/envrubyprint"Enteryourpassword:"password=gets.chompputs"Hereisyourpassword:#{password}"我运行的脚本文件:开始.rboutput=`runner`putsoutput.match(/Hereisyour(password:.*)/).captures[0].to_s正如您在此处看到的那样,存在问题。在start.rb的第一行,屏幕是空的。我在运行程序中看不到“输入您的密

    随机推荐