V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
justou
V2EX  ›  Python

请教一个用程序打开 windows 资源管理器的问题

  •  
  •   justou · 2016-08-09 13:09:33 +08:00 · 2788 次点击
    这是一个创建于 2820 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家在 windows 下使用编辑器或者其它一些软件的时候应该遇到过这种功能: "在目录中显示", "打开文件所在目录",... 比如:

    • PyCharm 在左边工程文件上右键时, 会有选项"show in explorer"
    • CodeBlocks 直接在代码上右键会有个选项"open containing folder"
    • VS(我的是 2015)在编辑器的 table 页的标签上右键也有个选项"open containing folder"
    • programer's notepad 也有"open containing folder"
    • 迅雷也有这种"打开文件夹"的功能

    但是我发现它们的行为有两种:
    对于同一个文件,

    1. pycharm, codeblocks 执行多少次"打开文件夹"就有多少个窗口出现
    2. 而 VS, programmer's notepad, 迅雷, 对于同一个文件, 无论执行多少次"打开文件夹"就只会出现一个窗口, 如果有一个旧的窗口存在了, 就仅仅是把它弹到最前面来.

    对于第一种行为, 直接使用 windows 的命令即可, explorer /select, path
    比如在控制台上执行explorer /select, C:\Windows, 这将会打开 C 盘并选中Windows 文件夹, 当然执行多少次就会打开多少个窗口.

    问题是第二种行为如何实现?

    程序是由 python+pyqt 写的, 如果第二种行为控制台命令可行的话, 直接把命令传给 subprocess 就行了, 如果控制台命令行不通, 在 python 下可有其它办法?

    11 条回复    2016-08-10 21:41:08 +08:00
    xuboying
        1
    xuboying  
       2016-08-09 13:11:30 +08:00 via Android   ❤️ 1
    可以选择 API 调用
    Kisesy
        2
    Kisesy  
       2016-08-10 18:19:19 +08:00
    最好不要执行 explorer /select ,这个会创建多个 explorer 进程,即使关掉窗口,这些进程也不会关掉
    justou
        3
    justou  
    OP
       2016-08-10 18:53:15 +08:00
    @Kisesy 我试了下, 关闭窗口后 explorer 的应用进程消失, 然后转为后台进程, 但是一会儿过后这些后台进程会自动结束,
    我的是 win10 1511. 所以我才寻找可以只打开一个窗口方法, 翻了很久 windows api, 至今没解决
    Kisesy
        4
    Kisesy  
       2016-08-10 20:19:35 +08:00
    遗留进程的问题,在 Win7 上是有的,关于 API 可能是 SHOpenFolderAndSelectItems
    justou
        5
    justou  
    OP
       2016-08-10 21:00:26 +08:00
    @Kisesy 我也只找到这个, 感觉效果跟 explorer /select 是一样的, 翻了很久文档跟查找相关头文件就是找怎么用 ctypes 构造它的参数, 这方面资料太少了, 只好先用 explorer /select 先将就了下了
    justou
        6
    justou  
    OP
       2016-08-10 21:12:52 +08:00
    还想到的办法是执行 explorer /select 后获得它的进程号, 再打开同一个文件的窗口时如果有旧的进程存在就先将那个进程杀死(用 psutil)后再打开新窗口, 这样的话每个文件就需要绑定一个进程号, 不想去改那些代码了, 已经把 show_in_explorer(filename)独立出来了, 只需要给它个文件名就可以, 不想它跟其它代码发生关系
    Kisesy
        7
    Kisesy  
       2016-08-10 21:18:45 +08:00   ❤️ 1
    import ctypes

    ctypes.windll.ole32.CoInitialize(None)
    upath = r"C:\Windows\notepad.exe"
    pidl = ctypes.windll.shell32.ILCreateFromPathW(upath)
    ctypes.windll.shell32.SHOpenFolderAndSelectItems(pidl, 0, None, 0)
    ctypes.windll.shell32.ILFree(pidl)
    ctypes.windll.ole32.CoUninitialize()

    唉。。网上抄的, Py3 用的,如果是 Py2 ,请把路径转一下码
    Kisesy
        8
    Kisesy  
       2016-08-10 21:19:55 +08:00
    不想转码就把 ILCreateFromPathW 换成 ILCreateFromPathA
    justou
        9
    justou  
    OP
       2016-08-10 21:26:24 +08:00
    @Kisesy 非常感谢! 的确可行! 刚好满足需求!
    可否贴一下原始地址, 唉... 对 windll 里面东西太陌生了
    Kisesy
        10
    Kisesy  
       2016-08-10 21:30:55 +08:00
    https://github.com/exaile/exaile/blob/master/xl/common.py

    唉.... 其实以前我的 API 资料很多,但是被格式化了。。。只能现找了。。。
    justou
        11
    justou  
    OP
       2016-08-10 21:41:08 +08:00
    唉, 没想起在那儿搜, 前不久才注册了账号(´+ω+`)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1060 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 22:39 · PVG 06:39 · LAX 15:39 · JFK 18:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.