1

For example, let's say I have a folder on my desktop. When I open the folder, is it possible for a program to run when it happens? Is there any way to identify the action of a specific folder opening?

Pang
  • 9,564
  • 146
  • 81
  • 122
killakrab
  • 41
  • 5

2 Answers2

3

You may can use the handle.exe which released by microsoft, could download it from microsoft offical site: https://learn.microsoft.com/zh-cn/sysinternals/downloads/handle

After download it, put handle.exe in the same folder of test.py, then execute python test.py $your_folder to get the result, FYI.

test.py

import os
import sys

candidate_folder = sys.argv[1]
print('Please wait for some seconds before the process done...')
rc = os.system("handle.exe -accepteula %s | findstr pid" %(candidate_folder))
if 0 == rc:
    print('The folder is opened by above process.')
else:
    print('No process open this folder now.')

1) test1: (do not open the folder C:\abc)

C:\Handle>python test.py C:\abc
Please wait for some seconds before the process done...
No process open this folder now.

2) test2: (open the folder C:\abc)

C:\Handle>python test.py C:\abc
Please wait for some seconds before the process done...
explorer.exe       pid: 15052  type: File          2B9C: C:\abc
explorer.exe       pid: 15052  type: File          2BC0: C:\abc
The folder is opened by above process.
atline
  • 28,355
  • 16
  • 77
  • 113
1

One way you could achieve this would be by frequently polling the currently opened windows titles this recipe.

Make a function that attempts to find a window object with the expected title and returns True if it finds one, False otherwise.

Now you can have a while True: loop that calls that function, checks if it returns a True (which should happen when that folder is opened, if it's opened using the Windows Explorer with the option to show the folder name in the title bar), and waits a few seconds before trying again. Maybe you can have additional checks on the hwnd object to make sure it's an explorer process and not something else, I don't know.

I don't know much about the windll function, maybe there's a way to avoid polling and be notified by some kind of event when the status of the windows change, which would make the code more efficient and a bit more resilient.


Full working example after correcting a few things (tested on Windows 7 with the "Display the full path in the title bar" Folder Option turned on):

import ctypes
import time

EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible

class FoundWindow(Exception):
  pass

def titleExists(title):
  status = []
  def foreach_window(hwnd, lParam):
    if IsWindowVisible(hwnd):
      length = GetWindowTextLength(hwnd)
      buff = ctypes.create_unicode_buffer(length + 1)
      GetWindowText(hwnd, buff, length + 1)
      if buff.value == title:
        status.append(True)
      return True
  EnumWindows(EnumWindowsProc(foreach_window), 0)
  return len(status) > 0

while True:
  if titleExists(u"C:\Windows"):
    print('The "C:\Windows" directory was opened!')
    exit(0)
  time.sleep(1)

I'm bad at python so I had to resort to ugly tricks to keep track of what happened inside the EnumWindowsProc calls, there are probably better approaches to that, but it works.

NicolasB
  • 966
  • 5
  • 9