类 WIN32OLE

WIN32OLE

WIN32OLE 对象在 Ruby 中表示 OLE 自动化对象。

通过使用 WIN32OLE,您可以像 VBScript 一样访问 OLE 服务器。

以下是一个示例脚本。

require 'win32ole'

excel = WIN32OLE.new('Excel.Application')
excel.visible = true
workbook = excel.Workbooks.Add();
worksheet = workbook.Worksheets(1);
worksheet.Range("A1:D1").value = ["North","South","East","West"];
worksheet.Range("A2:B2").value = [5.2, 10];
worksheet.Range("C2").value = 8;
worksheet.Range("D2").value = 20;

range = worksheet.Range("A1:D2");
range.select
chart = workbook.Charts.Add;

workbook.saved = true;

excel.ActiveWorkbook.Close(0);
excel.Quit();

不幸的是,Win32OLE 不直接支持按引用传递的参数。相反,Win32OLE 提供了 WIN32OLE::ARGV 或 WIN32OLE_VARIANT 对象。如果您想获取按引用传递的参数的结果值,可以使用 WIN32OLE::ARGV 或 WIN32OLE_VARIANT。

oleobj.method(arg1, arg2, refargv3)
puts WIN32OLE::ARGV[2]   # the value of refargv3 after called oleobj.method

或者

refargv3 = WIN32OLE_VARIANT.new(XXX,
            WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX)
oleobj.method(arg1, arg2, refargv3)
p refargv3.value # the value of refargv3 after called oleobj.method.

常量

ARGV

在使用引用参数调用 OLE 方法后,您可以使用 ARGV 访问参数的值。

如果由 C#.NET 编写的 OLE(COM) 服务器的方法如下

void calcsum(int a, int b, out int c) {
    c = a + b;
}

那么,用于检索调用 calcsum 方法后参数 c 值的 Ruby OLE(COM) 客户端脚本如下

a = 10
b = 20
c = 0
comserver.calcsum(a, b, c)
p c # => 0
p WIN32OLE::ARGV # => [10, 20, 30]

您可以使用 WIN32OLE_VARIANT 对象来检索引用参数的值,而不是引用 WIN32OLE::ARGV

CP_ACP

ANSI 代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

CP_MACCP

2

CP_OEMCP

OEM 代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

CP_SYMBOL

符号代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

CP_THREAD_ACP

当前线程的 ANSI 代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

CP_UTF7

UTF-7 代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

CP_UTF8

UTF-8 代码页。参见 WIN32OLE.codepageWIN32OLE.codepage=

LOCALE_SYSTEM_DEFAULT

操作系统的默认区域设置。参见 WIN32OLE.localeWIN32OLE.locale=

LOCALE_USER_DEFAULT

用户或进程的默认区域设置。参见 WIN32OLE.localeWIN32OLE.locale=

VERSION

WIN32OLE 的版本字符串。

公共类方法

codepage 点击切换源代码

返回当前代码页。

WIN32OLE.codepage # => WIN32OLE::CP_ACP
static VALUE
fole_s_get_code_page(VALUE self)
{
    return RB_INT2FIX(cWIN32OLE_cp);
}
codepage = CP 点击切换源代码

设置当前代码页。 WIN32OLE.codepage 根据 Encoding.default_internal 初始化。如果 Encoding.default_internal 为 nil,则 WIN32OLE.codepage 根据 Encoding.default_external 初始化。

WIN32OLE.codepage = WIN32OLE::CP_UTF8
WIN32OLE.codepage = 65001
static VALUE
fole_s_set_code_page(VALUE self, VALUE vcp)
{
    UINT cp = RB_FIX2INT(vcp);
    set_ole_codepage(cp);
    /*
     * Should this method return old codepage?
     */
    return Qnil;
}
connect( ole ) -→ aWIN32OLE 点击切换源代码

返回正在运行的 OLE 自动化对象或 WIN32OLE 对象,从别名获取。第一个参数应该是 OLE 程序 ID 或类 ID 或别名。

WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
static VALUE
fole_s_connect(int argc, VALUE *argv, VALUE self)
{
    VALUE svr_name;
    VALUE others;
    HRESULT hr;
    CLSID   clsid;
    OLECHAR *pBuf;
    IDispatch *pDispatch;
    void *p;
    IUnknown *pUnknown;

    /* initialize to use OLE */
    ole_initialize();

    rb_scan_args(argc, argv, "1*", &svr_name, &others);
    StringValue(svr_name);

    /* get CLSID from OLE server name */
    pBuf = ole_vstr2wc(svr_name);
    hr = CLSIDFromProgID(pBuf, &clsid);
    if(FAILED(hr)) {
        hr = CLSIDFromString(pBuf, &clsid);
    }
    SysFreeString(pBuf);
    if(FAILED(hr)) {
        return ole_bind_obj(svr_name, argc, argv, self);
    }

    hr = GetActiveObject(&clsid, 0, &pUnknown);
    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError,
                  "OLE server `%s' not running", StringValuePtr(svr_name));
    }
    hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
    pDispatch = p;
    if(FAILED(hr)) {
        OLE_RELEASE(pUnknown);
        ole_raise(hr, eWIN32OLERuntimeError,
                  "failed to create WIN32OLE server `%s'",
                  StringValuePtr(svr_name));
    }

    OLE_RELEASE(pUnknown);

    return create_win32ole_object(self, pDispatch, argc, argv);
}
const_load( ole, mod = WIN32OLE) 点击切换源代码

将 OLE 自动化服务器的常量定义为 mod 的常量。第一个参数是 WIN32OLE 对象或类型库名称。如果省略第二个参数,则默认为 WIN32OLE。Ruby 常量变量名的第一个字母是大写,因此 WIN32OLE 对象的常量变量名是大写的。例如,Excel 的 ‘xlTop’ 常量在 WIN32OLE 中更改为 ‘XlTop’。如果常量变量的第一个字母不是 [A-Z],则该常量将定义为 CONSTANTS 哈希元素。

module EXCEL_CONST
end
excel = WIN32OLE.new('Excel.Application')
WIN32OLE.const_load(excel, EXCEL_CONST)
puts EXCEL_CONST::XlTop # => -4160
puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541

WIN32OLE.const_load(excel)
puts WIN32OLE::XlTop # => -4160

module MSO
end
WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO)
puts MSO::MsoLineSingle # => 1
static VALUE
fole_s_const_load(int argc, VALUE *argv, VALUE self)
{
    VALUE ole;
    VALUE klass;
    struct oledata *pole = NULL;
    ITypeInfo *pTypeInfo;
    ITypeLib *pTypeLib;
    unsigned int index;
    HRESULT hr;
    OLECHAR *pBuf;
    VALUE file;
    LCID    lcid = cWIN32OLE_lcid;

    rb_scan_args(argc, argv, "11", &ole, &klass);
    if (!RB_TYPE_P(klass, T_CLASS) &&
        !RB_TYPE_P(klass, T_MODULE) &&
        !RB_TYPE_P(klass, T_NIL)) {
        rb_raise(rb_eTypeError, "2nd parameter must be Class or Module");
    }
    if (rb_obj_is_kind_of(ole, cWIN32OLE)) {
        pole = oledata_get_struct(ole);
        hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
                                                  0, lcid, &pTypeInfo);
        if(FAILED(hr)) {
            ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
        }
        hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
        if(FAILED(hr)) {
            OLE_RELEASE(pTypeInfo);
            ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetContainingTypeLib");
        }
        OLE_RELEASE(pTypeInfo);
        if(!RB_TYPE_P(klass, T_NIL)) {
            ole_const_load(pTypeLib, klass, self);
        }
        else {
            ole_const_load(pTypeLib, cWIN32OLE, self);
        }
        OLE_RELEASE(pTypeLib);
    }
    else if(RB_TYPE_P(ole, T_STRING)) {
        file = typelib_file(ole);
        if (file == Qnil) {
            file = ole;
        }
        pBuf = ole_vstr2wc(file);
        hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
        SysFreeString(pBuf);
        if (FAILED(hr))
          ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
        if(!RB_TYPE_P(klass, T_NIL)) {
            ole_const_load(pTypeLib, klass, self);
        }
        else {
            ole_const_load(pTypeLib, cWIN32OLE, self);
        }
        OLE_RELEASE(pTypeLib);
    }
    else {
        rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance");
    }
    return Qnil;
}
create_guid 点击切换源代码

创建 GUID。

WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
static VALUE
fole_s_create_guid(VALUE self)
{
    GUID guid;
    HRESULT hr;
    OLECHAR bstr[80];
    int len = 0;
    hr = CoCreateGuid(&guid);
    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
    }
    len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
    if (len == 0) {
        rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
    }
    return ole_wc2vstr(bstr, FALSE);
}
locale → locale id. 点击切换源代码

返回当前区域设置 ID (lcid)。默认区域设置是 WIN32OLE::LOCALE_SYSTEM_DEFAULT

lcid = WIN32OLE.locale
static VALUE
fole_s_get_locale(VALUE self)
{
    return RB_INT2FIX(cWIN32OLE_lcid);
}
locale = lcid 点击切换源代码

设置当前区域设置 ID (lcid)。

WIN32OLE.locale = 1033 # set locale English(U.S)
obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
static VALUE
fole_s_set_locale(VALUE self, VALUE vlcid)
{
    LCID lcid = RB_FIX2INT(vlcid);
    if (lcid_installed(lcid)) {
        cWIN32OLE_lcid = lcid;
    } else {
        switch (lcid) {
        case LOCALE_SYSTEM_DEFAULT:
        case LOCALE_USER_DEFAULT:
            cWIN32OLE_lcid = lcid;
            break;
        default:
            rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
        }
    }
    return Qnil;
}
new(server, [host]) → WIN32OLE 对象 点击切换源代码
new(server, license: 'key') → WIN32OLE 对象

返回一个新的 WIN32OLE 对象(OLE 自动化对象)。第一个参数 server 指定 OLE 自动化服务器。第一个参数应该是 CLSID 或 PROGID。如果指定了第二个参数 host,则返回主机上的 OLE 自动化对象。如果提供了 :license 关键字参数,则使用 IClassFactory2::CreateInstanceLic 创建许可服务器的实例。

WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
static VALUE
fole_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE svr_name;
    VALUE host;
    VALUE others;
    VALUE opts;
    HRESULT hr;
    CLSID   clsid;
    OLECHAR *pBuf;
    OLECHAR *key_buf;
    IDispatch *pDispatch;
    IClassFactory2 * pIClassFactory2;
    void *p;
    static ID keyword_ids[1];
    VALUE kwargs[1];

    rb_call_super(0, 0);
    rb_scan_args(argc, argv, "11*:", &svr_name, &host, &others, &opts);

    StringValue(svr_name);
    if (!NIL_P(host)) {
        StringValue(host);
        return ole_create_dcom(self, svr_name, host, others);
    }

    /* get CLSID from OLE server name */
    pBuf  = ole_vstr2wc(svr_name);
    hr = CLSIDFromProgID(pBuf, &clsid);
    if(FAILED(hr)) {
        hr = CLSIDFromString(pBuf, &clsid);
    }
    SysFreeString(pBuf);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError,
                  "unknown OLE server: `%s'",
                  StringValuePtr(svr_name));
    }

    if (!keyword_ids[0]) {
        keyword_ids[0] = rb_intern_const("license");
    }
    rb_get_kwargs(opts, keyword_ids, 0, 1, kwargs);

    if (kwargs[0] == Qundef) {
        /* get IDispatch interface */
        hr = CoCreateInstance(
            &clsid,
            NULL,
            CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
            &IID_IDispatch,
            &p
        );
    } else {
        hr = CoGetClassObject(
            &clsid,
            CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
            NULL,
            &IID_IClassFactory2,
            (LPVOID)&pIClassFactory2
        );
        if (hr == S_OK) {
            key_buf = ole_vstr2wc(kwargs[0]);
            hr = pIClassFactory2->lpVtbl->CreateInstanceLic(pIClassFactory2, NULL, NULL, &IID_IDispatch, key_buf, &p);
            SysFreeString(key_buf);
            OLE_RELEASE(pIClassFactory2);
        }
    }
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError,
                  "failed to create WIN32OLE object from `%s'",
                  StringValuePtr(svr_name));
    }
    pDispatch = p;

    ole_set_member(self, pDispatch);
    return self;
}
ole_free(aWIN32OLE) -→ 数字 点击切换源代码

调用 WIN32OLE 对象的 Dispatch 接口的 Release 方法。您不应该使用此方法,因为此方法仅用于调试 WIN32OLE。返回值是 OLE 对象的引用计数。

static VALUE
fole_s_free(VALUE self, VALUE obj)
{
    ULONG n = 0;
    struct oledata * pole = NULL;
    pole = oledata_get_struct(obj);
    if(pole->pDispatch) {
        if (reference_count(pole) > 0) {
            n = OLE_RELEASE(pole->pDispatch);
        }
    }
    return RB_INT2NUM(n);
}
ole_reference_count(aWIN32OLE) -→ 数字 点击切换源代码

返回 WIN32OLE 对象的 Dispatch 接口的引用计数。您不应该使用此方法,因为此方法仅用于调试 WIN32OLE

static VALUE
fole_s_reference_count(VALUE self, VALUE obj)
{
    struct oledata * pole = NULL;
    pole = oledata_get_struct(obj);
    return RB_INT2NUM(reference_count(pole));
}
ole_show_help(obj [,helpcontext]) 点击切换源代码

显示帮助文件。第一个参数指定 WIN32OLE_TYPE 对象或 WIN32OLE_METHOD 对象或帮助文件。

excel = WIN32OLE.new('Excel.Application')
typeobj = excel.ole_type
WIN32OLE.ole_show_help(typeobj)
static VALUE
fole_s_show_help(int argc, VALUE *argv, VALUE self)
{
    VALUE target;
    VALUE helpcontext;
    VALUE helpfile;
    VALUE name;
    HWND  hwnd;
    rb_scan_args(argc, argv, "11", &target, &helpcontext);
    if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) ||
        rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) {
        helpfile = rb_funcall(target, rb_intern("helpfile"), 0);
        if(strlen(StringValuePtr(helpfile)) == 0) {
            name = rb_ivar_get(target, rb_intern("name"));
            rb_raise(rb_eRuntimeError, "no helpfile of `%s'",
                     StringValuePtr(name));
        }
        helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0);
    } else {
        helpfile = target;
    }
    if (!RB_TYPE_P(helpfile, T_STRING)) {
        rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)");
    }
    hwnd = ole_show_help(helpfile, helpcontext);
    if(hwnd == 0) {
        rb_raise(rb_eRuntimeError, "failed to open help file `%s'",
                 StringValuePtr(helpfile));
    }
    return Qnil;
}

公共实例方法

WIN32OLE[a1,a2,...] 点击切换源代码

返回由 a1、a2 等指定的集合的值。

dict = WIN32OLE.new('Scripting.Dictionary')
dict.add('ruby', 'Ruby')
puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')

备注:您不能使用此方法获取属性。

excel = WIN32OLE.new('Excel.Application')
# puts excel['Visible']  This is error !!!
puts excel.Visible # You should to use this style to get the property.
static VALUE
fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
{
    VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
    if (v == rb_eNoMethodError) {
        return rb_call_super(argc, argv);
    }
    return v;
}
WIN32OLE[a1, a2, ...]=val 点击切换源代码

将值设置到由 a1、a2 等指定的 WIN32OLE 对象。

dict = WIN32OLE.new('Scripting.Dictionary')
dict.add('ruby', 'RUBY')
dict['ruby'] = 'Ruby'
puts dict['ruby'] # => 'Ruby'

备注:您不能使用此方法设置属性值。

excel = WIN32OLE.new('Excel.Application')
# excel['Visible'] = true # This is error !!!
excel.Visible = true # You should to use this style to set the property.
static VALUE
fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
{
    VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
    if (v == rb_eNoMethodError) {
        return rb_call_super(argc, argv);
    }
    return v;
}
WIN32OLE#_getproperty(dispid, args, types) 点击切换源代码

运行早期绑定方法以获取属性。第一个参数指定调度 ID,第二个参数指定参数数组,第三个参数指定参数类型的数组。

excel = WIN32OLE.new('Excel.Application')
puts excel._getproperty(558, [], []) # same effect as puts excel.visible
static VALUE
fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
    return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
}
WIN32OLE#_invoke(dispid, args, types) 点击切换源代码

运行早期绑定方法。第一个参数指定调度 ID,第二个参数指定参数数组,第三个参数指定参数类型的数组。

excel = WIN32OLE.new('Excel.Application')
excel._invoke(302, [], []) #  same effect as excel.Quit
static VALUE
fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
    return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
}
WIN32OLE#_setproperty(dispid, args, types) 点击切换源代码

运行早期绑定方法来设置属性。第一个参数指定调度 ID,第二个参数指定参数数组,第三个参数指定参数类型的数组。

