| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 45 人关注过本帖
标题:使用IShellFolder接口不能正确列举控制面板项目
只看楼主 加入收藏
mybeibuwan
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2025-3-13
收藏
 问题点数:0 回复次数:1 
使用IShellFolder接口不能正确列举控制面板项目
其他磁盘分区目录和文件是可以正常列举的,但对控制面板这个虚拟目录却不能正常列举,经过多种方式检查均找不出问题原因,现在将问题源码发出来,希望有人能够找出问题的原因和给出解决方案。
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ActiveX, ShellAPI, ShlObj, ComObj,
  Vcl.StdCtrls;

procedure EnumControlPanelItems();
var
  controlPIDL, parentPIDL, pidlChild2: PItemIDList;
  shellFolder1, shellFolder2: IShellFolder;
  enumIDL1, enumIDL2: IEnumIDList;
  pidlSub1, pidlSub2: PItemIDList;
  dwFetched: DWORD;
  dName: String; // 对象显示名称
begin
  CoInitialize(nil);
  try
    // 获取控制面板PIDL
    SHGetSpecialFolderLocation(0, CSIDL_CONTROLS, controlPIDL);
    outputdebugstring(pwidechar('controlPIDL:' + inttostr(ILGetSize(controlPIDL))));

    // 绑定“控制面板”文件夹shellFolder1
    SHBindToParent(controlPIDL, IShellFolder, Pointer(shellFolder1), parentPIDL);
    // 获取控制面板枚举对象enumIDL1
    shellFolder1.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_SHAREABLE, enumIDL1);
    // 这里可以正确列举控制面板第一级功能模块
    while enumIDL1.Next(1, pidlSub1, dwFetched) = S_OK do
    begin
      // 获取显示名
      dName := GetDisplayName(shellFolder1, pidlSub1);
      outputdebugstring(pwidechar(dName));

      // 错误原因可能是下面2个方法上,1:BindToObject,2:EnumObjects,可能是参数传递有问题

      // 绑定到第二级下级文件夹的 IShellFolder 接口
      shellFolder1.BindToObject(pidlSub1, nil, IID_IShellFolder, Pointer(shellFolder2));
      // OLECheck((SHBindToObject(shellFolder1, pidlSub1, nil, IID_IShellFolder, Pointer(shellFolder2))));

      // 获取第二级下级枚举对象enumIDL2
      shellFolder2.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_SHAREABLE, enumIDL2);
      // 是这里不能正确列举第二级下级子项目,大多返回S_FALSE,很多子项都不能列举出来
      while enumIDL2.Next(1, pidlSub2, dwFetched) = S_OK do
      begin
        dName := GetDisplayName(shellFolder2, pidlSub2);
        outputdebugstring(pwidechar('      ' + dName + inttostr(ILGetSize(pidlSub2))));
        CoTaskMemFree(pidlSub2);
      end;

      CoTaskMemFree(pidlSub1);
    end;
    // 释放PIDL
    CoTaskMemFree(parentPIDL);
    CoTaskMemFree(controlPIDL);
  finally
    CoUninitialize;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  EnumControlPanelItems;
end;

下面给出执行源码输出结果
Debug Output: 系统和安全 Process Project1.exe (23360)
Debug Output: 网络和 Internet Process Project1.exe (23360)
Debug Output: 硬件和声音 Process Project1.exe (23360)
Debug Output: 程序 Process Project1.exe (23360)
Debug Output: 用户帐户 Process Project1.exe (23360)
Debug Output:       邮件176 Process Project1.exe (23360)
Debug Output: 外观和个性化 Process Project1.exe (23360)
Debug Output: 时钟和区域 Process Project1.exe (23360)
Debug Output: 轻松使用 Process Project1.exe (23360)
Debug Output: 所有控制面板项 Process Project1.exe (23360)
Debug Output:       Flash Player174 Process Project1.exe (23360)
Debug Output:       邮件176 Process Project1.exe (23360)
Debug Output:       360强力卸载156 Process Project1.exe (23360)
Debug Output:       128 Process Project1.exe (23360)
Debug Output:




[此贴子已经被作者于2025-3-13 19:43编辑过]

2025-03-13 19:34
mybeibuwan
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2025-3-13
收藏
得分:0 
我用VC6语言测试也是这个输出结果,下面给出源码
// 工程1.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "工程1.h"
#include "工程1Dlg.h"
#include <shlobj.h>   // Shell API 相关定义
#pragma comment(lib, "shell32.lib")  // 链接 Shell32 库
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define UNICODE
#define _UNICODE

/////////////////////////////////////////////////////////////////////////////
// CMy1App

BEGIN_MESSAGE_MAP(CMy1App, CWinApp)
    //{{AFX_MSG_MAP(CMy1App)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG
    ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy1App construction



CMy1App::CMy1App()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance

    IShellFolder* pDesktopFolder = NULL;
    SHGetDesktopFolder(&pDesktopFolder);  // 获取桌面 IShellFolder 接口
    LPITEMIDLIST pidlControlPanel = NULL;
    SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlControlPanel);  // 获取控制面板 PIDL?
    IShellFolder* pControlPanelFolder = NULL;
    pDesktopFolder->BindToObject(pidlControlPanel, NULL, IID_IShellFolder, (void**)&pControlPanelFolder);  // 绑定到控制面板?
    IEnumIDList* pEnum = NULL;
    pControlPanelFolder->EnumObjects(NULL, SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnum);  // 获取枚举器

    LPITEMIDLIST pidlItem = NULL;
    while (pEnum->Next(1, &pidlItem, NULL) == S_OK) {
        // 获取显示名称
        STRRET strret;
        pControlPanelFolder->GetDisplayNameOf(pidlItem, SHGDN_NORMAL, &strret);

        WCHAR wszName[MAX_PATH];
        switch (strret.uType) {
            case STRRET_WSTR:
                wcscpy(wszName, strret.pOleStr);  // 直接拷贝宽字符串
                CoTaskMemFree(strret.pOleStr);    // 释放内存?:ml-citation{ref="1,2" data="citationList"}
                break;
            case STRRET_OFFSET:
                wsprintfW(wszName, L"%s", (LPCWSTR)(((BYTE*)pidlItem) + strret.uOffset));
                break;
            case STRRET_CSTR:
                MultiByteToWideChar(CP_ACP, 0, strret.cStr, -1, wszName, MAX_PATH);  // ANSI 转宽字符
                break;
        }
        // 输出名称

        MessageBoxW(NULL, _T(wszName), L"提示", MB_OK);
        // 释放 PIDL
        CoTaskMemFree(pidlItem);
    }
//    pEnum->Release();

}

/////////////////////////////////////////////////////////////////////////////
// The one and only CMy1App object

CMy1App theApp;

/////////////////////////////////////////////////////////////////////////////
// CMy1App initialization

BOOL CMy1App::InitInstance()
{
    AfxEnableControlContainer();

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.

#ifdef _AFXDLL
    Enable3dControls();            // Call this when using MFC in a shared DLL
#else
    Enable3dControlsStatic();    // Call this when linking to MFC statically
#endif

    CMy1Dlg dlg;
    m_pMainWnd = &dlg;
    int nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with OK
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with Cancel
    }

    // Since the dialog has been closed, return FALSE so that we exit the
    //  application, rather than start the application's message pump.
    return FALSE;
}
2025-03-13 19:48
快速回复:使用IShellFolder接口不能正确列举控制面板项目
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.034116 second(s), 8 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved