我尝试从SWT打开Excel时得到NullPointerException
。遗憾的是,我无法发布完整的堆栈跟踪和一些代码,因为它引用了我工作的公司。希望有人之前遇到过这个问题并且可能会认出来。
这是我可以发布的堆栈跟踪的一部分
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添加了一个依赖项。这里是我的pom文件,你可以看到只有一个依赖项。项目中的代码与上面的类相同。
<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:35更新
感谢favonius的信息,我能够找到更多信息。我在64位Windows操作系统上找到了关于32位com的讨论。这是讨论64位32位com的地方。 http://www.eclipse.org/forums/index.php/mv/msg/264018/763345/ 这可能是我的问题,因为我们运行的Office 2007只有32位,而且它运行在64位操作系统上。我想检查注册表,但我不知道我应该查找什么密钥。有谁知道注册表项是什么?
<小时/> 09/05上午9:45更新
以下是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:51 pm
我们的应用程序输出一个xls文件,用于打开excel。我只是尝试读取xlsx文件,它的工作原理。这是修复此特定应用程序问题的合理更改。是不是应该打开xls文件?
答案 0 :(得分: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);
现在,上面代码中的第二行正在尝试创建与指定CLSID关联的类的单个未初始化对象。现在,在您的情况下,您直接提供XLSX文件路径,因此它使用GetClassFile()返回与指定文件名关联的CLSID。现在,如果它失败了那么你应该在OleClientSite
的 186 行获得例外。此外,您可以从program id
获得正确的file class id
,否则会产生 189 行的异常。
在您的堆栈跟踪中,您收到错误代码-2147221164
。现在来检查它的真正含义。启动Visual Studio并从菜单Tools
中选择 - &gt; Error Lookup
。将错误代码放在那里,然后单击查找。它给了......
现在的问题是,class is not registered
是否应该在从program id
189 获取class id
时遇到此问题。这让事情变得奇怪。因此,在继续之前,请按照第二次检查。
根据CoCreateInstance的MSDN条目,上述错误消息还可能表示您未在CLSCTX枚举中请求的服务器类型未注册,或者注册表中服务器类型的值已损坏。
作为第二项检查并确定真正的问题,只需尝试此SWT Snippet并更新问题中的结果。
我写过这个简单的测试类。尝试运行它并发布控制台输出。此外,取消注释第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;
}
}