excel = WIN32OLE.new('Excel.Application')
excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
static VALUE
fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
    return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
}
WIN32OLE#each {|i|...} 点击切换源代码

迭代具有 IEnumVARIANT 接口的 OLE 集合中的每个项目。

excel = WIN32OLE.new('Excel.Application')
book = excel.workbooks.add
sheets = book.worksheets(1)
cells = sheets.cells("A1:A5")
cells.each do |cell|
  cell.value = 10
end
static VALUE
fole_each(VALUE self)
{
    LCID    lcid = cWIN32OLE_lcid;

    struct oledata *pole = NULL;

    unsigned int argErr;
    EXCEPINFO excepinfo;
    DISPPARAMS dispParams;
    VARIANT result;
    HRESULT hr;
    IEnumVARIANT *pEnum = NULL;
    void *p;

    RETURN_ENUMERATOR(self, 0, 0);

    VariantInit(&result);
    dispParams.rgvarg = NULL;
    dispParams.rgdispidNamedArgs = NULL;
    dispParams.cNamedArgs = 0;
    dispParams.cArgs = 0;
    memset(&excepinfo, 0, sizeof(excepinfo));

    pole = oledata_get_struct(self);
    hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM,
                                         &IID_NULL, lcid,
                                         DISPATCH_METHOD | DISPATCH_PROPERTYGET,
                                         &dispParams, &result,
                                         &excepinfo, &argErr);

    if (FAILED(hr)) {
        VariantClear(&result);
        ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
    }

    if (V_VT(&result) == VT_UNKNOWN) {
        hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
                                                        &IID_IEnumVARIANT,
                                                        &p);
        pEnum = p;
    } else if (V_VT(&result) == VT_DISPATCH) {
        hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
                                                         &IID_IEnumVARIANT,
                                                         &p);
        pEnum = p;
    }
    if (FAILED(hr) || !pEnum) {
        VariantClear(&result);
        ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
    }

    VariantClear(&result);
    rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
    return Qnil;
}
WIN32OLE#invoke(method, [arg1,...]) → method 的返回值。 点击切换源代码

运行 OLE 方法。第一个参数指定 OLE 自动化对象的 method 名称。其他参数指定 method 的参数。如果无法直接执行 method ,则使用此方法。

excel = WIN32OLE.new('Excel.Application')
excel.invoke('Quit')  # => same as excel.Quit
static VALUE
fole_invoke(int argc, VALUE *argv, VALUE self)
{
    VALUE v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
    if (v == rb_eNoMethodError) {
        return rb_call_super(argc, argv);
    }
    return v;
}
WIN32OLE#method_missing(id [,arg1, arg2, ...]) 点击切换源代码

调用 WIN32OLE#invoke 方法。

static VALUE
fole_missing(int argc, VALUE *argv, VALUE self)
{
    VALUE mid, org_mid, sym, v;
    const char* mname;
    long n;
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    mid = org_mid = argv[0];
    sym = rb_check_symbol(&mid);
    if (!NIL_P(sym)) mid = rb_sym2str(sym);
    mname = StringValueCStr(mid);
    if(!mname) {
        rb_raise(rb_eRuntimeError, "fail: unknown method or property");
    }
    n = RSTRING_LEN(mid);
    if(mname[n-1] == '=') {
        rb_check_arity(argc, 2, 2);
        argv[0] = rb_enc_associate(rb_str_subseq(mid, 0, n-1), cWIN32OLE_enc);

        return ole_propertyput(self, argv[0], argv[1]);
    }
    else {
        argv[0] = rb_enc_associate(rb_str_dup(mid), cWIN32OLE_enc);
        v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
        if (v == rb_eNoMethodError) {
            argv[0] = org_mid;
            return rb_call_super(argc, argv);
        }
        return v;
    }
}
methods(*args) 点击切换源代码

通过覆盖 Object#methods,WIN32OLE 可能与 did_you_mean gem 很好地配合使用。这属于实验性功能。

require 'win32ole'
dict = WIN32OLE.new('Scripting.Dictionary')
dict.Ade('a', 1)
#=> Did you mean?  Add
调用超类方法
# File win32ole/lib/win32ole.rb, line 21
def methods(*args)
  super + ole_methods_safely.map(&:name).map(&:to_sym)
end
WIN32OLE#ole_activex_initialize() → Qnil 点击切换源代码

通过调用 IPersistMemory::InitNew 初始化 WIN32OLE 对象(ActiveX 控件)。

