0

NullPointerExceptionSWT から Excel を開こうとするとエラーが発生します。残念ながら、私が働いている会社への参照が含まれているため、完全なスタック トレースとコードの一部を投稿することはできません。うまくいけば、誰かが以前にこの問題に遭遇し、それを認識するかもしれません.

ここに投稿できるスタックトレースの一部があります

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 がインスタンス化されると、例外がスローされるのは最後の行です。

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

立方体の提案に従って、ここに自己完結型の例を作成しました。コードは次のとおりです。

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)


アップデート:

Maven を使用してまったく新しいプロジェクトを作成し、Eclipse SDK 4.2 の依存関係を 1 つ追加しました。これが私の pom ファイルで、依存関係が 1 つしかないことがわかります。プロジェクト内のコードは、上記のクラスと同じです。

    <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 のバージョンである可能性は低くなります。


アップデート:

SWT ソース コードをダウンロードすると、OleClientSite の 392 行目のこの行で例外がスローされます。

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:35am

favonius の情報のおかげで、さらに多くの情報を見つけることができました。64 ビット Windows OS での 32 ビット com に関するこのディスカッションを見つけました。ここでは、64 ビットでの 32 ビット com について説明します。 http://www.eclipse.org/forums/index.php/mv/msg/264018/763345/ 32 ビット版のみの Office 2007 を 64 ビット OS で実行しているため、これは私の問題かもしれません。レジストリを確認したいのですが、どのキーを調べればよいかわかりません。レジストリキーが何であるか知っている人はいますか?


更新 09/05 9:45am

以下は favonius が提供した TestCode クラスの結果です。

57 行目にコメントを付けて 1 を実行します。

{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:51pm

私たちのアプリは、開くための Excel 用の xls ファイルを出力します。xlsx ファイルを読み込もうとしたところ、動作しました。これは、この特定のアプリの問題を修正するための合理的な変更です。xlsファイルを開くことは想定されていませんか?

4

1 に答える 1

0

問題の分析

前回の更新によるwhereと、例外の原因について言及しましたが、問題は次の行にあります。

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);

上記のコードの2行目は、指定されたCLSIDに関連付けられたクラスの初期化されていない単一のオブジェクトを作成しようとしています。ここで、XLSXファイルパスを直接指定しているため、指定されたファイル名に関連付けられたCLSIDを返すGetClassFile()を使用します。これで失敗した場合は、の186行目で例外が発生しているはずですOleClientSite。また、そうでなければ189行目の例外が発生したであろうprogram idから適切なものを取得することができます。file class id

エラーコードの確認

スタックトレースにエラーコードがあります-2147221164。次に、それが実際に何を意味するのかを確認します。Visual Studioを起動し、メニューTools->から選択しますError Lookup。そこにエラーコードを入れて、ルックアップをクリックします。そしてそれは与える...

ここに画像の説明を入力してください

ここで問題となるのは、 189行目からclass is not registeredを取得しているときにこの問題が発生するはずだったかどうかです。そして、これは物事を奇妙にします。したがって、先に進む前に、2番目のチェックに従ってください。program idclass id

CoCreateInstanceのMSDNエントリによると、上記のエラーメッセージは、CLSCTX列挙で要求したサーバーの種類が登録されていないか、レジストリのサーバーの種類の値が破損していることを意味する場合もあります。

2回目のチェック

2番目のチェックとして、実際の問題を突き止めるために、このSWTスニペットを試して、質問の結果を更新してください。

3番目のチェック

この簡単なテストクラスを作成しました。それを実行して、コンソール出力を投稿してみてください。また、 57行目のコメントを外して再度実行し、その出力も投稿します。

注-ファイルコンストラクターパラメーターを変更する必要があります。

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;
    }
}
于 2012-09-05T06:03:51.000 に答える