如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

在SWT中提供了访问OLE的方式,不过相关的例子都是进程内OLE的例子,比如嵌入浏览器、引用ActiveX控件什么的。由于客户的需求,我们需要在程序中通过进程外Automation服务的方式访问IE浏览器。经过网上搜寻,找到一个朋友写的CComObject类可以访问Automation服务。不过经过使用发现一些错误,因此对其进行了修改,为了方便访问IE,我又封装了一个IEAutomation类,这样就暴露给使用者navigatequit这样的方法。(作者:www.cownew.com 杨中科)

这里例子完全可以用来操控其他的Automation对象,比如操控Work、Excel、AcrobatReader等。

全部代码如下:

CComObject.java

package test;


import org.eclipse.swt.SWT;

import org.eclipse.swt.internal.ole.win32.COM;

import org.eclipse.swt.internal.ole.win32.DISPPARAMS;

import org.eclipse.swt.internal.ole.win32.EXCEPINFO;

import org.eclipse.swt.internal.ole.win32.GUID;

import org.eclipse.swt.internal.ole.win32.IDispatch;

import org.eclipse.swt.internal.ole.win32.ITypeInfo;

import org.eclipse.swt.internal.ole.win32.IUnknown;

import org.eclipse.swt.internal.win32.OS;

import org.eclipse.swt.ole.win32.OLE;

import org.eclipse.swt.ole.win32.Variant;

/**

 * 
@author hcw

 
*/


public class CComObject

{

private GUID guid = new GUID();


private IDispatch Autoface = null;


private ITypeInfo TypeInfo = null;


private void CreateComObject()

{

dispose();


int[] ppv = new int[1];


int ret = COM.CoCreateInstance(guid, 0, COM.CLSCTX_INPROC_SERVER

| COM.CLSCTX_LOCAL_SERVER, COM.IIDIUnknown, ppv);

if (ret != COM.S_OK)

OLE.error(ret);

// throw new RuntimeException("对象创建失败!");


IUnknown objIUnknown 
= new IUnknown(ppv[0]);

ppv 
= new int[1];


ret 
= objIUnknown.QueryInterface(COM.IIDIDispatch, ppv);

objIUnknown.Release();

if (ret != COM.S_OK)

OLE.error(ret);

// throw new RuntimeException("对象不支持Dispatch!");


Autoface 
= new IDispatch(ppv[0]);


ppv 
= new int[1];

ret 
= Autoface.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);

if (ret == OLE.S_OK)

{

TypeInfo 
= new ITypeInfo(ppv[0]);

TypeInfo.AddRef();


}



}



private int getIDsOfNames(String name)

{

int[] rgdispid = new int[1];

String[] names 
= new String[] { name };

int ret = Autoface.GetIDsOfNames(guid, names, names.length,

COM.LOCALE_USER_DEFAULT, rgdispid);

if (ret != COM.S_OK)

return -1;


return rgdispid[0];

}



private void getVariantData(Variant aVar, int pData)

{

if (pData == 0)

OLE.error(OLE.ERROR_OUT_OF_MEMORY);


COM.VariantInit(pData);


if ((aVar.getType() & COM.VT_BYREF) == COM.VT_BYREF)

{

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new int[] { aVar.getByRef() }4);

return;

}



switch (aVar.getType())

{

case COM.VT_EMPTY:

break;

case COM.VT_BOOL:

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8,

new int[] { (aVar.getBoolean()) ? COM.VARIANT_TRUE

: COM.VARIANT_FALSE }
2);

break;

case COM.VT_R4:

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new float[] { aVar.getFloat() }4);

break;

case COM.VT_I4:

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new int[] { aVar.getInt() }4);

break;

case COM.VT_DISPATCH:

aVar.getDispatch().AddRef();

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new int[] { aVar.getDispatch()

.getAddress() }
4);

break;

case COM.VT_UNKNOWN:

aVar.getUnknown().AddRef();

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new int[] { aVar.getUnknown()

.getAddress() }
4);

break;

case COM.VT_I2:

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

COM.MoveMemory(pData 
+ 8new short[] { aVar.getShort() }2);

break;

case COM.VT_BSTR:

COM.MoveMemory(pData, 
new short[] { aVar.getType() }2);

char[] data = (aVar.getString() + "\0").toCharArray();

int ptr = COM.SysAllocString(data);

COM.MoveMemory(pData 
+ 8new int[] { ptr }4);

break;


default:

OLE.error(SWT.ERROR_NOT_IMPLEMENTED);

}


}



private Variant setVariantData(int pData)

