Search code examples
javawinapiwindows-explorershell32com4j

Error com4j.ComException: 80004005 .\invoke.cpp:51 while getting open windows and selected items


I need to get all selected files and folders in Windows Explorer. I'm using com4j to access win Shell32 API (thanks to Tom91136, refer this if you need to learn how can you install and initialize com4j).

This code class gets the selected files or folders in Windows Explorer and prints.

import java.io.File;
import com4j.*;
import test.wsh.*;
import java.util.*;
import java.util.Timer;
import javax.swing.*;


public class DetectSelection {

    public static void main(String[] argv)
    {
            list(); //there is a timer actually, calls every second
    }

    public static void list(){
        System.out.println("SELECTION DETECT:");

        String newResults="";

        try
        {
            List<IWebBrowser2> browsers = getIWebBrowser2();
            for(IWebBrowser2 browser : browsers){
                IShellFolderViewDual3 view = getIShellFolderViewDual3(browser);
                if (view != null && browser.visible()) {

                    FolderItems items = view.selectedItems();

                    for (Com4jObject object : items) {
                        FolderItem item = object.queryInterface(FolderItem.class);
                        if (item != null) {
                            newResults+=item.path()+" - "+item.type()+"\n\n";
                        }
                    }
                }
            }
        }
        catch(Exception error)
        {
            System.out.println("Error in list: "+error.toString());
        }

        System.out.println(newResults);
    }

    public static List<IWebBrowser2> getIWebBrowser2() {
        // TODO this can be potentially optimized
        try
        {
            List<IWebBrowser2> rWindows=new ArrayList<IWebBrowser2>();

            IShellWindows windows = ClassFactory.createShellWindows()
                    .queryInterface(IShellWindows.class);
            for (Com4jObject window : windows) {

                IWebBrowser2 browser = window.queryInterface(IWebBrowser2.class);
                    rWindows.add(browser);
            }
            return rWindows;
        }
        catch(Exception error)
        {
            System.out.println("Error in getIWebBrowser2: "+error.toString());
            return null;
        }
    }

    public static IShellFolderViewDual3 getIShellFolderViewDual3(IWebBrowser2 browser) {
        if (browser == null)
            return null;

        try
        {
            return browser.document().queryInterface(IShellFolderViewDual3.class);
        }
        catch(Exception error)
        {
            System.out.println("Error in getIShellFolderViewDual3: "+error.toString());
            return null;
        }
    }
}

I posted only essential parts. I am using a timer to check open files periodically. Calls list() method every second. It works fine but I am getting the error below if I close a Window.

    com4j.ComException: 80004005 
 .\invoke.cpp:517
        at com4j.Wrapper.invoke(Wrapper.java:166)
        at com.sun.proxy.$Proxy10.document(Unknown Source)
        at DetectSelection.getIShellFolderViewDual3(DetectSelection.java:79)
        at DetectSelection.list(DetectSelection.java:32)
    Caused by: com4j.ComException: 80004005 Belirtilmemiş hata : Belirtilmemiş hata : .\invoke.cpp:517
        at com4j.Native.invoke(Native Method)
        at com4j.StandardComMethod.invoke(StandardComMethod.java:35)
        at com4j.Wrapper$InvocationThunk.call(Wrapper.java:340)
        at com4j.Task.invoke(Task.java:51)
        at com4j.ComThread.run0(ComThread.java:153)
        at com4j.ComThread.run(ComThread.java:134)

I started to use try-catch and I got this:

Error in getIShellFolderViewDual3: com4j.ComException: 80004005  .\invoke.cpp:517

Something wrong with "IShellFolderViewDual3" method.


Solution

  • I guess your problem is about timer. If there is a timer and the list() method is running every second then when you close a window, getIShellFolderViewDual3() method also tries to access a closing window, at the same time.

    Check if "browser" object is visible and not null before use it.

    try
            {
                List<IWebBrowser2> browsers = getIWebBrowser2();
                for(IWebBrowser2 browser : browsers){
                    if(browser.visible())
                    {
    
                        IShellFolderViewDual3 view = getIShellFolderViewDual3(browser);
                        if (view != null && browser.visible()) {
    
                            FolderItems items = view.selectedItems();
    
                            for (Com4jObject object : items) {
                                FolderItem item = object.queryInterface(FolderItem.class);
                                if (item != null) {
                                    newResults+=item.path()+" - "+item.type()+"\n\n";
                                }
                            }
                        }
                    }
                }
            }