在调用 OLE 方法之前,某些使用 MFC 创建的 ActiveX 控件应通过调用 IPersistXXX::InitNew 进行初始化。

如果您收到“HRESULT 错误代码:0x8000ffff 灾难性故障”异常,请在调用任何 ole_method 之前尝试使用此方法。

obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
obj.ole_activex_initialize
obj.method(...)
static VALUE
fole_activex_initialize(VALUE self)
{
    struct oledata *pole = NULL;
    IPersistMemory *pPersistMemory;
    void *p;

    HRESULT hr = S_OK;

    pole = oledata_get_struct(self);

    hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
    pPersistMemory = p;
    if (SUCCEEDED(hr)) {
        hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
        OLE_RELEASE(pPersistMemory);
        if (SUCCEEDED(hr)) {
            return Qnil;
        }
    }

    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
    }

    return Qnil;
}
WIN32OLE#ole_free 点击切换源代码

调用 WIN32OLE 对象的 Dispatch 接口的 Release 方法。通常,您不需要调用此方法,因为 Release 方法会在 WIN32OLE 对象被垃圾回收时自动调用。

static VALUE
fole_free(VALUE self)
{
    struct oledata *pole = NULL;
    pole = oledata_get_struct(self);
    OLE_FREE(pole->pDispatch);
    pole->pDispatch = NULL;
    return Qnil;
}
WIN32OLE#ole_func_methods 点击切换源代码

返回 WIN32OLE_METHOD 对象数组。数组的元素是 WIN32OLE 对象的属性(可设置)。

excel = WIN32OLE.new('Excel.Application')
properties = excel.ole_func_methods
static VALUE
fole_func_methods(VALUE self)
{
    return ole_methods( self, INVOKE_FUNC);
}
WIN32OLE#ole_get_methods 点击切换源代码

返回 WIN32OLE_METHOD 对象数组。数组的元素是 WIN32OLE 对象的属性(可获取)。

excel = WIN32OLE.new('Excel.Application')
properties = excel.ole_get_methods
static VALUE
fole_get_methods(VALUE self)
{
    return ole_methods( self, INVOKE_PROPERTYGET);
}
WIN32OLE#ole_method_help(method) 点击切换源代码

返回与第一个参数指定的 method 对应的 WIN32OLE_METHOD 对象。

excel = WIN32OLE.new('Excel.Application')
method = excel.ole_method_help('Quit')
static VALUE
fole_method_help(VALUE self, VALUE cmdname)
{
    ITypeInfo *pTypeInfo;
    HRESULT hr;
    struct oledata *pole = NULL;
    VALUE obj;

    SafeStringValue(cmdname);
    pole = oledata_get_struct(self);
    hr = typeinfo_from_ole(pole, &pTypeInfo);
    if(FAILED(hr))
        ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get ITypeInfo");

    obj = create_win32ole_method(pTypeInfo, cmdname);

    OLE_RELEASE(pTypeInfo);
    if (obj == Qnil)
        rb_raise(eWIN32OLERuntimeError, "not found %s",
                 StringValuePtr(cmdname));
    return obj;
}
也称为:ole_method_help
WIN32OLE#ole_method_help(method)

返回与第一个参数指定的 method 对应的 WIN32OLE_METHOD 对象。

excel = WIN32OLE.new('Excel.Application')
method = excel.ole_method_help('Quit')
别名:ole_method
WIN32OLE#ole_methods 点击切换源代码

返回 WIN32OLE_METHOD 对象数组。元素是 WIN32OLE 对象的 OLE 方法。

excel = WIN32OLE.new('Excel.Application')
methods = excel.ole_methods
static VALUE
fole_methods(VALUE self)
{
    return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
}
WIN32OLE#ole_type

返回 WIN32OLE_TYPE 对象。

excel = WIN32OLE.new('Excel.Application')
tobj = excel.ole_type
别名:ole_type
WIN32OLE#ole_put_methods 点击切换源代码

返回 WIN32OLE_METHOD 对象数组。数组的元素是 WIN32OLE 对象的属性(可设置)。

excel = WIN32OLE.new('Excel.Application')
properties = excel.ole_put_methods
static VALUE
fole_put_methods(VALUE self)
{
    return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
}
WIN32OLE#ole_query_interface(iid) → WIN32OLE object 点击切换源代码