{

if (pData == 0)

OLE.error(OLE.ERROR_INVALID_ARGUMENT);


Variant ret 
= null;

short[] dataType = new short[1];

COM.MoveMemory(dataType, pData, 
2);

int type = dataType[0];


if ((type & COM.VT_BYREF) == COM.VT_BYREF)

{

int[] newByRefPtr = new int[1];

OS.MoveMemory(newByRefPtr, pData 
+ 84);

return new Variant(newByRefPtr[0], COM.VT_BYREF);

}



switch (type)

{

case COM.VT_EMPTY:

break;

case COM.VT_BOOL:

short[] newBooleanData = new short[1];

COM.MoveMemory(newBooleanData, pData 
+ 82);

ret 
= new Variant(newBooleanData[0!= 0);

break;

case COM.VT_R4:

float[] newFloatData = new float[1];

COM.MoveMemory(newFloatData, pData 
+ 84);

ret 
= new Variant(newFloatData[0]);

break;

case COM.VT_I4:

int[] newIntData = new int[1];

OS.MoveMemory(newIntData, pData 
+ 84);

ret 
= new Variant(newIntData[0]);

break;

case COM.VT_DISPATCH:

{

int[] ppvObject = new int[1];

OS.MoveMemory(ppvObject, pData 
+ 84);

if (ppvObject[0== 0)

{

type 
= COM.VT_EMPTY;

break;

}


ret 
= new Variant(new IDispatch(ppvObject[0]));

break;

}


case COM.VT_UNKNOWN:

{

int[] ppvObject = new int[1];

OS.MoveMemory(ppvObject, pData 
+ 84);

if (ppvObject[0== 0)

{

type 
= COM.VT_EMPTY;

break;

}


ret 
= new Variant(new IUnknown(ppvObject[0]));

break;

}


case COM.VT_I2:

short[] newShortData = new short[1];

COM.MoveMemory(newShortData, pData 
+ 82);

ret 
= new Variant(newShortData[0]);

break;

case COM.VT_BSTR:

// get the address of the memory in which the string resides

int[] hMem = new int[1];

OS.MoveMemory(hMem, pData 
+ 84);

if (hMem[0== 0)

{

type 
= COM.VT_EMPTY;

break;

}


int size = COM.SysStringByteLen(hMem[0]);

if (size > 0)

{

char[] buffer = new char[(size + 1/ 2]; // add one to avoid

// rounding errors

COM.MoveMemory(buffer, hMem[
0], size);

ret 
= new Variant(new String(buffer));

}
 else

{

ret 
= new Variant(""); //$NON-NLS-1$

}


break;


default:

int newPData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT,

Variant.sizeof);

if (COM.VariantChangeType(newPData, pData, (short0, COM.VT_R4) == COM.S_OK)

{

ret 
= setVariantData(newPData);

}
 else if (COM.VariantChangeType(newPData, pData, (short0,

COM.VT_I4) 
== COM.S_OK)

{

setVariantData(newPData);

}
 else if (COM.VariantChangeType(newPData, pData, (short0,

COM.VT_BSTR) 
== COM.S_OK)

{

ret 
= setVariantData(newPData);

}


COM.VariantClear(newPData);

OS.GlobalFree(newPData);

break;

}


return ret;

}



private int invoke(int dispIdMember, int wFlags, Variant[] rgvarg,

int[] rgdispidNamedArgs, Variant[] pVarResult)

{


if (Autoface == null)

return COM.E_FAIL;


DISPPARAMS pDispParams 
= new DISPPARAMS();

if (rgvarg != null && rgvarg.length > 0)

{

pDispParams.cArgs 
= rgvarg.length;

pDispParams.rgvarg 
= OS.GlobalAlloc(COM.GMEM_FIXED

| COM.GMEM_ZEROINIT, Variant.sizeof * rgvarg.length);

int offset = 0;

for (int i = rgvarg.length - 1; i >= 0; i--)

{

getVariantData(rgvarg[i], pDispParams.rgvarg 
+ offset);

offset 
+= Variant.sizeof;

}


}



if (rgdispidNamedArgs != null && rgdispidNamedArgs.length > 0)

{

pDispParams.cNamedArgs 
= rgdispidNamedArgs.length;

pDispParams.rgdispidNamedArgs 
= OS.GlobalAlloc(COM.GMEM_FIXED

| COM.GMEM_ZEROINIT, 4 * rgdispidNamedArgs.length);

int offset = 0;

for (int i = rgdispidNamedArgs.length; i > 0; i--)

{

COM.MoveMemory(pDispParams.rgdispidNamedArgs 
+ offset,

new int[] { rgdispidNamedArgs[i - 1] }4);

offset 
+= 4;

}


}



EXCEPINFO excepInfo 
= new EXCEPINFO();

int[] pArgErr = new int[1];

int pVarResultAddress = 0;

if (pVarResult != null)

pVarResultAddress 
= OS.GlobalAlloc(

OS.GMEM_FIXED 
| OS.GMEM_ZEROINIT, Variant.sizeof);

int ret = Autoface.Invoke(dispIdMember, new GUID(),

COM.LOCALE_USER_DEFAULT, wFlags, pDispParams,

pVarResultAddress, excepInfo, pArgErr);

if (ret != COM.S_OK)

return ret;


if (pVarResultAddress != 0)

{

pVarResult[
0= setVariantData(pVarResultAddress);

COM.VariantClear(pVarResultAddress);

OS.GlobalFree(pVarResultAddress);

}



if (pDispParams.rgdispidNamedArgs != 0)

{

OS.GlobalFree(pDispParams.rgdispidNamedArgs);

}


if (pDispParams.rgvarg != 0)

{

int offset = 0;

for (int i = 0, length = rgvarg.length; i < length; i++)

{

COM.VariantClear(pDispParams.rgvarg 
+ offset);

offset 
+= Variant.sizeof;

}


OS.GlobalFree(pDispParams.rgvarg);

}



return ret;

}



/**

 * 创建空对象在使用需调用CreateComObject或CreateComObjectProgID创建COM对象。

 * 

 
*/


public CComObject()

{


}



/**

 * 使用CLSID创建COM对象,建构后可以调用COM对象方法或属性。

 * 

 * 
@param sCLSID

 *            COM对象CLSID

 * 
@throws RuntimeException

 
*/


public CComObject(String sCLSID) throws RuntimeException

{

COM.IIDFromString(sCLSID.toCharArray(), guid);

CreateComObject();

}



/**

 * 使用现有自动化对象接口创建COM对象。

 * 

 * 
@param prgDispatch

 
*/


public CComObject(IDispatch prgDispatch)

{

Autoface 
= prgDispatch;

Autoface.AddRef();

}



/**

 * 
@author 杨中科

 * 
@param clientName

 * 
@param guid

 
*/


protected void getClassID(String clientName, GUID guid)

{

// create a null terminated array of char

char[] buffer = null;

if (clientName != null)

{

int count = clientName.length();

buffer 
= new char[count + 1];

clientName.getChars(
0, count, buffer, 0);

}


if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK)

{

int result = COM.CLSIDFromString(buffer, guid);

if (result != COM.S_OK)

OLE.error(result);

}


}



/**

 * 使用CLSID创建COM对象。可用于创建新的对象(原有对象将释放)

 * 

 * 
@param sCLSID

 * 
@return

 * 
@throws RuntimeException

 
*/


public IDispatch CreateComObject(String sCLSID) throws RuntimeException

{

COM.IIDFromString(sCLSID.toCharArray(), guid);

CreateComObject();

return Autoface;

}



/**

 * 创建远程COM对象(未实现)。

 * 

 * 
@param MachineName

 * 
@param sCLSID

 * 
@return

 
*/


public IDispatch CreateRemoteComObject(String MachineName, String sCLSID)

{

COM.IIDFromString(sCLSID.toCharArray(), guid);

return Autoface;

}



/**

 * 使用ProgID创建COM对象。

 * 

 * 
@param ProgID

 * 
@return

 * 
@throws RuntimeException

 
*/


public IDispatch CreateComObjectProgID(String ProgID)

throws RuntimeException

{

getClassID(ProgID, guid);

CreateComObject();

return Autoface;

}



/**

 * 调用COM对象方法,有返回值(可变参数暂不支持)。

 * 

 * 
@param FunctionName

 * 
@param rgvarg

 * 
@return

 * 
@throws RuntimeException

 
*/


public Variant CallFunction(String FunctionName, Variant[] rgvarg)

throws RuntimeException

{

if (Autoface == null)

throw new RuntimeException("对象为空");

int rgdispid = getIDsOfNames(FunctionName);

if (rgdispid == -1)

throw new RuntimeException("方法不支持!");

Variant[] pVarResult 
= new Variant[1];

int ret = invoke(rgdispid, COM.DISPATCH_METHOD, rgvarg, null,

pVarResult);

if (ret != COM.S_OK)

OLE.error(ret);

// throw new RuntimeException("方法调用失败!");

return pVarResult[0];

}



/**

 * 调用COM对象方法,无参数和返回值。

 * 

 * 
@param FunctionName

 * 
@throws RuntimeException

 
*/


public void CallFunction(String FunctionName) throws RuntimeException

{

CallFunction(FunctionName, 
new Variant[] {});

}



/**

 * 获取COM对象属性值。

 * 

 * 
@param PropertyName

 * 
@param rgvarg

 * 
@return

 * 
@throws RuntimeException

 
*/


public Variant getProperty(String PropertyName, Variant[] rgvarg)

throws RuntimeException

{

if (Autoface == null)

throw new RuntimeException("对象为空");

int rgdispid = getIDsOfNames(PropertyName);

if (rgdispid == -1)

throw new RuntimeException("属性不支持!");

Variant[] pVarResult 
= new Variant[1];

int ret = invoke(rgdispid, COM.DISPATCH_PROPERTYGET, rgvarg, null,

pVarResult);

if (ret != COM.S_OK)

OLE.error(ret);

// throw new RuntimeException("属性获取失败");

return pVarResult[0];


}



/**

 * 给COM对象属性赋值。

 * 

 * 
@param PropertyName

 * 
@param rgvarg

 * 
@throws RuntimeException

 
*/


public void setProperty(String PropertyName, Variant[] rgvarg)

throws RuntimeException

{

if (Autoface == null)

throw new RuntimeException("对象为空");

int rgdispid = getIDsOfNames(PropertyName);

if (rgdispid == -1)

throw new RuntimeException("属性不支持!");

int[] rgdispidNamedArgs = new int[] { COM.DISPID_PROPERTYPUT };

int dwFlags = COM.DISPATCH_PROPERTYPUT;

for (int i = 0; i < rgvarg.length; i++)

{

if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)

dwFlags 
= COM.DISPATCH_PROPERTYPUTREF;

}


Variant[] pVarResult 
= new Variant[1];

int ret = invoke(rgdispid, dwFlags, rgvarg, rgdispidNamedArgs,

pVarResult);

if (ret != COM.S_OK)

OLE.error(ret);

}



/**

 * 释放COM对象的连接。在对象不用的时候需调用此函数,以便及时释放对象。

 * 

 
*/


public void dispose()

{

if (Autoface != null)

Autoface.Release();

Autoface 
= null;

if (TypeInfo != null)

TypeInfo.Release();

TypeInfo 
= null;

}


}


IEAutomation.java

package test;


import org.eclipse.swt.ole.win32.Variant;


/**

 * 更多方法参考MSDN“InternetExplorer Object”文档

 * 
@author 杨中科

 * 

 
*/


public class IEAutomation

{

static final String progId = "InternetExplorer.Application";


private CComObject ieComObject = new CComObject();


public IEAutomation()

{

ieComObject.CreateComObjectProgID(progId);

}



public void setProperty(String name, int value)

{

ieComObject.setProperty(name, 
new Variant[] new Variant(value) });

}



public int getPropertyAsInt(String name)

{

Variant value 
= ieComObject.getProperty(name, new Variant[0]);

return value.getInt();

}



public void setProperty(String name, boolean value)

{

ieComObject.setProperty(name, 
new Variant[] new Variant(value) });

}



public boolean getPropertyAsBool(String name)

{

Variant value 
= ieComObject.getProperty(name, new Variant[0]);

return value.getBoolean();

}



public void setProperty(String name, String value)

{

ieComObject.setProperty(name, 
new Variant[] new Variant(value) });

}



public String getPropertyAsString(String name)

{

Variant value 
= ieComObject.getProperty(name, new Variant[0]);

return value.getString();

}



public void setVisible(boolean value)

{

setProperty(
"Visible", value);

}



public boolean isVisible()

{

return getPropertyAsBool("Visible");

}



public void setMenuBar(boolean value)

{

setProperty(
"MenuBar", value);

}



public boolean isMenuBar()

{

return getPropertyAsBool("MenuBar");

}



public int getHWND()

{

return getPropertyAsInt("HWND");

}



public void navigate(String url)

{

ieComObject.CallFunction(
"Navigate"new Variant[] new Variant(url) });

}



public void quit()

{

ieComObject.CallFunction(
"Quit");

}


}


调用代码:

final IEAutomation ie = new IEAutomation();

ie.setVisible(
true);

ie.navigate(
"http://www.baidu.com");

ie.setMenuBar(
false);

int hwnd = ie.getHWND();

// composite为承载被启动程序的控件

OS.SetParent(hwnd, composite.handle);

// 窗口最大化

OS.SendMessage(hwnd, OS.WM_SYSCOMMAND, OS.SC_MAXIMIZE, 
0);

OS.SendMessage(hwnd, OS.WM_ACTIVATE, 
00);


composite.addDisposeListener(
new DisposeListener() {

public void widgetDisposed(DisposeEvent e)

{

//必须手动指定退出,否则会报异常

ie.quit();

}


}
);


我们高呼,SWT,你丫真牛,比CowNew还牛,呵呵。

posted on 2008-06-23 17:04 CowNew开源团队 阅读(2232) 评论(1)  编辑  收藏 所属分类: 技术类

评论

# re: SWT中调用Automation的方式 2008-06-23 21:59 DVD比价
能找到朋友写的CComObject类来访问Automation服务,真是件幸运的事情。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: