Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 128841 - 100% CPU usage with excel automation
Summary: 100% CPU usage with excel automation
Status: RESOLVED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Duong Nguyen CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-02-21 11:50 EST by Aditya Mahajan CLA
Modified: 2008-07-29 18:28 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aditya Mahajan CLA 2006-02-21 11:50:45 EST
I am trying to use swt automation to open an existing excel file. I picked up code from Snippet199.java to get it going http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet199.java?rev=HEAD&content-type=text/vnd.viewcvs-markup

The code works, as in it opens up the excel file for me. However my CPU usage goes up to 100% when excel is launched! 

I tried to debug a little further and found that the following line of code in org.eclipse.swt.ole.win32.OleClientSite causes the CPU usage to go to 100%

/********************************************************/
protected void addObjectReferences() {
...
...
// Notify the control object that it is embedded in an OLE container
  COM.OleSetContainedObject(objIUnknown.getAddress(), true);
...
...
}
/********************************************************/

I commented out the call to OleSetContainedObject and recompiled swt.jar. The application seems to run fine now and the CPU load is perfectly normal. But probably I have added a few memory leaks now. 
Please find the relevant code to reproduce the problem below. 
Environment details: Win XP / Office 2003 / Eclipse3.2M4 / jdk1.4.2_08

/********************************************************/

 public static void main (String [] args) {
    Display display = new Display ();
    Shell shell = new Shell (display);
    shell.setLayout(new FillLayout());
    OleControlSite controlSite;
     OleAutomation application;
    OleAutomation workbook ;

    try {
        OleFrame frame = new OleFrame(shell, SWT.NONE);
        controlSite = new OleControlSite(frame, SWT.None, "Excel.Application");

    } catch (SWTError e) {
        System.out.println("Unable to open activeX control");
        return;
    }
    application = new OleAutomation(controlSite);
    int[] dispIDs = application.getIDsOfNames(new String[] {"Workbooks"});
    Variant pVarResult = application.getProperty(dispIDs[0]);
    OleAutomation workbooks = pVarResult.getAutomation();
    pVarResult.dispose();

     final int[] dispMIDs = workbooks.getIDsOfNames(new String[] {"Open"});

     Variant[] arguments = new Variant[]{new Variant("C:\\excel test\\Book1.xls")};
     if ((dispMIDs != null) && (dispMIDs.length > 0)) {
         workbook= workbooks.invoke(dispMIDs[0],arguments).getAutomation();
     }

     workbooks.dispose();

     dispIDs = application.getIDsOfNames(new String[] {"Visible"});
     pVarResult = application.getProperty(dispIDs[0]);
     application.setProperty(dispIDs[0], new Variant(true));
     pVarResult.dispose();


    while (!shell.isDisposed ()) {
        if (!display.readAndDispatch ()) display.sleep ();
    }
    application.dispose();
    display.dispose ();
}

/********************************************************/
Comment 1 Steve Northover CLA 2006-02-24 20:02:32 EST
Aditya, did this ever get resolved on the newsgroup?
Comment 2 Aditya Mahajan CLA 2006-02-26 11:30:10 EST
This issue never got resolved in the newsgroup. A quite popular workaround however was mentioned which is to use "Excel.Sheet" as the progId. This does not lead to the high CPU usage problem. The workaround is however not very usable since it has its own share of problems. see- http://www.eclipse.org/newsportal/article.php?id=27096&group=eclipse.platform.swt#27096
Comment 3 Duong Nguyen CLA 2007-05-29 11:14:15 EDT
I believe the "hijack" problem is no longer an issue.
Comment 4 Steve Northover CLA 2007-05-29 12:03:33 EDT
Duong, please get to the bottom of it.  Is the bug still happening or not?  Is the news group work around necessary?
Comment 5 Duong Nguyen CLA 2007-05-30 14:27:39 EDT
The 100% CPU usage occurs after invoking this line in the OleClientSite:

	// Notify the control object that it is embedded in an OLE container
	COM.OleSetContainedObject(objIUnknown.getAddress(), true);

MSDN doc states that calling this method "ensures that reference counting is done correctly for containers that support links to embedded objects." I'm not sure if why this caused the CPU usage to spike to 100%.

Even when the SWT app is terminated, the CPU usage remains at 100%. You must terminate EXCEL.EXE to restore things back to normal. In fact, you don't need to open up any SWT shell. Just causing the Excel application to run by creating the OleControlSite was sufficient to cause the CPU usage to go up to 100%. Another interesting observation I found is that if you click on any menus in the Excel app, the CPU will drop back down to 0%. It would appear that the application is mis-behaving.

I found a few bugs on MSDN related to CPU usage spikes to 100% when using Excel. They have a couple of patches for this problem. I applied them to my machine but  it doesn't seem to fix the problem.

Since there's a reasonable work around using Excel.Sheet and it appears to be an Windows issue. I'm marking this defect as WONTFIX.
Comment 6 Shawn Peters CLA 2008-07-28 18:01:40 EDT
I know this bug was marked as a WONTFIX, but I am curious why would this still work then from a Visual Basic 6 application? It seems like if this was a windows issue this should be occurring no matter what technology I go through. Currently, we have this working in an old visual basic application and are in the process of re-writing it in Java. 

As for the workaround, the Excel.sheets is not a viable option because (as I understand it), Excel will be treated as an ActiveX control and will therefore be controlled by the Java application instantiating it. Meaning, it can't close unless the entire Java application closes or we programmatically dispose of it ourselves. 

The problem is that we want to be able to open Excel and allow the user to have it open as long as they want. So we won't ever know when we can dispose of it. We want it to be treated as a completely separate process.

Thanks 
Comment 7 Steve Northover CLA 2008-07-28 18:48:52 EDT
Shawn, it seems the best bet is "Excel.Sheet".  Duong, we need to understand why this is no good.  Please help this guy.
Comment 8 Duong Nguyen CLA 2008-07-29 13:46:44 EDT
I'm not sure I understand what you mean when you said:

   > Meaning, it can't close unless the entire Java application 
   > closes or we programmatically dispose of it ourselves. 

You can open Excel hosted inside of Eclipse (in-place editor) and close the (Excel) editor when you're done. You don't have to close the entire Java application.
Comment 9 Shawn Peters CLA 2008-07-29 14:51:24 EDT
(In reply to comment #8)
> I'm not sure I understand what you mean when you said:
> 
>    > Meaning, it can't close unless the entire Java application 
>    > closes or we programmatically dispose of it ourselves. 
> 
> You can open Excel hosted inside of Eclipse (in-place editor) and close the
> (Excel) editor when you're done. You don't have to close the entire Java
> application.
> 

What I mean is, Excel closes, but the process does not terminate. The workflow we are trying to implement is from an RCP application, open excel and populate a worksheet with some data and then allow Excel to run by itself completely separate from our RCP app (which is why running Excel.application is the option we prefer as opposed to Excel.Sheet). For instance they may leave Excel open long after the RCP app or close it before the RCP app closes.

Does that help?
Comment 10 Duong Nguyen CLA 2008-07-29 15:21:09 EDT
Thanks for the clarification.

In that case, wouldn't it be easier to launch Excel as a separate application instead of using OLE? Something like this:

	Display display = new Display ();
	Program program = Program.findProgram("xls");
	program.execute("e:/temp/ole/test.xls");
	display.dispose ();


Comment 11 Shawn Peters CLA 2008-07-29 18:28:05 EDT
Actually, I agree. I would prefer to do something like that, however we need to be able to generate the data on a worksheet in memory. I cannot leave the files on the file system. If I write the document out using an API like Apache POI and then open the workbook I will have to have some other process later on clean up the files that we write out when it is not currently open, because I won't know when they closed Excel.