返回 WIN32OLE 对象,用于由 iid 指定的特定调度或双重接口。

ie = WIN32OLE.new('InternetExplorer.Application')
ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
static VALUE
fole_query_interface(VALUE self, VALUE str_iid)
{
    HRESULT hr;
    OLECHAR *pBuf;
    IID iid;
    struct oledata *pole = NULL;
    IDispatch *pDispatch;
    void *p;

    pBuf  = ole_vstr2wc(str_iid);
    hr = CLSIDFromString(pBuf, &iid);
    SysFreeString(pBuf);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError,
                  "invalid iid: `%s'",
                  StringValuePtr(str_iid));
    }

    pole = oledata_get_struct(self);
    if(!pole->pDispatch) {
        rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
    }

    hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
                                                 &p);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLEQueryInterfaceError,
                  "failed to get interface `%s'",
                  StringValuePtr(str_iid));
    }

    pDispatch = p;
    return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
}
WIN32OLE#ole_respond_to?(method) → true 或 false 点击切换源代码

当 OLE 对象具有 OLE 方法时返回 true,否则返回 false。

ie = WIN32OLE.new('InternetExplorer.Application')
ie.ole_respond_to?("gohome") => true
static VALUE
fole_respond_to(VALUE self, VALUE method)
{
    struct oledata *pole = NULL;
    BSTR wcmdname;
    DISPID DispID;
    HRESULT hr;
    if(!RB_TYPE_P(method, T_STRING) && !RB_TYPE_P(method, T_SYMBOL)) {
        rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
    }
    if (RB_TYPE_P(method, T_SYMBOL)) {
        method = rb_sym2str(method);
    }
    pole = oledata_get_struct(self);
    wcmdname = ole_vstr2wc(method);
    hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
            &wcmdname, 1, cWIN32OLE_lcid, &DispID);
    SysFreeString(wcmdname);
    return SUCCEEDED(hr) ? Qtrue : Qfalse;
}
WIN32OLE#ole_type 点击切换源代码

返回 WIN32OLE_TYPE 对象。

excel = WIN32OLE.new('Excel.Application')
tobj = excel.ole_type
static VALUE
fole_type(VALUE self)
{
    ITypeInfo *pTypeInfo;
    HRESULT hr;
    struct oledata *pole = NULL;
    LCID  lcid = cWIN32OLE_lcid;
    VALUE type = Qnil;

    pole = oledata_get_struct(self);

    hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo );
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
    }
    type = ole_type_from_itypeinfo(pTypeInfo);
    OLE_RELEASE(pTypeInfo);
    if (type == Qnil) {
        rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
    }
    return type;
}
也称为:ole_obj_help
WIN32OLE#ole_typelib → The WIN32OLE_TYPELIB object 点击切换源代码

返回 WIN32OLE_TYPELIB 对象。该对象表示包含 WIN32OLE 对象的类型库。

excel = WIN32OLE.new('Excel.Application')
tlib = excel.ole_typelib
puts tlib.name  # -> 'Microsoft Excel 9.0 Object Library'
static VALUE
fole_typelib(VALUE self)
{
    struct oledata *pole = NULL;
    HRESULT hr;
    ITypeInfo *pTypeInfo;
    LCID  lcid = cWIN32OLE_lcid;
    VALUE vtlib = Qnil;

    pole = oledata_get_struct(self);
    hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
                                              0, lcid, &pTypeInfo);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
    }
    vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
    OLE_RELEASE(pTypeInfo);
    if (vtlib == Qnil) {
        rb_raise(rb_eRuntimeError, "failed to get type library info.");
    }
    return vtlib;
}
setproperty('property', [arg1, arg2,...] val) 点击切换源代码

设置 OLE 对象的属性。当您想使用参数设置属性时,可以使用此方法。

excel = WIN32OLE.new('Excel.Application')
excel.Visible = true
book = excel.workbooks.add
sheet = book.worksheets(1)
sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
static VALUE
fole_setproperty(int argc, VALUE *argv, VALUE self)
{
    VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
    if (v == rb_eNoMethodError) {
        return rb_call_super(argc, argv);
    }
    return v;
}

私有实例方法

ole_methods_safely() 点击切换源代码
# File win32ole/lib/win32ole.rb, line 27
def ole_methods_safely
  ole_methods
rescue WIN32OLEQueryInterfaceError
  []
end