在Windows 7上实例化和OleControlSite时引发NullPointerException [英] NullPointerException thrown when instantiating and OleControlSite on Windows 7

查看:214
本文介绍了在Windows 7上实例化和OleControlSite时引发NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试从SWT打开excel时出现NullPointerException.可悲的是,我无法发布完整的stacktrace和一些代码,因为它引用了我所工作的公司.希望有人曾经遇到过这个问题并且可能认识到它.

I am getting a NullPointerException when trying to open excel from SWT. Sadly I can't post the full stacktrace and some of the code because it has references to the company that I work for. Hopefully someone has run into this issue before and might recognize it.

这是我可以发布的堆栈跟踪的一部分

Here is the part of the stacktrace that I can post

java.lang.NullPointerException
at org.eclipse.swt.ole.win32.OleControlSite.disconnectEventSinks(OleControlSite.java:468)
at org.eclipse.swt.ole.win32.OleControlSite.releaseObjectInterfaces(OleControlSite.java:774)
at org.eclipse.swt.ole.win32.OleClientSite.onDispose(OleClientSite.java:909)
at org.eclipse.swt.ole.win32.OleClientSite.access$1(OleClientSite.java:895)
at org.eclipse.swt.ole.win32.OleClientSite$1.handleEvent(OleClientSite.java:129)

这是代码.在实例化新的OleControlSite时,在最后一行抛出异常.

Here is the code. It's on the last line that the exception gets thrown, when a new OleControlSite is instantiated.

OleFrame frame1 = new OleFrame(shell, SWT.NONE);
if (clientSite != null && !clientSite.isDisposed()){
    clientSite.dispose();
    clientSite = null;
}
OleAutomation doc;
try{
    clientSite = new OleControlSite(frame1, SWT.NONE, file);    

此代码在Windows XP中有效,但在Windows 7中不起作用,它会抛出NullPointerException.

This code works in windows XP, but not in windows 7 it throws the NullPointerException.

根据三次建议,我创建了一个自包含的示例,此处是代码.

As per cubic suggestion I created a self contained example here is the code.

package com.test;

import java.io.File;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleControlSite;
import org.eclipse.swt.ole.win32.OleEvent;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.OleListener;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Button;

public class OpenExcelExampleWindow extends Shell {
    public final static int WorkbookBeforeClose    = 0x00000622;

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String args[]) {
        try {
            Display display = Display.getDefault();
            OpenExcelExampleWindow shell = new OpenExcelExampleWindow(display);
            shell.open();
            shell.layout();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Create the shell.
     * @param display
     */
    public OpenExcelExampleWindow(Display display) {
        super(display, SWT.SHELL_TRIM);

        Button btnOpenExcel = new Button(this, SWT.NONE);
        btnOpenExcel.setBounds(10, 10, 68, 23);
        btnOpenExcel.setText("open excel");

        btnOpenExcel.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                onOpenExcelClicked();
            }

        });
        createContents();
    }

    protected void onOpenExcelClicked() {
        openExcel("testfile.xls",this);
    }

    /**
     * Create contents of the shell.
     */
    protected void createContents() {
        setText("SWT Application");
        setSize(450, 300);

    }

    @Override
    protected void checkSubclass() {
        // Disable the check that prevents subclassing of SWT components
    }

    protected void openExcel(String fileName, Shell shell){
        OleControlSite clientSite = null;
        final File file = new File(fileName);
        if (file.exists()) {

            OleFrame frame1 = new OleFrame(shell, SWT.NONE);
            if (clientSite != null && !clientSite.isDisposed()){
                clientSite.dispose();
                clientSite = null;
            }

            clientSite = new OleControlSite(frame1, SWT.NONE, file);                        
            OleAutomation doc = new OleAutomation(clientSite);

            int [] dispInfo = doc.getIDsOfNames(new String[] {"Application"});
            Variant variant = doc.getProperty(dispInfo[0]);
            OleAutomation app = variant.getAutomation();
            variant.dispose();
            doc.dispose();
            doc = null;

            int result = clientSite.doVerb(OLE.OLEIVERB_OPEN);  
            if (result != OLE.S_OK){
                OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
            }

            //When user close workbook, dispose the clientSite.
            clientSite.addEventListener(app, "{00024413-0000-0000-C000-000000000046}",
                    WorkbookBeforeClose,new OleListener() {
                public void handleEvent(OleEvent event) {

                    OleControlSite oldControlSite = (OleControlSite)event.widget;
                    if ( !oldControlSite.isDisposed()){
                        //System.out.println("event in WorkbookBeforeClose");
                        oldControlSite.dispose();
                    }
                }
            });

        }
    }
}

这是个例外

