【问题标题】:IExplorerBrowser - Browse in place without starting default applicationIExplorerBrowser - 原地浏览而不启动默认应用程序
【发布时间】:2015-04-05 12:13:45
【问题描述】:

我正在开发 Windows 文件管理器应用程序,它本质上包含 IExplorerBrowser,为我提供了与 Windows 资源管理器中一样的精确控制。

我已经使用 Mutex 和 IPC 实现了单实例来传递参数。

所以现在我希望能够在您从 ie 打开目录时将我的文件管理器注册为默认应用程序。桌面

所以我创建了这样的注册表脚本:

REGEDIT4

[HKEY_CURRENT_USER\Software\Classes\Drive\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName\command]
@="\"<app-path>\" %1"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName\command]
@="\"<app-path>\" \"%1\""

它按预期工作,如果我双击目录它会启动我的应用程序,并且由于我实现了单个实例,它不会产生多个实例。

由于我的应用程序中有选项卡式界面,因此每次打开目录时,它都会使用 IExplorerBrowser 控件创建新选项卡。

问题是,现在 IExplorerBrowser 控件的行为发生了变化,当我从控件打开目录时,我得到了新选项卡,而不是在控件内部导航,这是合乎逻辑的(它总是调用注册表命令来启动我的应用程序,并将目录作为 arg)

TL;博士;

Windows 资源管理器如何处理这个问题? Windows 资源管理器如何知道目录是否从 ie 打开。桌面,还是从 Windows 资源管理器内部导航到“listview”而不是打开新窗口?

【问题讨论】:

  • Explorer 从文件夹的 IContextMenu 中查询 IObjectWithSite 接口,并调用 IObjectWithSite.SetSite 对象实现 IServiceProvider。打开命令处理程序使用站点并获取 IShellBrowser 接口。如果找到 IShellBrowser 打开命令处理程序使用它进行导航。
  • @DenisAnisimov 我正在使用 IExplorerBrowser 的 Windows-API-Code-Pack-1.1 C# 实现,如果我理解正确的话,HResult Microsoft.WindowsAPICodePack.Controls.IServiceProvider.QueryService 应该为 RIID 和接口指针返回 HResult.Ok?

标签: c# winapi registry windows-explorer single-instance


【解决方案1】:

我不是 C# 开发人员,我不知道 Windows-API-Code-Pack-1.1 的详细信息。在我的 NSE 项目中,我在当前资源管理器窗口(IContextMenu 处理程序的一部分)中使用以下导航算法:

Site.QueryInterface(IServiceProvider, ServiceProvider) // Site was received in IObjectWithSite.SetSite
ServiceProvider.QueryService(SID_STopLevelBrowser, IShellBrowser, ShellBrowser)
ShellBrowser.BrowseObject(ChildItem, SBSP_RELATIVE or SBSP_SAMEBROWSER)

也许对你有帮助。

【讨论】:

  • 我想我终于明白了,你在谈论类似于 stackoverflow.com/questions/28166945/… 的东西,基本上是说我必须创建 shell 扩展,而不仅仅是将它推到注册表中。你真的帮了我很多,谢谢!
  • 我创建了 shell 扩展,就像你在我之前的评论中链接到的问题中解释的那样,我得到了在我的 SetSite 函数中实现 IServiceProvider 的站点,还有一件事让我抓狂的是我可以当我在资源管理器中双击文件夹时,它不能调用我的 InvokeCommand,而它在右键单击时工作 -> 打开,有什么想法吗?
  • 我的理解是否正确 - 当您双击文件夹时,您的 shell 扩展已创建,但未调用 IObjectWithSite.SetSite?
  • IObjectWithSite.SetSite 如你所说被调用,但是当我双击时没有调用 InvokeCommand。
  • 这意味着您的菜单项不是第一个默认菜单项。当您双击文件夹时,会执行第一个默认项目。
【解决方案2】:

它必须是一个更好的方法来做到这一点,但这是可行的:

  HResult ICommDlgBrowser3.OnDefaultCommand(IntPtr ppshv)
    {
        if (SelectedItems.Count > 0)
        {
            var item = SelectedItems[0];

            ShellNativeMethods.ShellFileGetAttributesOptions sfgao;
            item.NativeShellItem2.GetAttributes(ShellNativeMethods.ShellFileGetAttributesOptions.Folder, out sfgao);
            bool isFolder = (sfgao & ShellNativeMethods.ShellFileGetAttributesOptions.Folder) != 0;

            if (isFolder)
            {
                Navigate(SelectedItems[0]);
                return HResult.Ok;
            }
        }
        return HResult.False;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    相关资源
    最近更新 更多