You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows资源管理器中打开指定文件夹并选中多个项目

实现Windows资源管理器定位文件夹并多选项目

问题场景

已知文件夹路径:

dir_: str = r'path\to\a\folder'

以及该文件夹内的项目列表(不含路径):

items: list[str] = [
    'foo.py',
    'bar.exe',
    'baz'
]

需要打开Windows资源管理器,定位到dir_并选中列表中所有项目。尝试过subprocess调用explorer /select命令,但该命令仅支持选中单个项目。

解决方案

方法一:使用pywin32库(需额外安装)

先安装依赖:

pip install pywin32

实现代码:

import os
import win32com.client

dir_ = r'path\to\a\folder'
items = ['foo.py', 'bar.exe', 'baz']

# 生成每个项目的完整路径
full_item_paths = [os.path.join(dir_, item) for item in items]

# 初始化Shell对象
shell = win32com.client.Dispatch("Shell.Application")

# 打开文件夹并选中第一个项目
shell.ShellExecuteEx(
    Verb="open",
    File=dir_,
    Parameters=f"/select,{full_item_paths[0]}",
    Show=1
)

# 遍历选中剩余项目
folder = shell.NameSpace(dir_)
for path in full_item_paths[1:]:
    item = folder.ParseName(os.path.basename(path))
    item.InvokeVerb("select")

说明:先通过ShellExecuteEx打开目标文件夹并选中第一个项目,再通过Shell对象的NameSpace方法获取文件夹对象,逐个选中剩余项目。

方法二:使用ctypes(无需额外依赖)

直接调用Windows Shell API,无需安装第三方库:

import os
import ctypes
from ctypes import wintypes

# 定义Windows API所需的结构和常量
SHCONT = wintypes.DWORD
SIGDN = wintypes.DWORD
SEE_MASK_INVOKEIDLIST = 0x0000000C
SIGDN_FILESYSPATH = 0x80058000

class SHELLEXECUTEINFO(ctypes.Structure):
    _fields_ = [
        ("cbSize", wintypes.DWORD),
        ("fMask", wintypes.DWORD),
        ("hwnd", wintypes.HWND),
        ("lpVerb", wintypes.LPCWSTR),
        ("lpFile", wintypes.LPCWSTR),
        ("lpParameters", wintypes.LPCWSTR),
        ("lpDirectory", wintypes.LPCWSTR),
        ("nShow", wintypes.INT),
        ("hInstApp", wintypes.HINSTANCE),
        ("lpIDList", wintypes.LPVOID),
        ("lpClass", wintypes.LPCWSTR),
        ("hkeyClass", wintypes.HKEY),
        ("dwHotKey", wintypes.DWORD),
        ("hIconOrMonitor", wintypes.HANDLE),
        ("hProcess", wintypes.HANDLE)
    ]

class IShellFolder(ctypes.Structure):
    _fields_ = [
        ("QueryInterface", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.LPCVOID, ctypes.POINTER(wintypes.LPVOID))),
        ("AddRef", ctypes.CFUNCTYPE(wintypes.ULONG)),
        ("Release", ctypes.CFUNCTYPE(wintypes.ULONG)),
        ("ParseDisplayName", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.HWND, wintypes.LPCVOID, wintypes.LPCWSTR, ctypes.POINTER(wintypes.ULONG), ctypes.POINTER(wintypes.LPITEMIDLIST), ctypes.POINTER(wintypes.DWORD))),
        ("EnumObjects", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.HWND, SHCONT, ctypes.POINTER(wintypes.LPVOID))),
        ("BindToObject", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.LPITEMIDLIST, wintypes.LPCVOID, wintypes.LPCVOID, ctypes.POINTER(wintypes.LPVOID))),
        ("BindToStorage", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.LPITEMIDLIST, wintypes.LPCVOID, wintypes.LPCVOID, ctypes.POINTER(wintypes.LPVOID))),
        ("CompareIDs", ctypes.CFUNCTYPE(wintypes.HRESULT, SHCONT, wintypes.LPITEMIDLIST, wintypes.LPITEMIDLIST)),
        ("CreateViewObject", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.HWND, wintypes.LPCVOID, ctypes.POINTER(wintypes.LPVOID))),
        ("GetAttributesOf", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.ULONG, wintypes.LPITEMIDLIST*, ctypes.POINTER(wintypes.DWORD))),
        ("GetUIObjectOf", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.HWND, wintypes.ULONG, wintypes.LPITEMIDLIST*, wintypes.LPCVOID, wintypes.DWORD, ctypes.POINTER(wintypes.LPVOID))),
        ("GetDisplayNameOf", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.LPITEMIDLIST, SIGDN, ctypes.POINTER(wintypes.LPWSTR))),
        ("SetNameOf", ctypes.CFUNCTYPE(wintypes.HRESULT, wintypes.HWND, wintypes.LPITEMIDLIST, wintypes.LPCWSTR, SIGDN, ctypes.POINTER(wintypes.LPITEMIDLIST)))
    ]