java.lang.NullPointerException
at org.eclipse.swt.ole.win32.OleControlSite.disconnectEventSinks(OleControlSite.java:468)
at org.eclipse.swt.ole.win32.OleControlSite.releaseObjectInterfaces(OleControlSite.java:774)
at org.eclipse.swt.ole.win32.OleClientSite.onDispose(OleClientSite.java:909)
at org.eclipse.swt.ole.win32.OleClientSite.access$1(OleClientSite.java:895)
at org.eclipse.swt.ole.win32.OleClientSite$1.handleEvent(OleClientSite.java:129)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1058)
at org.eclipse.swt.widgets.Widget.release(Widget.java:808)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:446)
at org.eclipse.swt.ole.win32.OleClientSite.<init>(OleClientSite.java:194)
at org.eclipse.swt.ole.win32.OleControlSite.<init>(OleControlSite.java:96)
at com.test.OpenExcelExampleWindow.openExcel(OpenExcelExampleWindow.java:93)
at com.test.OpenExcelExampleWindow.onOpenExcelClicked(OpenExcelExampleWindow.java:65)
at com.test.OpenExcelExampleWindow$1.widgetSelected(OpenExcelExampleWindow.java:57)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:248)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
at com.test.OpenExcelExampleWindow.main(OpenExcelExampleWindow.java:33)


更新:


Update:

我用maven创建了一个全新的项目,并为eclipse sdk 4.2添加了一个依赖关系,这是我的pom文件,您可以看到只有一个依赖关系.项目中的代码与上面的类相同.

I created an entirely new project with maven and just added one dependency for eclipse sdk 4.2 here is my pom file you can see there is only one dependency. The code in the project is the same as the class above.

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test</groupId>
  <artifactId>excelopen</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>excelopen</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
<build>
<plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.8</version>
            </plugin>
</plugins>
</build>
  <dependencies>
        <dependency>
            <groupId>org.eclipse.swt</groupId>
            <artifactId>swt-win32-x86_64</artifactId>
            <version>4.2_3.100.0.v4233d</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
  </dependencies>
</project>

我注意到OleControlSite类的源代码从3.8 sdk到4.2 sdk是相同的,因此不太可能是SDK版本对我造成了问题.

I noticed that the source code for the OleControlSite class is the same from 3.8 sdk to the 4.2 sdk, which makes it unlikely that it's the SDK version that's causing the issue for me.


更新:


Update:

我下载了SWT源代码,并在此行的OleClientSite的392行引发了异常.

I download the SWT Source code and the exception get's thrown at line 392 of OleClientSite at this line.

if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result)

隐藏的异常是

org.eclipse.swt.SWTException: Failed to create Ole Client. result = -2147221164
at org.eclipse.swt.ole.win32.OLE.error(OLE.java:302)
at org.eclipse.swt.ole.win32.OleClientSite.OleCreate(OleClientSite.java:392)
at org.eclipse.swt.ole.win32.OleClientSite.<init>(OleClientSite.java:192)
at org.eclipse.swt.ole.win32.OleControlSite.<init>(OleControlSite.java:96)
at com.test.OpenExcelExampleWindow.openExcel(OpenExcelExampleWindow.java:93)
at com.test.OpenExcelExampleWindow.onOpenExcelClicked(OpenExcelExampleWindow.java:65)
at com.test.OpenExcelExampleWindow$1.widgetSelected(OpenExcelExampleWindow.java:57)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:248)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
at com.test.OpenExcelExampleWindow.main(OpenExcelExampleWindow.java:33)


更新09/05 9:35 am


Update 09/05 9:35am

由于favonius的信息,我能够找到更多的信息.我在64位Windows OS上找到了有关32位com的讨论.这是讨论64位上的32位com的地方. http://www.eclipse.org/forums/index. php/mv/msg/264018/763345/ 这可能是我的问题,因为我们正在运行的Office 2007仅以32位版本提供,并且在64位OS上运行.我想检查注册表,但是我不知道我应该查找什么键.有谁知道注册表项是什么?

Thanks to favonius's information I was able to find out some more information. I found this discussion about 32bit com's on a 64bit windows OS. This is where the 32bit com on 64bit is discussed. http://www.eclipse.org/forums/index.php/mv/msg/264018/763345/ This might be my issue as we are running Office 2007 which only comes in 32bit and it's running on a 64bit OS. I would like to check the registry but I don't know what key's I should look up. Does anyone know what the registry key is?


更新09/05 9:45 am


Update 09/05 9:45am

这是favonius提供的TestCode类的结果.

Here are the results of the TestCode class that favonius provided.

运行1,第57行已注释

Run 1 with line 57 commented

{00020820-0000-0000-C000-000000000046}
Excel.Sheet.8
org.eclipse.swt.SWTException: Failed to create Ole Client. result = -2147221164
    at org.eclipse.swt.ole.win32.OLE.error(OLE.java:302)
    at com.test.TestCode.check(TestCode.java:62)
    at com.test.TestCode.main(TestCode.java:23)

第2行第57行未注释

