1

My problem is that I am making a program that will get file's data as per the folder that the user has opened as a file explorer... and I have surfed the whole internet to find the answer but it seems that this problem is never faced by anybody before. Many answers are related to the current working directory in which project files are situated.

So, I basically want the path for the folder which is currently being viewed by the user in file explorer...

Julian
  • 3,549
  • 17
  • 39
  • 1
    What is file explorer? Do you mean all of them including terminal file explorers like ranger or one specific file explorer? What if the user opens 5 different folders with 5 instances of one file explorer? – Thomas Sablik Feb 11 '21 at 08:42
  • @ThomasSablik Probably a *File explorer* built-in Windows I suppose, that's only I can think of with same name. – jupiterbjy Feb 11 '21 at 08:43
  • @jupiterbjy Can't see Windows in the question. – Thomas Sablik Feb 11 '21 at 08:43
  • A specific one, which a normal user works with on daily basis... like **My PC** in windows. I want the path to folder on which the user is currently on in My PC. For example (D:\Games) – imran-akbar Feb 11 '21 at 08:47
  • Again, what if they have 5 folders open? You mean the one with the focus? – Tomerikoo Feb 11 '21 at 08:52
  • 2
    Does this answer your question? [Obtain Active window using Python](https://stackoverflow.com/questions/10266281/obtain-active-window-using-python) – Tomerikoo Feb 11 '21 at 08:53
  • What if the user opens 5 folders and none of them has focus? – Thomas Sablik Feb 11 '21 at 08:55
  • @TomerikooTomorrow hmmm... this is not giving me the path. it's only gave me the name of the folder in the foreground – imran-akbar Feb 11 '21 at 08:58

2 Answers2

1
import win32gui, time
from win32con import PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE, MEM_RELEASE, PROCESS_ALL_ACCESS, WM_GETTEXTLENGTH, WM_GETTEXT
from commctrl import LVS_OWNERDATA, LVM_GETITEMCOUNT, LVM_GETNEXTITEM, LVNI_SELECTED
import os
import struct
import ctypes
import win32api
import datetime
import win32com.client as win32
import win32ui
import psutil
import subprocess
import time
import urllib.parse

clsid = '{9BA05972-F6A8-11CF-A442-00A0C90A8F39}' #Valid for IE as well!

def getEditText(hwnd):
    # api returns 16 bit characters so buffer needs 1 more char for null and twice the num of chars
    buf_size = (win32gui.SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0) +1 ) * 2
    target_buff = ctypes.create_string_buffer(buf_size)
    win32gui.SendMessage(hwnd, WM_GETTEXT, buf_size, ctypes.addressof(target_buff))
    return target_buff.raw.decode('utf16')[:-1]# remove the null char on the end

def _normaliseText(controlText):
    '''Remove '&' characters, and lower case.
    Useful for matching control text.'''
    return controlText.lower().replace('&', '')

def _windowEnumerationHandler(hwnd, resultList):
    '''Pass to win32gui.EnumWindows() to generate list of window handle,
    window text, window class tuples.'''
    resultList.append((hwnd, win32gui.GetWindowText(hwnd), win32gui.GetClassName(hwnd)))

def searchChildWindows(currentHwnd,
               wantedText=None,
               wantedClass=None,
               selectionFunction=None):
    results = []
    childWindows = []
    try:
        win32gui.EnumChildWindows(currentHwnd,
                      _windowEnumerationHandler,
                      childWindows)
    except win32gui.error:
        # This seems to mean that the control *cannot* have child windows,
        # i.e. not a container.
        return
    for childHwnd, windowText, windowClass in childWindows:
        descendentMatchingHwnds = searchChildWindows(childHwnd)
        if descendentMatchingHwnds:
            results += descendentMatchingHwnds

        if wantedText and \
            not _normaliseText(wantedText) in _normaliseText(windowText):
                continue
        if wantedClass and \
            not windowClass == wantedClass:
                continue
        if selectionFunction and \
            not selectionFunction(childHwnd):
                continue
        results.append(childHwnd)
    return results


def explorer_fileselection():
    global clsid
    address_1=""
    files = []
    shellwindows = win32.Dispatch(clsid)
    w=win32gui
    window = w.GetForegroundWindow()
    #print("window: %s" % window)
    if (window != 0):
        if (w.GetClassName(window) == 'CabinetWClass'): # the main explorer window
            #print("class: %s" % w.GetClassName(window))
            #print("text: %s " %w.GetWindowText(window))
            children = list(set(searchChildWindows(window)))
            addr_edit = None
            file_view = None
            for child in children:
                if (w.GetClassName(child) == 'WorkerW'): # the address bar
                    addr_children = list(set(searchChildWindows(child)))
                    for addr_child in addr_children:
                        if (w.GetClassName(addr_child) == 'ReBarWindow32'):
                            addr_edit = addr_child
                            addr_children = list(set(searchChildWindows(child)))
                            for addr_child in addr_children:
                                if (w.GetClassName(addr_child) == 'Address Band Root'):
                                    addr_edit = addr_child
                                    addr_children = list(set(searchChildWindows(child)))
                                    for addr_child in addr_children:
                                        if (w.GetClassName(addr_child) == 'msctls_progress32'):
                                            addr_edit = addr_child
                                            addr_children = list(set(searchChildWindows(child)))
                                            for addr_child in addr_children:
                                                if (w.GetClassName(addr_child) == 'Breadcrumb Parent'):
                                                    addr_edit = addr_child
                                                    addr_children = list(set(searchChildWindows(child)))
                                                    for addr_child in addr_children:
                                                        if (w.GetClassName(addr_child) == 'ToolbarWindow32'):
                                                            text=getEditText(addr_child)
                                                            if "\\" in text:
                                                                address_1=getEditText(addr_child)[text.index(" ")+1:]
                                                                print("Address --> "+address_1)

    for window in range(shellwindows.Count):
        window_URL = urllib.parse.unquote(shellwindows[window].LocationURL,encoding='ISO 8859-1')
        window_dir = window_URL.split("///")[1].replace("/", "\\")
        print("Directory --> "+window_dir)
        if window_dir==address_1:
            selected_files = shellwindows[window].Document.SelectedItems()
            for file in range(selected_files.Count):
                files.append(selected_files.Item(file).Path)
            print("Files --> "+str(files))

while True:
    try:
        explorer_fileselection()
    except Exception:
        print("No Path Found!")
    time.sleep(1)

Well, my solution is quite complicated, but i have found this for you. I hope that it may help.

0

Best way I can imagine doing that is write your Python software to use context menu in Explorer. With quick googling I found a interesting library for that: https://pypi.org/project/context-menu/

I suppose that there is no sensible way to read data from another process. That would cause security problems.

ex4
  • 1,947
  • 1
  • 10
  • 19
  • _"I suppose that there is no sensible way to read data from another process. That would cause security problems."_ It's called API. Many programs provide interfaces for this kind of communication: https://docs.microsoft.com/en-us/windows/win32/shell/developing-with-windows-explorer – Thomas Sablik Feb 11 '21 at 09:02
  • @ThomasSablik: thank you for info. I didn't know Windows Explorer provides API. I was thinking scenario trying read data from a process which doesn't provide API or data which isn't provided by API. For example, I hope no one can read data from my banksoftware.exe process. – ex4 Feb 11 '21 at 09:06
  • On Windows you can. That's how most of the game cheating software works. They read memory of the game process and try to interpret the values to change them later. On other operating systems it's difficult or impossible. – Thomas Sablik Feb 11 '21 at 09:07