【问题标题】:How do I programmatically add a folder to the user's Favorites (in Windows Explorer)?如何以编程方式将文件夹添加到用户的收藏夹(在 Windows 资源管理器中)?
【发布时间】:2010-11-24 21:36:56
【问题描述】:

我正在寻找一种以编程方式将文件夹添加到 Windows 资源管理器中的收藏夹的方法。它的 Windows Explorer 特定并基于这个项目:http://www.codeproject.com/Tips/132804/Open-folders-using-a-Run-Command

到目前为止,我已经尝试过 Process Monitor 并搜索注册表,但我似乎无法在 regedit 中找到我的 Windows Explorer 收藏夹。


Microsoft 在 Windows 8 中对此进行了更改,因此我相应地标记了我的问题。有关 Win8 等详细信息,请参阅标记答案中的 cmets。

【问题讨论】:

    标签: c# windows-7 windows-shell favorites


    【解决方案1】:

    您可以执行以下操作,而不是读取注册表:

    string favoritesFolder = 
        Environment.GetFolderPath(Environment.SpecialFolder.Favorites);
    

    【讨论】:

    • 对于 Windows 7 也是不正确的,当资源管理器侧边栏不合逻辑地从 %USERPROFILE%\Links 获取它的收藏夹部分时,这会给出 %USERPROFILE%\Favourites
    • 我可以确认@Jonathan。回答。这没有按预期工作。
    【解决方案2】:

    P.S.:请务必查看@bsegraves' solution,我认为这比我的要好得多。

    我不确定这是否是您要查找的内容,但我认为可以通过以下注册表值找到最喜欢的文件夹:

    HKEY_CURRENT_USER\
      Software\
        Microsoft\
          Windows\
            CurrentVersion\
              Explorer\
                User Shell Folders\
                  Favorites
    

    您应该能够使用以下代码检索此文件夹名称:

    using Microsoft.Win32;
    ...
    
    RegistryKey topLevel = Registry.CurrentUser;
    RegistryKey key = topLevel.OpenSubKey(
        @"Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders",
        true);
    
    string favoriteFolder = key.GetValue("Favorites").ToString();
    

    然后只需在指定文件夹中创建链接或文档即可。

    (请注意,此键的值可能类似于%USERPROFILE%\Favorites;环境变量应由上面调用的.GetValue(..) 方法自动扩展。)

    【讨论】:

    • 谢谢!那个目录 %USERPROFILE%\Favorites 有他们:) 如果我有 15 分,我会投票给你:(
    • @Jeremy,即使你不能投票,如果你认为它充分回答了你的问题,你仍然应该能够接受答案(勾选它)。 (这也会给 2 个等级积分。)
    • 我认为 OP 是在询问 WINDOWS 资源管理器,而不是 IE。收藏夹文件夹包含指向 IE 中收藏夹的链接。
    • @KFL:老实说,我现在有点困惑,为什么我的回答当时对我和 OP 来说都是正确的。今天,我的 Explorer 收藏夹确实位于Favorites(注册表项指向的位置),而是位于Links。会不会是 Windows 操作系统从那以后发生了轻微的变化?我当时有 Windows 7,但现在使用的是 Windows 8。
    • @stakx Mate,您的回答确实有效。现在无法在 Win8 上对其进行测试,但如果不是,我不会将其标记为正确 - 这是我在 Stack Overflow 上的第一个问题。重新标记以使我的问题特定于 Win7。
    【解决方案3】:

    对于 Windows 8,此位置已更改为 %USERPROFILE%\Links。请参考this answer

    【讨论】:

    【解决方案4】:

    从 Vista 开始 FOLDERID_Links 添加了常量。它指向 Windows 资源管理器的收藏夹。我的代码(Delphi,但主要思想可见):

    procedure AddFileObjectToFavorites(AParent: HWND; const AObjectFileName: UnicodeString);
    
      function GetFavorites: PItemIDList;
      begin
        if IsWindowsVistaOrLater then
          OleCheck(SHGetKnownFolderIDList(FOLDERID_Links, 0, 0, Result))
        else
          OleCheck(SHGetFolderLocation(AParent, CSIDL_FAVORITES, 0, 0, Result));
      end;
    
    var
      Desktop: IShellFolder;
      Eaten: DWORD;
      Attr: DWORD;
      ObjectIDList: PItemIDList;
      ObjectParentFolder: IShellFolder;
      ObjectChildIDList: PItemIDList;
      LinksIDList: PItemIDList;
      LinksParentFolder: IShellFolder;
      LinksChildIDList: PItemIDList;
      DataObject: IDataObject;
      LinksDropTarget: IDropTarget;
      Effect: Integer;
    begin
      OleCheck(SHGetDesktopFolder(Desktop));
      try
        Attr := 0;
        OleCheck(Desktop.ParseDisplayName(AParent, nil, PWideChar(AObjectFileName), Eaten, ObjectIDList, Attr));
        try
          SHBindToParent(ObjectIDList, IShellFolder, Pointer(ObjectParentFolder), ObjectChildIDList);
          try
            LinksIDList := GetFavorites;
            try
              OleCheck(SHBindToParent(LinksIDList, IShellFolder, Pointer(LinksParentFolder), LinksChildIDList));
              try
                OleCheck(LinksParentFolder.GetUIObjectOf(AParent, 1, LinksChildIDList, IDropTarget, nil, LinksDropTarget));
                try
                  OleCheck(ObjectParentFolder.GetUIObjectOf(AParent, 1, ObjectChildIDList, IDataObject, nil, DataObject));
                  try
                    Effect := DROPEFFECT_LINK;
                    OleCheck(LinksDropTarget.DragEnter(DataObject, 0, Point(0, 0), Effect));
                    if Effect and DROPEFFECT_LINK = 0 then
                      begin
                        OleCheck(LinksDropTarget.DragLeave);
                        raise Exception.Create('Cannot drop');
                      end;
                    Effect := DROPEFFECT_LINK;
                    OleCheck(LinksDropTarget.Drop(DataObject, 0, Point(0, 0), Effect));
                  finally
                    DataObject := nil;
                  end;
                finally
                  LinksDropTarget := nil;
                end;
              finally
                LinksParentFolder := nil;
              end;
            finally
              CoTaskMemFree(LinksIDList);
            end;
          finally
            ObjectParentFolder := nil;
          end;
        finally
          CoTaskMemFree(ObjectIDList);
        end;
      finally
        Desktop := nil;
      end;
    end;
    

    【讨论】:

    • 我之前没有在 Delphi 中编写过代码,但是 7 try catch's vs 3 行 .net。哇,纯粹的精神错乱
    • @JeremyThompson 5 个 try/finally 块是多余的和不必要的。 Delphi 原生支持接口引用计数。本例中无需显式释放接口。只有对CoTaskMemFree() 的2 次调用应使用try/finally 进行保护。此外,IShellLink 的使用要比跳过所有这些设置IShellFolderIDataObject 简单得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 2015-07-15
    • 2010-11-10
    相关资源
    最近更新 更多