# 加载Windows API函数
SHGetDesktopFolder = ctypes.windll.shell32.SHGetDesktopFolder
SHGetDesktopFolder.argtypes = [ctypes.POINTER(wintypes.IShellFolder)]
SHGetDesktopFolder.restype = wintypes.HRESULT

ShellExecuteExW = ctypes.windll.shell32.ShellExecuteExW
ILFree = ctypes.windll.shell32.ILFree

def select_multiple_items(dir_path, item_names):
    if not item_names:
        # 无项目时直接打开文件夹
        ctypes.windll.shell32.ShellExecuteW(None, "open", dir_path, None, None, 1)
        return

    # 打开文件夹并选中第一个项目
    sei = SHELLEXECUTEINFO()
    sei.cbSize = ctypes.sizeof(SHELLEXECUTEINFO)
    sei.fMask = SEE_MASK_INVOKEIDLIST
    sei.lpVerb = "open"
    sei.lpFile = dir_path
    sei.lpParameters = f"/select,{os.path.join(dir_path, item_names[0])}"
    sei.nShow = 1
    ShellExecuteExW(ctypes.byref(sei))

    # 获取桌面Shell文件夹接口
    desktop_folder = IShellFolder()
    SHGetDesktopFolder(ctypes.byref(desktop_folder))

    # 解析文件夹路径为ITEMIDLIST
    folder_pidl = wintypes.LPITEMIDLIST()
    ch_eaten = wintypes.ULONG()
    attrs = wintypes.DWORD()
    desktop_folder.ParseDisplayName(None, None, dir_path, ctypes.byref(ch_eaten), ctypes.byref(folder_pidl), ctypes.byref(attrs))

    # 绑定到目标文件夹的IShellFolder接口
    target_folder = IShellFolder()
    desktop_folder.BindToObject(folder_pidl, None, ctypes.byref(ctypes.c_void_p.from_address(ctypes.addressof(target_folder))), None)

    # 选中剩余项目
    for name in item_names[1:]:
        item_pidl = wintypes.LPITEMIDLIST()
        target_folder.ParseDisplayName(None, None, name, ctypes.byref(ch_eaten), ctypes.byref(item_pidl), ctypes.byref(attrs))
        # 调用select动词选中项目
        target_folder.GetUIObjectOf(None, 1, ctypes.byref(item_pidl), None, 0, None)
        ILFree(item_pidl)

    # 释放资源
    ILFree(folder_pidl)
    desktop_folder.Release()
    target_folder.Release()

# 使用示例
dir_ = r'path\to\a\folder'
items = ['foo.py', 'bar.exe', 'baz']
select_multiple_items(dir_, items)

说明:直接调用Windows底层Shell API,先打开文件夹选中第一个项目,再通过解析项目路径获取对应的Shell对象,逐个选中剩余项目,无需额外安装依赖。

注意事项

  • 确保items中的所有项目都存在于dir_路径下,不存在的项目无法被选中。
  • 如果items为空,建议直接打开文件夹,避免代码报错。

内容的提问来源于stack exchange,提问作者Megacodist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:27:06