ass_launcher 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,235 @@
1
+ [![Code Climate](https://codeclimate.com/github/leoniv/ass_launcher/badges/gpa.svg)](https://codeclimate.com/github/leoniv/ass_launcher)
2
+ [![Gem Version](https://badge.fury.io/rb/ass_launcher.svg)](https://badge.fury.io/rb/ass_launcher)
3
+
4
+ # AssLauncher
5
+
6
+ Ruby wrapper for 1C:Enterprise platform.
7
+
8
+ Goal of this to make easily and friendly writing scripts for development
9
+ and support lifecycle of 1C:Enterprise applications
10
+
11
+ `AssLauncher` is cross platform but **it full tested in `Cygwin` only!**. In `Windows` and `Linux` it works too.
12
+
13
+ In `Linux` don't support `OLE` feature. Don't known why I told it ;)
14
+
15
+
16
+ ## Quick start
17
+
18
+ ### Using `AssLauncher` as a library
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'ass_launcher'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install ass_launcher
33
+
34
+ For example, writing script which dumping 1C:Enterprise application
35
+
36
+ ```ruby
37
+ require 'ass_launcher'
38
+
39
+ include AssLauncher::Api
40
+
41
+ def main(dupm_path)
42
+ # Get wrapper for the thck client
43
+ thick_client = thicks('~> 8.3.8.0').last
44
+
45
+ # Fail if 1C:Enterprise installation not found
46
+ fail '1C:Enterprise not found' if thick_client.nil?
47
+
48
+ # Build designer command
49
+ designer = thick_client.command :designer do
50
+ _S 'enterprse_server/application_name'
51
+ dumpIB dupm_path
52
+ end
53
+
54
+ # Execute command
55
+ designer.run.wait
56
+
57
+ # Verify result
58
+ designer.process_holder.result.verify!
59
+ end
60
+
61
+ main ARGV[0]
62
+ ```
63
+
64
+ ### Command line utility `ass-launcher`
65
+
66
+ From version `0.3.0` `AssLauncher` provides console tool `ass-launcher` wich has
67
+ features:
68
+
69
+ - make new 1C:Enterprise application instance (aka information base)
70
+ - run 1C:Enterprise
71
+ - show help about 1C:Enterprise CLI parameters
72
+ - and some more
73
+
74
+ For more info about `ass-launcher` execute:
75
+
76
+ $ass-launcher --help
77
+
78
+
79
+ ## x86_64 1C:Enterprise for Windows
80
+
81
+ From `v8.3.9` 1C provides x86_64 arch platform for Windows.
82
+
83
+ For choosing which arch of 1C binary you need
84
+ `AssLauncher::Enterprise::BinaryWrapper` has `arch` property and some helpers
85
+ in `AssLauncher::Api` like a `*_i386` and `*_x86_64`.
86
+
87
+ For in-process OLE server `v83.ComConnector` aka `comcntr.dll`, arch of 1C
88
+ binary selects automaticaly in depends of Ruby arch.
89
+
90
+ On default using of `x86_64` 1C OLE server is forbidden (see below trouble).
91
+ For forcing to use `x86_64` OLE server set config flag `use_x86_64_ole`:
92
+
93
+ ```ruby
94
+ AssLauncher.configure do |conf|
95
+ conf.use_x86_64_ole = true
96
+ end
97
+ ```
98
+
99
+ ### Trouble with x86_64 in-process OLE server `v83.ComConnector`
100
+
101
+ `x86_64` in-process OLE server or Ruby `win32ole` is unstable now
102
+ and Ruby usually crashed while handling connect error.
103
+
104
+ Еxample for `x86_64` Ruby and 1C OLE server:
105
+
106
+ ```
107
+ $ruby -v
108
+ ruby 2.3.6p384 (2017-12-14 revision 9808) [x86_64-cygwin]
109
+
110
+ $pry
111
+
112
+ RbConfig::CONFIG['arch'] #=> "x86_64-cygwin"
113
+
114
+ require 'win32ole'
115
+
116
+ inproc = WIN32OLE.new('V83.COMConnector')
117
+
118
+ inproc.connect('invalid connection string')
119
+
120
+ ....*** buffer overflow detected ***: terminated
121
+ Aborted (стек памяти сброшен на диск)
122
+ ```
123
+
124
+ The same example for `i386` Ruby and 1C OLE server working fine:
125
+
126
+ ```
127
+ $ruby -v
128
+ ruby 2.3.6p384 (2017-12-14 revision 9808) [i386-cygwin]
129
+
130
+ $pry
131
+
132
+ RbConfig::CONFIG['arch'] #=> "i386-cygwin"
133
+
134
+ require 'win32ole'
135
+
136
+ inproc = WIN32OLE.new('V83.COMConnector')
137
+
138
+ inproc.connect('invalid connection string')
139
+
140
+ WIN32OLERuntimeError: (in OLE method `connect': )
141
+ OLE error code:80004005 in V83.COMConnector.1
142
+ Неверные или отсутствующие параметры соединения с информационной базой
143
+ HRESULT error code:0x80020009
144
+ Exception occurred.
145
+ from (pry):3:in `method_missing'
146
+ ```
147
+
148
+
149
+ ### Trouble with x86_64 local OLE servers `v83c.Application` and `v83.Application`
150
+
151
+ On theory, architecture of local OLE server isn't important for using them
152
+ in various Ruby architectures.
153
+
154
+ But it only theory. While in the run [exaples](examples/) in the `i386` Ruby
155
+ with `x86_64` local 1C OLE observes the unexpected behavior of 1C OLE
156
+ servers like a errors while to connect to information base:
157
+
158
+ ```
159
+ WIN32OLERuntimeError: (in OLE method `connect': )
160
+ OLE error code:0 in <Unknown>
161
+ <No Description>
162
+ HRESULT error code:0x80010108
163
+ The object invoked has disconnected from its clients.
164
+ /tmp/ass_launcher/lib/ass_launcher/enterprise/ole/win32ole.rb:87:in `method_missing'
165
+ /tmp/ass_launcher/lib/ass_launcher/enterprise/ole/win32ole.rb:87:in `call'
166
+ /tmp/ass_launcher/lib/ass_launcher/enterprise/ole/win32ole.rb:87:in `block in <class:WIN32OLE>'
167
+ /tmp/ass_launcher/lib/ass_launcher/enterprise/ole.rb:142:in `__try_open__'
168
+ /tmp/ass_launcher/lib/ass_launcher/enterprise/ole.rb:136:in `__open__'
169
+ /tmp/ass_launcher/examples/enterprise_ole_example.rb:131:in `block (4 levels) in <module:EnterpriseOle>'
170
+ ```
171
+
172
+ ## Usage
173
+
174
+ ### Examples
175
+
176
+ For more usage examples see [examples](examples/)
177
+
178
+ For beginning look at
179
+ [examples/enterprise_running_example.rb](examples/enterprise_running_example.rb)
180
+
181
+ All [examples](examples/) executable. For run them require
182
+ 1C:Enterprise platform version defined in `Examples::MIN_PLATFORM_VERSION`
183
+
184
+ Run all examples:
185
+
186
+ $rake run_examples
187
+
188
+ Or run specified example:
189
+
190
+ $rake run_examples TEST=examples/enterprise_running_example.rb
191
+
192
+ ### Troubles
193
+
194
+ Directory [examples/troubles](examples/troubles) contains examples
195
+ which describe troubles with executing 1C:Enterprise binary.
196
+
197
+ All [examples/troubles](examples/troubles) are executable too.
198
+
199
+ Run all troubles:
200
+
201
+ $rake run_trouble_examples
202
+
203
+ **Be careful to run [examples/troubles](examples/troubles)! Learn sources before run it.**
204
+
205
+ ## Help
206
+
207
+ If you have any questions open issue with `question` lable
208
+
209
+ ## Development
210
+
211
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
212
+
213
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
214
+
215
+ ### Development helper
216
+
217
+ `AssLauncher` include [bin/dev-helper](bin/dev-helper) utility for contributors.
218
+
219
+ $bin/dev-helper --help
220
+
221
+ ### Testing
222
+
223
+ #### Run unit tests:
224
+
225
+ $export SIMPLECOV=YES && rake test
226
+
227
+ Unit tests is isolated and doesn't require installation of 1C:Enterprise
228
+
229
+ #### Run examples:
230
+
231
+ Examples writed as `Minitest::Spec`. About run examples see above
232
+
233
+ ## Contributing
234
+
235
+ Bug reports and pull requests are welcome on GitHub at https://github.com/leoniv/ass_launcher.
@@ -0,0 +1,35 @@
1
+ # Примеры использования *AssLauncher*
2
+
3
+ В данном каталоге собраны примеры использования *AssLauncher* оформленные как
4
+ исполняемые тесты в формате [Mintest::Spec](https://github.com/seattlerb/minitest).
5
+ Примеры сгруппированы по фичам *AssLauncher*:
6
+
7
+ - файл [binary_wrappers_example.rb](binary_wrappers_example.rb) - примеры для
8
+ работы с различными видами клиентов платформы 1С
9
+ - файл [arguments_builder_example.rb](arguments_builder_example.rb) - примеры
10
+ работы с построителем аргументов для консольного запуска платформы 1С
11
+ - файл [connection_string_example.rb](connection_string_example.rb) - пример
12
+ работы со строкой соединения
13
+ - файл [create_infobase_example.rb](create_infobase_example.rb) - примеры
14
+ запуска платформы в режиме создания информационной базы
15
+ - файл [enterprise_ole_example.rb](enterprise_ole_example.rb) - примеры работы с
16
+ различными видами 1С OLE серверов
17
+ - файл [enterprise_out_example.rb](enterprise_out_example.rb) - пример захвата
18
+ вывода платформы
19
+ - файл [enterprise_running_example.rb](enterprise_running_example.rb) - базовые
20
+ примеры работы с различными клиентами платформы 1С
21
+ - файл [v8i_file_example.rb](v8i_file_example.rb) - пример работы с файлами v8i
22
+ - файл [webclient_example.rb](webclient_example.rb) - более подробный пример
23
+ работы с web клиентом
24
+
25
+ Для запуска примеров требуется установленная платформа 1С версии указанной
26
+ в константе `MIN_PLATFORM_VERSION` объявленной в файле
27
+ [example_helper.rb](example_helper.rb)
28
+
29
+ Запуск примеров:
30
+
31
+ $ bundler exec rake run_examples
32
+
33
+ Запуск с фильтром по имени спеки:
34
+
35
+ $ bundler exec rake run_examples TESTOPTS='--name=/здесь рег. выражение/i'
@@ -38,7 +38,7 @@ module Examples
38
38
  end
39
39
 
40
40
  after do
41
- FileUtils.rm_rf conns.file if File.exists?(conns.file)
41
+ FileUtils.rm_rf conns.file if File.exist?(conns.file)
42
42
  end
43
43
  end
44
44
  end
@@ -8,9 +8,9 @@ module Examples
8
8
  end
9
9
 
10
10
  # 1C:Enterprise provides three OLE servers:
11
- # v8x.Application - thick client standalone OLE server
12
- # v8xC.Application - thin client standalone OLE server
13
- # v8x.ComConnector - inproc ole server for connect to:
11
+ # v8x.Application - thick client local OLE server
12
+ # v8xC.Application - thin client local OLE server
13
+ # v8x.ComConnector - in-process OLE server for connect to:
14
14
  # - 1C:Enterprise application aka infobases
15
15
  # - 1C:Enterprise server agent
16
16
  # - 1C:Enterprise server working process
@@ -72,7 +72,7 @@ module Examples
72
72
  end
73
73
 
74
74
  describe 'Closing connection' do
75
- describe 'For standalone server it working perfect' do
75
+ describe 'For local server it working perfect' do
76
76
  extend AssLauncher::Api
77
77
  thick_app = ole(:thick, PLATFORM_VER)
78
78
 
@@ -97,16 +97,16 @@ module Examples
97
97
  end
98
98
  end
99
99
 
100
- describe 'For inproc server close connection working with restrictions' do
101
- # 1C inproc OLE servers haven't method for closing connection!
100
+ describe 'For in-process server close connection working with restrictions' do
101
+ # 1C in-process OLE servers haven't method for closing connection!
102
102
  # Connection keep alive while live ruby process.
103
103
  #
104
- # If in one ruby script we want to use inproc connection for some work
104
+ # If in one ruby script we want to use in-process connection for some work
105
105
  # do in the infobase and after them we want run other connection
106
106
  # or application or designer with flag of exclusive mode, in this case
107
- # opened inproc connection doesn't give us to do it
107
+ # opened in-process connection doesn't give us to do it
108
108
  #
109
- # AssLauncher provide feature for closing inproc connection but
109
+ # AssLauncher provide feature for closing in-process connection but
110
110
  # it working with restrictions.
111
111
  #
112
112
  # AssLauncher patching WIN32OLE and collect all ole objects which
@@ -116,14 +116,14 @@ module Examples
116
116
  # But it works not always. Connection keep alive while have any alive
117
117
  # WIN32OLE refs generated this connection
118
118
 
119
- describe 'Case when inproc server connection realy closed' do
119
+ describe 'Case when in-process server connection realy closed' do
120
120
  extend AssLauncher::Api
121
121
 
122
- # Get standalone ole server wrapper
122
+ # Get local ole server wrapper
123
123
  # It is service connector
124
124
  thick_app = ole(:thick, PLATFORM_VER)
125
125
 
126
- # Get inproc ole server wrapper
126
+ # Get in-process ole server wrapper
127
127
  # It object under test
128
128
  external = ole(:external, PLATFORM_VER)
129
129
 
@@ -164,10 +164,10 @@ module Examples
164
164
  # AssLauncher automatically register needed server version
165
165
  # and returns suitable wrapper.
166
166
  #
167
- # Registration version of ole server working correct only for standalone
167
+ # Registration version of ole server working correct only for local
168
168
  # servers such as Thin and Thick applications.
169
169
  #
170
- # We don't get new version of inproc ole server until old version
170
+ # We don't get new version of in-process ole server until old version
171
171
  # is loaded in memory
172
172
 
173
173
  it "Fail if 1C:Enterprise version doesn't instaled" do
@@ -179,7 +179,7 @@ module Examples
179
179
  e.message.must_match %r{Platform version `~> 999' not instaled}
180
180
  end
181
181
 
182
- describe 'Choosing version of standalone ole server working perfect' do
182
+ describe 'Choosing version of local ole server working perfect' do
183
183
  extend AssLauncher::Api
184
184
 
185
185
  thick_app = ole(:thick, PLATFORM_VER)
@@ -49,7 +49,7 @@ module Examples
49
49
  # will be passed to arguments builder instance
50
50
  connection_string "File=\"#{TMP::EMPTY_IB}\";"
51
51
  _L 'en'
52
- _Debug
52
+ _Debug :'-tcp'
53
53
  _DebuggerUrl 'tcp://localhost'
54
54
  end
55
55
 
@@ -53,7 +53,7 @@ module Examples
53
53
  end
54
54
 
55
55
  def exists?(name)
56
- File.exists? ib_file_path(name)
56
+ File.exist? ib_file_path(name)
57
57
  end
58
58
 
59
59
  def ib_file_path(name)
@@ -103,7 +103,7 @@ module Examples
103
103
  module TmpIb
104
104
  extend IbMaker
105
105
  def self.rm(name)
106
- FileUtils.rm_rf ibases[name] if File.exists? ibases[name]
106
+ FileUtils.rm_rf ibases[name] if File.exist? ibases[name]
107
107
  end
108
108
 
109
109
  def self.ibases_root
@@ -0,0 +1,20 @@
1
+ # Примеры проблем консольного запуска платформы 1С
2
+
3
+ Об общих проблемах скриптинга на платформе 1С можно прочесть
4
+ [здесь](https://github.com/leoniv/v8_circles_of_hell/blob/master/articles/круг_первый_скриптинг.md)
5
+
6
+ Некоторые проблемы консольного запуска платформы проиллюстрированы в форме
7
+ исполняемых тестов расположенных в этом каталоге. Тесты написаны в формате
8
+ [Mintest::Spec](https://github.com/seattlerb/minitest)
9
+
10
+ Для запуска примеров требуется установленная платформа 1С версии указанной
11
+ в константе `MIN_PLATFORM_VERSION` объявленной в файле
12
+ [../example_helper.rb](../example_helper.rb)
13
+
14
+ Но прежде чем запустить их изучите исходники.
15
+
16
+ Запуск используйте команду:
17
+
18
+ $bundler exec rake run_trouble_examples SHOW_STUPID_GUI=YES
19
+
20
+ И не забывайте закрывать окна 1С которые будут появляться в процессе тестов.
@@ -28,7 +28,7 @@ module Examples
28
28
  command.run.wait
29
29
 
30
30
  # Infobase which we want not exists
31
- File.exists?(conns.file).must_equal false
31
+ File.exist?(conns.file).must_equal false
32
32
 
33
33
  # But created infobase which we don't want
34
34
  skip 'It fixed from 1C:Enterprise 8.3.10'
@@ -38,7 +38,7 @@ module Examples
38
38
  created = Regexp.last_match[1]
39
39
  created.must_match(/InfoBase\D?/i)
40
40
 
41
- File.exists?(created).must_equal true
41
+ File.exist?(created).must_equal true
42
42
  end
43
43
 
44
44
  it 'Creates infobase which we want' do
@@ -62,11 +62,11 @@ module Examples
62
62
  /Creation of infobase \("File\s?=\s?'([^']+)/i
63
63
  created = Regexp.last_match[1]
64
64
  command.args[1].must_include created
65
- File.exists?(conns.file).must_equal true
65
+ File.exist?(conns.file).must_equal true
66
66
  end
67
67
 
68
68
  after do
69
- FileUtils.rm_rf conns.file if File.exists? conns.file
69
+ FileUtils.rm_rf conns.file if File.exist? conns.file
70
70
  end
71
71
 
72
72
  describe 'Solution with AssLauncher' do
@@ -88,7 +88,7 @@ module Examples
88
88
  .path(infobasedir).win_string
89
89
 
90
90
  before do
91
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
91
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
92
92
  end
93
93
 
94
94
  it "Fails if connection string double quoted" do
@@ -132,11 +132,11 @@ module Examples
132
132
  created = Regexp.last_match[1]
133
133
 
134
134
  conns.file.must_equal created
135
- File.exists?(conns.file).must_equal true
135
+ File.exist?(conns.file).must_equal true
136
136
  end
137
137
 
138
138
  after do
139
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
139
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
140
140
  end
141
141
  end
142
142
 
@@ -147,7 +147,7 @@ module Examples
147
147
  'example_create_infobase_with_right_slashes.ib')
148
148
 
149
149
  before do
150
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
150
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
151
151
  end
152
152
 
153
153
  describe 'Using single quote in connection string' do
@@ -199,12 +199,12 @@ module Examples
199
199
  end
200
200
 
201
201
  # Realy infobase not exists
202
- File.exists?(infobasedir).must_equal false
202
+ File.exist?(infobasedir).must_equal false
203
203
  end
204
204
  end
205
205
 
206
206
  after do
207
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
207
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
208
208
  end
209
209
  end
210
210
 
@@ -242,9 +242,9 @@ module Examples
242
242
  end
243
243
 
244
244
  # Realy infobase not exists
245
- File.exists?(infobasedir).must_equal false
245
+ File.exist?(infobasedir).must_equal false
246
246
  # Infobase created in the current directory created
247
- File.exists?(infobasedir.gsub('..','.')).must_equal true
247
+ File.exist?(infobasedir.gsub('..','.')).must_equal true
248
248
 
249
249
  end
250
250
  end
@@ -282,7 +282,7 @@ module Examples
282
282
  end
283
283
 
284
284
  after do
285
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
285
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
286
286
  end
287
287
  end
288
288
 
@@ -300,7 +300,7 @@ module Examples
300
300
 
301
301
  extend AssLauncher::Api
302
302
 
303
- File.exists?(root).must_equal true
303
+ File.exist?(root).must_equal true
304
304
  conns = cs_file file: infobasedir
305
305
 
306
306
  command = CLIENTS::THICK.command :createinfobase,
@@ -316,7 +316,7 @@ module Examples
316
316
 
317
317
  describe 'Using double quoted connection string' do
318
318
  it 'Infobase is created not where you need' do
319
- File.exists?(root).must_equal true
319
+ File.exist?(root).must_equal true
320
320
  conns = "File=\"#{infobasedir}\""
321
321
 
322
322
  command = CLIENTS::THICK.command :createinfobase,
@@ -342,16 +342,16 @@ module Examples
342
342
  end
343
343
 
344
344
  # Realy infobase not exists
345
- File.exists?(infobasedir).must_equal false
345
+ File.exist?(infobasedir).must_equal false
346
346
  end
347
347
  end
348
348
 
349
349
  before do
350
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
350
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
351
351
  end
352
352
 
353
353
  after do
354
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
354
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
355
355
  end
356
356
  end
357
357
 
@@ -366,7 +366,7 @@ module Examples
366
366
  it 'Solution with ConnectionString::File' do
367
367
  extend AssLauncher::Api
368
368
 
369
- File.exists?(root).must_equal true
369
+ File.exist?(root).must_equal true
370
370
  # ConnectionString::File converts connection string
371
371
  # for CREATEINFOBASE mode from double quoted:
372
372
  # 'File="pat";' to single quoted: "File='path';" string
@@ -384,12 +384,12 @@ module Examples
384
384
  created = Regexp.last_match[1]
385
385
 
386
386
  conns.file.must_equal created
387
- File.exists?(conns.file).must_equal true
387
+ File.exist?(conns.file).must_equal true
388
388
  end
389
389
 
390
390
  describe 'Using double quoted connection string' do
391
391
  it 'Fails CREATEINFOBASE' do
392
- File.exists?(root).must_equal true
392
+ File.exist?(root).must_equal true
393
393
  conns = "File=\"#{infobasedir}\""
394
394
 
395
395
  command = CLIENTS::THICK.command :createinfobase,
@@ -408,11 +408,11 @@ module Examples
408
408
  end
409
409
 
410
410
  before do
411
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
411
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
412
412
  end
413
413
 
414
414
  after do
415
- FileUtils.rm_rf infobasedir if File.exists? infobasedir
415
+ FileUtils.rm_rf infobasedir if File.exist? infobasedir
416
416
  end
417
417
  end
418
418
  end