5

I try to get the selected files of a folder which the user is using. I have the following code which is already running, but only on desktop files:

private string selectedFiles()
{
    // get the handle of the desktop listview
    IntPtr vHandle = WinApiWrapper.FindWindow("Progman", "Program Manager");
    vHandle = WinApiWrapper.FindWindowEx(vHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
    vHandle = WinApiWrapper.FindWindowEx(vHandle, IntPtr.Zero, "SysListView32", "FolderView");
    
    //IntPtr vHandle = WinApiWrapper.GetForegroundWindow();

    //Get total count of the icons on the desktop
    int vItemCount = WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMCOUNT, 0, 0);
    //MessageBox.Show(vItemCount.ToString());
    uint vProcessId;
    WinApiWrapper.GetWindowThreadProcessId(vHandle, out vProcessId);
    IntPtr vProcess = WinApiWrapper.OpenProcess(WinApiWrapper.PROCESS_VM_OPERATION | WinApiWrapper.PROCESS_VM_READ |
    WinApiWrapper.PROCESS_VM_WRITE, false, vProcessId);
    IntPtr vPointer = WinApiWrapper.VirtualAllocEx(vProcess, IntPtr.Zero, 4096,
    WinApiWrapper.MEM_RESERVE | WinApiWrapper.MEM_COMMIT, WinApiWrapper.PAGE_READWRITE);
    try
    {
        for (int j = 0; j < vItemCount; j++)
        {
            byte[] vBuffer = new byte[256];
            WinApiWrapper.LVITEM[] vItem = new WinApiWrapper.LVITEM[1];
            vItem[0].mask = WinApiWrapper.LVIF_TEXT;
            vItem[0].iItem = j;
            vItem[0].iSubItem = 0;
            vItem[0].cchTextMax = vBuffer.Length;
            vItem[0].pszText = (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(WinApiWrapper.LVITEM)));
            uint vNumberOfBytesRead = 0;
            WinApiWrapper.WriteProcessMemory(vProcess, vPointer,
            Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0),
            Marshal.SizeOf(typeof(WinApiWrapper.LVITEM)), ref vNumberOfBytesRead);
            WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMW, j, vPointer.ToInt32());
            WinApiWrapper.ReadProcessMemory(vProcess,
            (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(WinApiWrapper.LVITEM))),
            Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
            vBuffer.Length, ref vNumberOfBytesRead);
            string vText = Encoding.Unicode.GetString(vBuffer, 0,
            (int)vNumberOfBytesRead);
            string IconName = vText;

            //Check if item is selected
            var result = WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMSTATE, j, (int)WinApiWrapper.LVIS_SELECTED);
            if (result == WinApiWrapper.LVIS_SELECTED)
            {
                return vText;
            }
        }
    }
    finally
    {
        WinApiWrapper.VirtualFreeEx(vProcess, vPointer, 0, WinApiWrapper.MEM_RELEASE);
        WinApiWrapper.CloseHandle(vProcess);
    }
    return String.Empty;
}

I tried to get the window handle with GetForegroundWindow() and then call the SHELLDLL_DefView without success.

So how can I change the first 3 rows to get me the handle of the current folder in use?

peterh
  • 11,875
  • 18
  • 85
  • 108
MUG4N
  • 19,377
  • 11
  • 56
  • 83

2 Answers2

4

That's a lot of hacking to do something that is explicitly supported by the various shell objects and interfaces. Granted the documentation doesn't make it easily discoverable, but the functionality is there. Raymond Chen wrote a great article about using these interfaces. There doesn't appear to be a way to get the "current" folder, though I guess you could get the HWNDs and see if any is the foreground window.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Luke
  • 11,211
  • 2
  • 27
  • 38
2

thank you very much. You gave me the right direction. It is possible to get the selected files of a folder:

/// <summary>
/// Get the selected file of the active window
/// </summary>
/// <param name="handle">Handle of active window</param>
/// <returns></returns>
public String getSelectedFileOfActiveWindow(Int32 handle)
{
    try
    {
        // Required ref: SHDocVw (Microsoft Internet Controls COM Object)
        ShellWindows shellWindows = new SHDocVw.ShellWindows();

        foreach (InternetExplorer window in shellWindows)
        {
            if (window.HWND == handle)
                return ((Shell32.IShellFolderViewDual2)window.Document).FocusedItem.Path;
        }                
    }
    catch (Exception)
    {
        return null;
    }
    return null;
}
Firo
  • 30,626
  • 4
  • 55
  • 94
MUG4N
  • 19,377
  • 11
  • 56
  • 83
  • 1
    You will have to add SHDocVw (Microsoft Internet Controls) COM Object as a reference to your project. – boulaycote Dec 07 '12 at 14:49
  • can you please show the code to get the variable handle and tell how the function getSelectedFileOfActiveWindow has to be called in main() – akki Jan 26 '14 at 18:44
  • @MUG4N I am actually having problem in creating a handle, maybe because I am very new to c#. Can you please point me in some direction.Any help is greatly apreciated. Thanks – akki Jan 27 '14 at 22:35
  • @akki: In the following link you can see how to get the handle of an active window http://stackoverflow.com/questions/12019524/get-active-window-of-net-application – MUG4N Jan 30 '14 at 17:33