com 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +225 -0
- data/Rakefile +10 -0
- data/lib/com.rb +73 -0
- data/lib/com/error.rb +44 -0
- data/lib/com/events.rb +68 -0
- data/lib/com/instantiable.rb +135 -0
- data/lib/com/methodinvocationerror.rb +38 -0
- data/lib/com/object.rb +79 -0
- data/lib/com/pathname.rb +10 -0
- data/lib/com/patternerror.rb +20 -0
- data/lib/com/standarderror.rb +61 -0
- data/lib/com/version.rb +5 -0
- data/lib/com/win32ole.rb +19 -0
- data/lib/com/wrapper.rb +96 -0
- data/test/unit/com.rb +23 -0
- data/test/unit/com/error.rb +11 -0
- data/test/unit/com/events.rb +28 -0
- data/test/unit/com/instantiable.rb +94 -0
- data/test/unit/com/methodinvocationerror.rb +67 -0
- data/test/unit/com/object.rb +33 -0
- data/test/unit/com/pathname.rb +21 -0
- data/test/unit/com/standarderror.rb +27 -0
- metadata +178 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
Expectations do
|
4
|
+
expect COM::MethodInvocationError do
|
5
|
+
COM::Error.from(stub(:message => %{method
|
6
|
+
OLE error code:123abcDE in server
|
7
|
+
message
|
8
|
+
HRESULT error code:0x123abcDE
|
9
|
+
hresult message}))
|
10
|
+
end
|
11
|
+
|
12
|
+
expect 'method' do
|
13
|
+
COM::Error.from(stub(:message => %{method
|
14
|
+
OLE error code:123abcDE in server
|
15
|
+
message
|
16
|
+
HRESULT error code:0x123abcDE
|
17
|
+
hresult message})).method
|
18
|
+
end
|
19
|
+
|
20
|
+
expect 'server' do
|
21
|
+
COM::Error.from(stub(:message => %{method
|
22
|
+
OLE error code:123abcDE in server
|
23
|
+
message
|
24
|
+
HRESULT error code:0x123abcDE
|
25
|
+
hresult message})).server
|
26
|
+
end
|
27
|
+
|
28
|
+
expect 0x123abcDE do
|
29
|
+
COM::Error.from(stub(:message => %{method
|
30
|
+
OLE error code:123abcDE in server
|
31
|
+
message
|
32
|
+
HRESULT error code:0x123abcDE
|
33
|
+
hresult message})).code
|
34
|
+
end
|
35
|
+
|
36
|
+
expect 0x123abcDE do
|
37
|
+
COM::Error.from(stub(:message => %{method
|
38
|
+
OLE error code:123abcDE in server
|
39
|
+
message
|
40
|
+
HRESULT error code:0x123abcDE
|
41
|
+
hresult message})).hresult_code
|
42
|
+
end
|
43
|
+
|
44
|
+
expect 'hresult message' do
|
45
|
+
COM::Error.from(stub(:message => %{method
|
46
|
+
OLE error code:123abcDE in server
|
47
|
+
message
|
48
|
+
HRESULT error code:0x123abcDE
|
49
|
+
hresult message})).hresult_message
|
50
|
+
end
|
51
|
+
|
52
|
+
expect 'message' do
|
53
|
+
COM::Error.from(stub(:message => %{method
|
54
|
+
OLE error code:123abcDE in server
|
55
|
+
message
|
56
|
+
HRESULT error code:0x123abcDE
|
57
|
+
hresult message})).message
|
58
|
+
end
|
59
|
+
|
60
|
+
expect 'message' do
|
61
|
+
COM::Error.from(stub(:message => %{method
|
62
|
+
OLE error code:123abcDE in server
|
63
|
+
message
|
64
|
+
HRESULT error code:0x123abcDE
|
65
|
+
hresult message})).to_s
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
Expectations do
|
4
|
+
=begin
|
5
|
+
expect :result do
|
6
|
+
COM::Object.new(stub).with_properties({}){ :result }
|
7
|
+
end
|
8
|
+
|
9
|
+
expect 1 do
|
10
|
+
o = {:a => 1}
|
11
|
+
COM::Object.new(o).with_properties(:a => 2){ }
|
12
|
+
o[:a]
|
13
|
+
end
|
14
|
+
|
15
|
+
expect 1 do
|
16
|
+
o = {:a => 1}
|
17
|
+
COM::Object.new(o).with_properties(:a => 2){ raise } rescue nil
|
18
|
+
o[:a]
|
19
|
+
end
|
20
|
+
|
21
|
+
expect 2 do
|
22
|
+
o = {:a => 1}
|
23
|
+
v = nil
|
24
|
+
COM::Object.new(o).with_properties(:a => 2){ v = o[:a] } rescue nil
|
25
|
+
o[:a]
|
26
|
+
v
|
27
|
+
end
|
28
|
+
=end
|
29
|
+
|
30
|
+
expect StandardError do
|
31
|
+
COM::Object.new(stub).with_properties({}){ raise StandardError }
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
Expectations do
|
6
|
+
expect 'c:/a' do
|
7
|
+
stub(COM).charset{ 'UTF-8' }
|
8
|
+
Pathname('c:/a').to_com
|
9
|
+
end
|
10
|
+
|
11
|
+
expect 'c:/å' do
|
12
|
+
stub(COM).charset{ 'UTF-8' }
|
13
|
+
Pathname('c:/å').to_com
|
14
|
+
end
|
15
|
+
|
16
|
+
# ANSI and ISO-8859-1 å
|
17
|
+
expect 'c:/å' do
|
18
|
+
stub(COM).charset{ 'UTF-8' }
|
19
|
+
Pathname("c:/\xe5".force_encoding('Windows-1252')).to_com
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
Expectations do
|
4
|
+
expect NotImplementedError do
|
5
|
+
COM::Error.from(stub(:message => "\nHRESULT error code:0x80004001\n"))
|
6
|
+
end
|
7
|
+
|
8
|
+
expect NoMethodError do
|
9
|
+
COM::Error.from(stub(:message => "\nHRESULT error code:0x80020006\n"))
|
10
|
+
end
|
11
|
+
|
12
|
+
expect ArgumentError do
|
13
|
+
COM::Error.from(stub(:message => "\nHRESULT error code:0x8002000e\n"))
|
14
|
+
end
|
15
|
+
|
16
|
+
expect ArgumentError do
|
17
|
+
COM::Error.from(stub(:message => "\nHRESULT error code:0x800401e4\n"))
|
18
|
+
end
|
19
|
+
|
20
|
+
expect COM::OperationUnavailableError do
|
21
|
+
COM::Error.from(stub(:message => "\nHRESULT error code:0x800401e3\n"))
|
22
|
+
end
|
23
|
+
|
24
|
+
expect NameError.new('unknown COM server: A.B') do
|
25
|
+
COM::Error.from(stub(:message => "unknown OLE server: `A.B'\n HRESULT error code:0x800401f3\n"))
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: com
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nikolai Weibull
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: lookout
|
16
|
+
requirement: &14503188 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *14503188
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
requirement: &14502792 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.6.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *14502792
|
36
|
+
description: ! "# COM #\n\nCOM is an object-oriented wrapper around WIN32OLE. COM
|
37
|
+
makes it easy to add\nbehavior to WIN32OLE objects, making them easier to work with
|
38
|
+
from Ruby.\n\n\n## Usage ##\n\nUsing COM is rather straightforward. There’s basically
|
39
|
+
four concepts to keep\ntrack of:\n\n 1. COM objects\n 2. Instantiable COM objects\n
|
40
|
+
\ 3. COM events\n 4. COM errors\n\nLet’s look at each concept separately, using
|
41
|
+
the following example as a base.\n\n module Word end\n\n class Word::Application
|
42
|
+
< COM::Instantiable\n def without_interaction\n with_properties('displayalerts'
|
43
|
+
=> Word::WdAlertsNone){ yield }\n end\n\n def documents\n Word::Documents.new(com.documents)\n
|
44
|
+
\ end\n\n def quit(saving = Word::WdDoNotSaveChanges, *args)\n com.quit
|
45
|
+
saving, *args\n end\n end\n\n### COM Objects ###\n\nA COM::Object is a wrapper
|
46
|
+
around a COM object. It provides error\nspecialization, which is discussed later
|
47
|
+
and a few utility methods. You\ntypically use it to wrap COM objects that are returned
|
48
|
+
by COM methods. If we\ntake the example given in the introduction, Word::Documents
|
49
|
+
is a good\ncandidate:\n\n class Word::Documents < COM::Object\n DefaultOpenOptions
|
50
|
+
= {\n 'confirmconversions' => false,\n 'readonly' => true,\n 'addtorecentfiles'
|
51
|
+
=> false,\n 'visible' => false\n }.freeze\n def open(path, options
|
52
|
+
= {})\n options = DefaultOpenOptions.merge(options)\n options['filename']
|
53
|
+
= Pathname(path).to_com\n Word::Document.new(com.open(options))\n end\n
|
54
|
+
\ end\n\nHere we override the #open method to be a bit easier to use, providing
|
55
|
+
sane\ndefaults for COM interaction. Worth noting is the use of the #com method
|
56
|
+
to\naccess the actual COM object to invoke the #open method on it. Also note that\nWord::Document
|
57
|
+
is also a COM::Object.\n\nCOM::Object provides a convenience method called #with_properties,
|
58
|
+
which is\nused in the #without_interaction method above. It lets you set properties
|
59
|
+
on\nthe COM::Object during the duration of a block, restoring them after it exits\n(successfully
|
60
|
+
or with an error).\n\n\n### Instantiable COM Objects ###\n\nInstantiable COM objects
|
61
|
+
are COM objects that we can connect to and that can be\ncreated. The Word::Application
|
62
|
+
object can, for example, be created.\nInstantiable COM objects should inherit from
|
63
|
+
COM::Instantiable. Instantiable\nCOM objects can be told what program ID to use,
|
64
|
+
whether or not to allow\nconnecting to an already running object, and to load its
|
65
|
+
associated constants\nupon creation.\n\nThe program ID is used to determine what
|
66
|
+
instantiable COM object to connect to.\nBy default the name of the COM::Instantiable
|
67
|
+
class’ name is used, taking the\nlast two double-colon-separated components and
|
68
|
+
joining them with a dot. For\nWord::Application, the program ID is “Word.Application”.
|
69
|
+
\ The program ID can be\nset by using the .program_id method:\n\n class IDontCare::ForConventions
|
70
|
+
< COM::Instantiable\n program_id 'Word.Application'\n end\n\nThe program
|
71
|
+
ID can be accessed with the same method:\n\n Word::Application.program_id # ⇒
|
72
|
+
'Word.Application'\n\nConnecting to an already running COM object is not done by
|
73
|
+
default, but is\nsometimes desirable: the COM object might take a long time to create,
|
74
|
+
or some\ncommon state needs to be accessed. If the default for a certain instantiable\nCOM
|
75
|
+
object should be to connect, this can be done using the .connect method:\n\n class
|
76
|
+
Word::Application < COM::Instantiable\n connect\n end\n\nIf no running COM
|
77
|
+
object is available, then a new COM object will be created in\nits stead. Whether
|
78
|
+
or not a class uses the connection method can be queried\nwith the .connect? method:\n\n
|
79
|
+
\ Word::Application.connect? # ⇒ true\n\nWhether or not to load constants associated
|
80
|
+
with an instantiable COM object is\nset with the .constants method:\n\n class
|
81
|
+
Word::Application < COM::Instantiable\n constants true\n end\n\nand can
|
82
|
+
similarly be checked:\n\n Word::Application.constants? # ⇒ true\n\nConstants
|
83
|
+
are loaded by default.\n\nWhen an instance of the instantiable COM object is created,
|
84
|
+
a check is run to\nsee if constants should be loaded and whether or not they already
|
85
|
+
have been\nloaded. If they should be loaded and they haven’t already been loaded,\nthey’re,
|
86
|
+
you guessed it, loaded. The constants are added to the module\ncontaining the COM::Instantiable.
|
87
|
+
\ Thus, for Word::Application, the Word module\nwill contain all the constants.
|
88
|
+
\ Whether or not the constants have already been\nloaded can be checked with .constants_loaded?:\n\n
|
89
|
+
\ Word::Application.constants_loaded # ⇒ false\n\nThat concludes the class-level
|
90
|
+
methods.\n\nLet’s begin with the #connected? method among the instance-level methods.
|
91
|
+
\ This\nmethod queries whether or not this instance connected to an already running
|
92
|
+
COM\nobject:\n\n Word::Application.new.connected? # ⇒ false\n\nThis can be very
|
93
|
+
important in determining how shutdown of a COM object should\nbe done. If you connected
|
94
|
+
to an already COM object it might be foolish to shut\nit down if someone else is
|
95
|
+
using it.\n\nThe #initialize method takes a couple of options:\n\n * connect: whether
|
96
|
+
or not to connect to a running instance\n * constants: whether or not to load constants\n\nThese
|
97
|
+
options will, when given, override the class-level defaults.\n\n### Events ###\n\nCOM
|
98
|
+
events are easily dealt with:\n\n class Word::Application < COM::Instantiable\n
|
99
|
+
\ def initialize(options = {})\n super\n @events = COM::Events.new(com,
|
100
|
+
'ApplicationEvents',\n 'OnQuit')\n end\n\n
|
101
|
+
\ def quit(saving = Word::WdDoNotSaveChanges, *args)\n @events.observe('OnQuit',
|
102
|
+
proc{ com.quit saving, *args }) do\n yield if block_given?\n end\n
|
103
|
+
\ end\n end\n\nTo tell you the truth this API sucks and will most likely
|
104
|
+
be rewritten. The\nreason that it is the way it is is that WIN32OLE, which COM
|
105
|
+
wraps, sucks. It’s\nevent API is horrid and the implementation is buggy. It will
|
106
|
+
keep every\nregistered event block in memory for ever, freeing neither the blocks
|
107
|
+
nor the\nCOM objects that yield the events.\n\n### Errors ###\n\nAll errors generated
|
108
|
+
by COM methods descend from COM::Error, except for those\ncases where a Ruby error
|
109
|
+
already exists. The following HRESULT error codes are\nturned into Ruby errors:\n\n
|
110
|
+
\ HRESULT Error Code | Error Class\n -------------------|------------\n 0x80004001
|
111
|
+
\ | NotImplementedError\n 0x80020005 | TypeError\n 0x80020006 |
|
112
|
+
NoMethodError\n 0x8002000e | ArgumentError\n 0x800401e4 | ArgumentError\n\nThere
|
113
|
+
are also a couple of other HRESULT error codes that are turned into more\nspecific
|
114
|
+
errors than COM::Error:\n\n HRESULT Error Code | Error Class\n -------------------|------------\n
|
115
|
+
\ 0x80020003 | MemberNotFoundError\n 0x800401e3 | OperationUnavailableError\n\nFinally,
|
116
|
+
when a method results in any other error, a COM::MethodInvocationError\nwill be
|
117
|
+
raised, which can be queried for the specifics, specifically #message,\n #method,
|
118
|
+
#server, #code, #hresult_code, and #hresult_message.\n\n### Pathname ###\n\nThe
|
119
|
+
Pathname object receives an additional method, #to_com. This method is\nuseful
|
120
|
+
for when you want to pass a Pathname object to a COM method. Simply\ncall #to_com
|
121
|
+
to turn it into a String of the right encoding for COM:\n\n Word::Application.new.documents.open(Pathname('a.docx').to_com)\n
|
122
|
+
\ # ⇒ Word::Document\n\n\n## Installation ##\n\nInstall COM with\n\n % gem
|
123
|
+
install com\n\n\n## License ##\n\nYou may use, copy and redistribute this library
|
124
|
+
under the same [terms][1] as\nRuby itself.\n\n[1]: http://www.ruby-lang.org/en/LICENSE.txt\n\n\n##
|
125
|
+
Contributors ##\n\n * Nikolai Weibull\n"
|
126
|
+
email: now@bitwi.se
|
127
|
+
executables: []
|
128
|
+
extensions: []
|
129
|
+
extra_rdoc_files: []
|
130
|
+
files:
|
131
|
+
- lib/com/error.rb
|
132
|
+
- lib/com/events.rb
|
133
|
+
- lib/com/instantiable.rb
|
134
|
+
- lib/com/methodinvocationerror.rb
|
135
|
+
- lib/com/object.rb
|
136
|
+
- lib/com/pathname.rb
|
137
|
+
- lib/com/patternerror.rb
|
138
|
+
- lib/com/standarderror.rb
|
139
|
+
- lib/com/version.rb
|
140
|
+
- lib/com/win32ole.rb
|
141
|
+
- lib/com/wrapper.rb
|
142
|
+
- lib/com.rb
|
143
|
+
- test/unit/com/error.rb
|
144
|
+
- test/unit/com/events.rb
|
145
|
+
- test/unit/com/instantiable.rb
|
146
|
+
- test/unit/com/methodinvocationerror.rb
|
147
|
+
- test/unit/com/object.rb
|
148
|
+
- test/unit/com/pathname.rb
|
149
|
+
- test/unit/com/standarderror.rb
|
150
|
+
- test/unit/com.rb
|
151
|
+
- README
|
152
|
+
- Rakefile
|
153
|
+
homepage: http://github.com/now/com
|
154
|
+
licenses: []
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
none: false
|
168
|
+
requirements:
|
169
|
+
- - ! '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 1.8.10
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: COM is an object-oriented wrapper around WIN32OLE.
|
178
|
+
test_files: []
|