[Win32utils-devel] [ win32utils-Feature Requests-25792 ] Create a pure Ruby win32-ole library

Heesob Park phasis at gmail.com
Wed May 6 02:31:26 EDT 2009


2009/5/6  <noreply at rubyforge.org>:
> Feature Requests item #25792, was opened at 2009-05-05 17:29
> You can respond by visiting:
> http://rubyforge.org/tracker/?func=detail&atid=414&aid=25792&group_id=85
>
> Category: None
> Group: None
> Status: Open
> Resolution: None
> Priority: 3
> Submitted By: Daniel Berger (djberg96)
> Assigned to: Nobody (None)
> Summary: Create a pure Ruby win32-ole library
>
> Initial Comment:
> The current Win32OLE library is a C monster, has some bugs, and doesn't have a particularly good interface.
>
> I think a pure Ruby version would be easier to write and maintain, could have a more Ruby-ish interface, and could be installed as a gem instead of people having to wait for the next release of Ruby.
>
As you know, OLE Automation programming in C is more difficult than in C++.
Furthermore, OLE Automation programming in pure Ruby is a pain :)

Here is a literal translation of the sample code from
http://support.microsoft.com/kb/181473

require 'windows/com'
require 'windows/unicode'
require 'windows/error'
require 'windows/national'
require 'windows/msvcrt/buffer'

include Windows::COM
include Windows::Unicode
include Windows::National
include Windows::Error
include Windows::MSVCRT::Buffer

VariantInit = Win32::API.new('VariantInit', 'P', 'V', 'oleaut32')
OleUninitialize = Win32::API.new('OleUninitialize', 'V', 'V', 'ole32')

DISPID_UNKNOWN	   = -1
DISPID_VALUE	   = 0
DISPID_PROPERTYPUT = -3
DISPID_NEWENUM	   = -4
DISPID_EVALUATE	   = -5
DISPID_CONSTRUCTOR = -6
DISPID_DESTRUCTOR  = -7
DISPID_COLLECT	   = -8

DISPATCH_METHOD         = 0x1
DISPATCH_PROPERTYGET    = 0x2
DISPATCH_PROPERTYPUT    = 0x4
DISPATCH_PROPERTYPUTREF = 0x8

# Initialize OLE Libraries.
OleInitialize()
# Get CLSID for Excel.Application from registry.
clsid_ptr = 0.chr * 4
hr = CLSIDFromProgID(multi_to_wide("Excel.Application"), clsid_ptr)
clsid = clsid_ptr.unpack('L').first
if hr != S_OK
   raise StandardError, "Excel not registered."
end

# Start Excel97, Excel 2000, or Excel 2002 and get its IDispatch pointer.
pDisp = 0.chr * 4
IID_IDispatch =
[0x00020400,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')

hr = CoCreateInstance(clsid_ptr, nil, CLSCTX_LOCAL_SERVER,
					  IID_IDispatch, pDisp)
if hr != S_OK
   raise StandardError, "Couldn't start Excel."
end
pDisp = pDisp.unpack('L').first

# Get the 'visible' property's DISPID.
ucPtr = multi_to_wide("Visible")
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,28)
table = table.unpack('L*')
GetIDsOfNames = Win32::API::Function.new(table[5],'PPPLLP','L')	
dispID = 0.chr * 4
IID_NULL = [0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00].pack('LSSC8')
GetIDsOfNames.call(pDisp,IID_NULL,[ucPtr].pack('P'),1,LOCALE_USER_DEFAULT,dispID)
dispID = dispID.unpack('L').first
puts("DISPID for 'Visible' property = 0x%08x" % dispID)

# Initiate parameters to set visible property to true.
parm1 = [VT_I4,0,0,0,1,0].pack('SSSSLL')

# One argument.
# Handle special-case for property-puts!
dispidNamed = [DISPID_PROPERTYPUT].pack('L')
dispParams = [[parm1].pack('P').unpack('L').first,[dispidNamed].pack('P').unpack('L').first,1,1].pack('LLLL')

# Set 'visible' property to true.
Invoke = Win32::API::Function.new(table[6],'PLPLLPPPP','L')	
hr = Invoke.call(pDisp,
   dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
   DISPATCH_PROPERTYPUT | DISPATCH_METHOD,
   dispParams, nil, nil, nil)
if hr != S_OK
   raise StandardError, "IDispatch::Invoke() failed with %08x" % hr
end
puts "done."
gets

# Uninitialize OLE Libraries.
OleUninitialize.call()


Regards,

Park Heesob


More information about the win32utils-devel mailing list