{00020820-0000-0000-C000-000000000046}
Excel.Sheet.8


更新09/05 1:51 pm


Update 09/05 1:51pm

我们的应用程序输出一个xls文件供excel打开.我只是尝试读取一个xlsx文件,它可以工作.这是一个合理的更改,可以解决此特定应用程序的问题.是否不应该打开xls文件?

Our app outputs an xls file for excel to open. I just tried reading in an xlsx file and it works. This is a reasonable change to fix the problem with this specific app. Is it not supposed to open xls files?

推荐答案

剖析问题

根据您的上一次更新,where您提到了异常的起源,问题出在以下几行.

Dissecting the Problem

As per your last update, where you mentioned the origin of the exception, the problem lies in the following lines.

int /*long*/[] ppv = new int /*long*/[1];
result = COM.CoCreateInstance(appClsid, 0, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, COM.IIDIUnknown, ppv);
if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);

现在,以上代码中的第二行尝试创建与指定的CLSID关联的类的单个未初始化对象.现在,根据您的情况,您直接提供XLSX文件路径,因此它使用

Now the second line in the above code is trying create a single uninitialized object of the class associated with a specified CLSID. Now in your case you are directly providing the XLSX file path, and therefore it uses the GetClassFile() which returns the CLSID associated with the specified file name. Now if it would have failed then you should have gotten the exception at line 186 of OleClientSite. Also, you are able to get a proper program id from the file class id otherwise an exception at line 189 would have resulted.

在您的堆栈跟踪中,您收到错误代码-2147221164.现在检查一下它的真正含义.启动Visual Studio,然后从菜单Tools-> Error Lookup中选择.将错误代码放在此处,然后单击查找.它给...

In your stacktrace you got an error code -2147221164. Now to check what it really means. Start up your Visual Studio and select from menu Tools -> Error Lookup. Put the error code there and click lookup. And it gives...

现在的问题是,在 189 行中从class id获取program id时,是否应该遇到class is not registered这个问题.这使事情变得怪异.因此,在继续操作之前,请先进行第二次检查.

Now the question is if the class is not registered then you should have got this problem while getting the program id from the class id at line 189. And this makes thing weird. Therefore, before proceeding ahead follow the Second Check.

按照

As per MSDN entry of CoCreateInstance, the above error message could also mean thatthe type of server you requested in the CLSCTX enumeration is not registered or the values for the server types in the registry are corrupt.

再次检查并确定真正的问题,只需尝试

As a second check and to nail the real problem, just try this SWT Snippet and update the result in your question.

我已经编写了这个简单的测试类.尝试运行它并发布控制台输出.另外,取消注释第57行,然后再次运行并发布其输出.

I have written this simple test class. Try to run it and post the console output. Also, uncomment the line 57 and run again and post its output too.

注意-,您必须更改File构造函数参数.

Note - You have to change the File constructor parameter.

import java.io.File;

import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.internal.ole.win32.GUID;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TestCode 
{
    public static void main(String[] args)
    {
        Display display = new Display();
        Shell shell = new Shell(display);

        shell.setText("Excel Example");
        shell.setLayout(new FillLayout());

        try{
            check(new File("output.xlsx"));
        }catch(Exception e){
            e.printStackTrace();
        }

        shell.open();

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

    static void check(File file)
    {
        GUID fileClsid = new GUID();
        char[] fileName = (file.getAbsolutePath()+"\0").toCharArray();
        int result = COM.GetClassFile(fileName, fileClsid);
        if (result != COM.S_OK) 
            OLE.error(OLE.ERROR_INVALID_CLASSID, result);

        System.out.println(fileClsid);

        String progID = getProgID(fileClsid); 
        if (progID == null) 
            OLE.error(OLE.ERROR_INVALID_CLASSID, result);

        System.out.println(progID);


        int [] ppv = new int[1];

        int server_type = COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER;

        //server_type |= COM.CLSCTX_LOCAL_SERVER; 

        result = COM.CoCreateInstance(fileClsid, 0, server_type, COM.IIDIUnknown, ppv);
        if (result != COM.S_OK) 
            OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
    }

    static String getProgID(GUID clsid)
    {
        if (clsid != null)
        {
            int [] lplpszProgID = new int [1];
            if (COM.ProgIDFromCLSID(clsid, lplpszProgID) == COM.S_OK)
            {
                int  hMem = lplpszProgID[0];
                int length = OS.GlobalSize(hMem);
                int  ptr = OS.GlobalLock(hMem);
                char[] buffer = new char[length];
                COM.MoveMemory(buffer, ptr, length);
                OS.GlobalUnlock(hMem);
                OS.GlobalFree(hMem);

                String result = new String(buffer);
                int index = result.indexOf("\0");
                return result.substring(0, index);
            }
        }
        return null;
    }
}

这篇关于在Windows 7上实例化和OleControlSite时引发NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