winrm-fs 0.4.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -2
- data/Gemfile +2 -0
- data/README.md +5 -12
- data/VERSION +1 -1
- data/Vagrantfile +1 -1
- data/appveyor.yml +2 -2
- data/changelog.md +2 -0
- data/lib/winrm-fs/core/file_transporter.rb +80 -93
- data/lib/winrm-fs/file_manager.rb +13 -13
- data/lib/winrm-fs/scripts/check_files.ps1.erb +17 -28
- data/lib/winrm-fs/scripts/checksum.ps1.erb +1 -1
- data/lib/winrm-fs/scripts/extract_files.ps1.erb +52 -0
- data/spec/config-example.yml +3 -5
- data/spec/integration/file_manager_spec.rb +10 -4
- data/spec/spec_helper.rb +5 -6
- data/winrm-fs.gemspec +1 -1
- metadata +7 -9
- data/lib/winrm-fs/scripts/decode_files.ps1.erb +0 -58
- data/spec/unit/file_transporter_spec.rb +0 -839
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e54c394c912274542248ea943f17cbf8b5801b7
|
4
|
+
data.tar.gz: 8fa0f2fead6f018f6f22cde2b1109c6fcda72fde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d11d2a9ea8715736c3dd9caedfc01ef96a954043896f15e9cd7e164f45b2d8222fe6d0151895c39969e1864347a788009cdd4f6ae83e2041dab02f57deca55d
|
7
|
+
data.tar.gz: 74dda7732bd2094e698a6651ef1cfc83fd64969c9cba111e8c75dc536133209d8c453a2ebe7eba321a9d049ea9e44d04904b89ba27a14bb1439391149abd997e
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,8 +8,8 @@ Files may be copied from the local machine to the winrm endpoint. Individual fil
|
|
8
8
|
```ruby
|
9
9
|
require 'winrm-fs'
|
10
10
|
|
11
|
-
|
12
|
-
file_manager = WinRM::FS::FileManager.new(
|
11
|
+
connection = WinRM::Connection.new(...
|
12
|
+
file_manager = WinRM::FS::FileManager.new(connection)
|
13
13
|
|
14
14
|
# upload file.txt from the current working directory
|
15
15
|
file_manager.upload('file.txt', 'c:/file.txt')
|
@@ -25,6 +25,9 @@ file_manager.upload([
|
|
25
25
|
], '$env:ProgramData')
|
26
26
|
```
|
27
27
|
|
28
|
+
### Optimizing WinRM settings
|
29
|
+
Since winrm-fs 1.0/winrm 2.0, files are uploaded using the PSRP protocol and transfer speeds are dramatically improved from previous versions. This is largely due to the fact that the size of chunks that can be transferred at one time are now governed by the `MaxEnvelopeSizekb` winrm configuration setting on the endpoint. This default to 500 on Windows 2012 R2 and 150 on Windows 2008 R2. You may experience much faster transfer rates on 2008 R2 by increasing this setting.
|
30
|
+
|
28
31
|
### Handling progress events
|
29
32
|
If you want to implement your own custom progress handling, you can pass a code
|
30
33
|
block and use the proggress data that `upload` yields to this block:
|
@@ -40,16 +43,6 @@ If you're having trouble, first of all its most likely a network or WinRM config
|
|
40
43
|
issue. Take a look at the [WinRM gem troubleshooting](https://github.com/WinRb/WinRM#troubleshooting)
|
41
44
|
first.
|
42
45
|
|
43
|
-
The most [common error](https://github.com/WinRb/winrm-fs/issues/1) with this gem is getting a 500 error because your maxConcurrentOperationsPerUser limit has been reached.
|
44
|
-
|
45
|
-
```
|
46
|
-
The WS-Management service cannot process the request. This user is allowed a
|
47
|
-
maximum number of 1500 concurrent operations, which has been exceeded. Close
|
48
|
-
existing operations for this user, or raise the quota for this user.
|
49
|
-
```
|
50
|
-
|
51
|
-
You can workaround this by increasing your operations per user quota.
|
52
|
-
|
53
46
|
## Contributing
|
54
47
|
|
55
48
|
1. Fork it.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/Vagrantfile
CHANGED
data/appveyor.yml
CHANGED
@@ -6,7 +6,7 @@ platform:
|
|
6
6
|
|
7
7
|
environment:
|
8
8
|
winrm_user: test_user
|
9
|
-
|
9
|
+
winrm_password: Pass@word1
|
10
10
|
|
11
11
|
matrix:
|
12
12
|
- ruby_version: "21"
|
@@ -19,7 +19,7 @@ branches:
|
|
19
19
|
- master
|
20
20
|
|
21
21
|
install:
|
22
|
-
- ps: net user /add $env:winrm_user $env:
|
22
|
+
- ps: net user /add $env:winrm_user $env:winrm_password
|
23
23
|
- ps: net localgroup administrators $env:winrm_user /add
|
24
24
|
- ps: winrm set winrm/config/client/auth '@{Basic="true"}'
|
25
25
|
- ps: winrm set winrm/config/service/auth '@{Basic="true"}'
|
data/changelog.md
CHANGED
@@ -41,8 +41,8 @@ module WinRM
|
|
41
41
|
# sessions being invoked which can be 2 orders of magnitude more
|
42
42
|
# expensive than vanilla CMD commands.
|
43
43
|
#
|
44
|
-
# This object is supported by
|
45
|
-
# depends on the `#
|
44
|
+
# This object is supported by a `PowerShell` instance as it
|
45
|
+
# depends on the `#run` API contract.
|
46
46
|
#
|
47
47
|
# An optional logger can be supplied, assuming it can respond to the
|
48
48
|
# `#debug` and `#debug?` messages.
|
@@ -50,12 +50,12 @@ module WinRM
|
|
50
50
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
51
51
|
# @author Matt Wrock <matt@mattwrock.com>
|
52
52
|
class FileTransporter
|
53
|
-
# Creates a FileTransporter given a
|
53
|
+
# Creates a FileTransporter given a PowerShell object.
|
54
54
|
#
|
55
|
-
# @param
|
56
|
-
def initialize(
|
57
|
-
@
|
58
|
-
@logger =
|
55
|
+
# @param shell [PowerShell] a winrm PowerShell object
|
56
|
+
def initialize(shell, opts = {})
|
57
|
+
@shell = shell
|
58
|
+
@logger = shell.logger
|
59
59
|
@id_generator = opts.fetch(:id_generator) { -> { SecureRandom.uuid } }
|
60
60
|
end
|
61
61
|
|
@@ -74,6 +74,7 @@ module WinRM
|
|
74
74
|
def upload(locals, remote)
|
75
75
|
files = nil
|
76
76
|
report = nil
|
77
|
+
remote = remote.to_s
|
77
78
|
|
78
79
|
elapsed1 = Benchmark.measure do
|
79
80
|
files = make_files_hash(Array(locals), remote)
|
@@ -91,7 +92,7 @@ module WinRM
|
|
91
92
|
end
|
92
93
|
|
93
94
|
elapsed3 = Benchmark.measure do
|
94
|
-
report =
|
95
|
+
report = extract_files(files)
|
95
96
|
merge_with_report!(files, report)
|
96
97
|
cleanup(files)
|
97
98
|
end
|
@@ -100,7 +101,7 @@ module WinRM
|
|
100
101
|
"Uploaded #{files.keys.size} items " \
|
101
102
|
"dirty_check: #{duration(elapsed1.real)} " \
|
102
103
|
"stream_files: #{duration(elapsed2.real)} " \
|
103
|
-
"
|
104
|
+
"extract: #{duration(elapsed3.real)} " \
|
104
105
|
)
|
105
106
|
|
106
107
|
[total_size, files]
|
@@ -108,12 +109,6 @@ module WinRM
|
|
108
109
|
|
109
110
|
private
|
110
111
|
|
111
|
-
# @return [Integer] the maximum number of bytes that can be supplied on
|
112
|
-
# a Windows CMD prompt without exceeded the maximum command line
|
113
|
-
# length
|
114
|
-
# @api private
|
115
|
-
MAX_ENCODED_WRITE = 8000
|
116
|
-
|
117
112
|
# @return [String] the Array pack template for Base64 encoding a stream
|
118
113
|
# of data
|
119
114
|
# @api private
|
@@ -128,9 +123,24 @@ module WinRM
|
|
128
123
|
# @api private
|
129
124
|
attr_reader :logger
|
130
125
|
|
131
|
-
# @return [Winrm::
|
126
|
+
# @return [Winrm::Shells::Powershell] a WinRM Powershell shell
|
127
|
+
# @api private
|
128
|
+
attr_reader :shell
|
129
|
+
|
130
|
+
# @return [Integer] the maximum number of bytes to send per request
|
131
|
+
# when streaming a file. This is optimized to send as much data
|
132
|
+
# as allowed in a single PSRP fragment
|
132
133
|
# @api private
|
133
|
-
|
134
|
+
def max_encoded_write
|
135
|
+
@max_encoded_write ||= begin
|
136
|
+
empty_command = WinRM::PSRP::MessageFactory.create_pipeline_message(
|
137
|
+
'00000000-0000-0000-0000-000000000000',
|
138
|
+
'00000000-0000-0000-0000-000000000000',
|
139
|
+
stream_command('')
|
140
|
+
)
|
141
|
+
shell.max_fragment_blob_size - empty_command.bytes.length
|
142
|
+
end
|
143
|
+
end
|
134
144
|
|
135
145
|
# Examines the files and corrects the file destination if it is
|
136
146
|
# targeting an existing folder. In this case, the destination path
|
@@ -198,9 +208,9 @@ module WinRM
|
|
198
208
|
# @api private
|
199
209
|
def check_files(files)
|
200
210
|
logger.debug 'Running check_files.ps1'
|
201
|
-
hash_file =
|
211
|
+
hash_file = check_files_ps_hash(files)
|
202
212
|
script = WinRM::FS::Scripts.render('check_files', hash_file: hash_file)
|
203
|
-
parse_response(
|
213
|
+
parse_response(shell.run(script))
|
204
214
|
end
|
205
215
|
|
206
216
|
# Constructs a collection of destination path/MD5 checksum pairs as a
|
@@ -236,63 +246,44 @@ module WinRM
|
|
236
246
|
end
|
237
247
|
end
|
238
248
|
|
239
|
-
#
|
240
|
-
# PowerShell hash table.
|
241
|
-
#
|
242
|
-
# @param hash [String] a String representation of a PowerShell hash
|
243
|
-
# table
|
244
|
-
# @return [String] the remote path to the temporary file
|
245
|
-
# @api private
|
246
|
-
def create_remote_hash_file(hash)
|
247
|
-
hash_file = "$env:TEMP\\hash-#{@id_generator.call}.txt"
|
248
|
-
hash.lines.each { |line| logger.debug line.chomp }
|
249
|
-
StringIO.open(hash) { |io| stream_upload(io, hash_file) }
|
250
|
-
hash_file
|
251
|
-
end
|
252
|
-
|
253
|
-
# Runs the decode_files PowerShell script against a collection of
|
249
|
+
# Runs the extract_files PowerShell script against a collection of
|
254
250
|
# temporary file/destination path pairs. The PowerShell script returns
|
255
251
|
# its results as a CSV-formatted report which is converted into a Ruby
|
256
|
-
# Hash. The script will not be invoked if there are no
|
252
|
+
# Hash. The script will not be invoked if there are no zip files
|
257
253
|
# present in the incoming files Hash.
|
258
254
|
#
|
259
255
|
# @param files [Hash] files hash, keyed by the local MD5 digest
|
260
256
|
# @return [Hash] a report hash, keyed by the local MD5 digest
|
261
257
|
# @api private
|
262
|
-
def
|
263
|
-
|
258
|
+
def extract_files(files)
|
259
|
+
extracted_files = extract_files_ps_hash(files)
|
264
260
|
|
265
|
-
if
|
266
|
-
logger.debug 'No remote files to
|
261
|
+
if extracted_files == ps_hash({})
|
262
|
+
logger.debug 'No remote files to extract, skipping'
|
267
263
|
{}
|
268
264
|
else
|
269
|
-
logger.debug 'Running
|
270
|
-
|
271
|
-
script = WinRM::FS::Scripts.render('decode_files', hash_file: hash_file)
|
265
|
+
logger.debug 'Running extract_files.ps1'
|
266
|
+
script = WinRM::FS::Scripts.render('extract_files', hash_file: extracted_files)
|
272
267
|
|
273
|
-
parse_response(
|
268
|
+
parse_response(shell.run(script))
|
274
269
|
end
|
275
270
|
end
|
276
271
|
|
277
272
|
# Constructs a collection of temporary file/destination path pairs for
|
278
|
-
# all
|
279
|
-
# PowerShell Hash Table.
|
280
|
-
# `"chk_dirty"` option set to `"True"` in the incoming files Hash.
|
273
|
+
# all zipped folders as a String representation of the contents of a
|
274
|
+
# PowerShell Hash Table.
|
281
275
|
#
|
282
276
|
# @param files [Hash] files hash, keyed by the local MD5 digest
|
283
277
|
# @return [String] the inner contents of a PowerShell Hash Table
|
284
278
|
# @api private
|
285
|
-
def
|
286
|
-
file_data = files.select
|
287
|
-
data['chk_dirty'] == 'True' || data.key?('tmpzip')
|
288
|
-
end
|
279
|
+
def extract_files_ps_hash(files)
|
280
|
+
file_data = files.select { |_, data| data.key?('tmpzip') }
|
289
281
|
|
290
|
-
|
291
|
-
result = file_data.map do |_, data|
|
282
|
+
result = file_data.map do |md5, data|
|
292
283
|
val = { 'dst' => data['dst'] }
|
293
284
|
val['tmpzip'] = data['tmpzip'] if data['tmpzip']
|
294
285
|
|
295
|
-
[
|
286
|
+
[md5, val]
|
296
287
|
end
|
297
288
|
|
298
289
|
ps_hash(Hash[result])
|
@@ -321,6 +312,7 @@ module WinRM
|
|
321
312
|
def make_files_hash(locals, remote)
|
322
313
|
hash = {}
|
323
314
|
locals.each do |local|
|
315
|
+
local = local.to_s
|
324
316
|
expanded = File.expand_path(local)
|
325
317
|
expanded += local[-1] if local.end_with?('/', '\\')
|
326
318
|
|
@@ -358,20 +350,6 @@ module WinRM
|
|
358
350
|
' ' * depth
|
359
351
|
end
|
360
352
|
|
361
|
-
# Parses CLIXML String into regular String (without any XML syntax).
|
362
|
-
# Inspired by https://github.com/WinRb/WinRM/issues/106.
|
363
|
-
#
|
364
|
-
# @param clixml [String] clixml text
|
365
|
-
# @return [String] parsed clixml into String
|
366
|
-
def clixml_to_s(clixml)
|
367
|
-
doc = REXML::Document.new(clixml)
|
368
|
-
text = doc.get_elements('//S').map(&:text).join
|
369
|
-
text.gsub(/_x(\h\h\h\h)_/) do
|
370
|
-
code = Regexp.last_match[1]
|
371
|
-
code.hex.chr
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
353
|
# Parses response of a PowerShell script or CMD command which contains
|
376
354
|
# a CSV-formatted document in the standard output stream.
|
377
355
|
#
|
@@ -380,22 +358,15 @@ module WinRM
|
|
380
358
|
# @return [Hash] report hash, keyed by the local MD5 digest
|
381
359
|
# @api private
|
382
360
|
def parse_response(output)
|
383
|
-
exitcode = output
|
361
|
+
exitcode = output.exitcode
|
384
362
|
stderr = output.stderr
|
385
|
-
if stderr.include?('The command line is too long')
|
386
|
-
# The powershell script which should result in `output` parameter
|
387
|
-
# is too long, remove some newlines, comments, etc from it.
|
388
|
-
fail StandardError, 'The command line is too long' \
|
389
|
-
' (powershell script is too long)'
|
390
|
-
end
|
391
|
-
pretty_stderr = clixml_to_s(stderr)
|
392
363
|
|
393
364
|
if exitcode != 0
|
394
365
|
fail FileTransporterFailed, "[#{self.class}] Upload failed " \
|
395
|
-
"(exitcode: #{exitcode})\n#{
|
396
|
-
elsif
|
366
|
+
"(exitcode: #{exitcode})\n#{stderr}"
|
367
|
+
elsif stderr != '\r\n' && stderr != ''
|
397
368
|
fail FileTransporterFailed, "[#{self.class}] Upload failed " \
|
398
|
-
"(exitcode: 0), but stderr present\n#{
|
369
|
+
"(exitcode: 0), but stderr present\n#{stderr}"
|
399
370
|
end
|
400
371
|
|
401
372
|
logger.debug 'Parsing CSV Response'
|
@@ -441,42 +412,59 @@ module WinRM
|
|
441
412
|
# the number of bytes transferred to the remote host
|
442
413
|
# @api private
|
443
414
|
def stream_upload(input_io, dest)
|
444
|
-
|
445
|
-
read_size = (MAX_ENCODED_WRITE.to_i / 4) * 3
|
415
|
+
read_size = ((max_encoded_write - dest.length) / 4) * 3
|
446
416
|
chunk, bytes = 1, 0
|
447
417
|
buffer = ''
|
448
|
-
|
418
|
+
shell.run(<<-EOS
|
419
|
+
$to = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("#{dest}")
|
420
|
+
$parent = Split-Path $to
|
421
|
+
if(!(Test-path $parent)) { mkdir $parent | Out-Null }
|
422
|
+
$fileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @(
|
423
|
+
$to,
|
424
|
+
[system.io.filemode]::Create,
|
425
|
+
[System.io.FileAccess]::Write,
|
426
|
+
[System.IO.FileShare]::ReadWrite
|
427
|
+
)
|
428
|
+
EOS
|
429
|
+
)
|
430
|
+
|
449
431
|
while input_io.read(read_size, buffer)
|
450
432
|
bytes += (buffer.bytesize / 3 * 4)
|
451
|
-
|
452
|
-
.insert(0, 'echo ').concat(%( >> "#{dest_cmd}")))
|
433
|
+
shell.run(stream_command([buffer].pack(BASE64_PACK)))
|
453
434
|
logger.debug "Wrote chunk #{chunk} for #{dest}" if chunk % 25 == 0
|
454
435
|
chunk += 1
|
455
436
|
yield bytes if block_given?
|
456
437
|
end
|
438
|
+
shell.run('$fileStream.Dispose()')
|
457
439
|
buffer = nil # rubocop:disable Lint/UselessAssignment
|
458
440
|
|
459
441
|
[chunk - 1, bytes]
|
460
442
|
end
|
461
443
|
|
462
|
-
|
444
|
+
def stream_command(encoded_bytes)
|
445
|
+
<<-EOS
|
446
|
+
$bytes=[Convert]::FromBase64String('#{encoded_bytes}')
|
447
|
+
$fileStream.Write($bytes, 0, $bytes.length)
|
448
|
+
EOS
|
449
|
+
end
|
450
|
+
|
451
|
+
# Uploads a local file.
|
463
452
|
#
|
464
453
|
# @param src [String] path to a local file
|
465
|
-
# @param
|
466
|
-
# host
|
454
|
+
# @param dest [String] path to the file on the remote host
|
467
455
|
# @return [Integer,Integer] the number of resulting upload chunks and
|
468
456
|
# the number of bytes transferred to the remote host
|
469
457
|
# @api private
|
470
|
-
def stream_upload_file(src,
|
471
|
-
logger.debug "Uploading #{src} to
|
458
|
+
def stream_upload_file(src, dest, &block)
|
459
|
+
logger.debug "Uploading #{src} to #{dest}"
|
472
460
|
chunks, bytes = 0, 0
|
473
461
|
elapsed = Benchmark.measure do
|
474
462
|
File.open(src, 'rb') do |io|
|
475
|
-
chunks, bytes = stream_upload(io,
|
463
|
+
chunks, bytes = stream_upload(io, dest, &block)
|
476
464
|
end
|
477
465
|
end
|
478
466
|
logger.debug(
|
479
|
-
"Finished uploading #{src} to
|
467
|
+
"Finished uploading #{src} to #{dest} " \
|
480
468
|
"(#{bytes.to_f / 1000} KB over #{chunks} chunks) " \
|
481
469
|
"in #{duration(elapsed.real)}"
|
482
470
|
)
|
@@ -496,9 +484,8 @@ module WinRM
|
|
496
484
|
files.each do |md5, data|
|
497
485
|
src = data.fetch('src_zip', data['src'])
|
498
486
|
if data['chk_dirty'] == 'True'
|
499
|
-
|
500
|
-
|
501
|
-
chunks, bytes = stream_upload_file(src, tmpfile) do |xfered|
|
487
|
+
response[md5] = { 'dest' => data['tmpzip'] || data['dst'] }
|
488
|
+
chunks, bytes = stream_upload_file(src, data['tmpzip'] || data['dst']) do |xfered|
|
502
489
|
yield data['src'], xfered
|
503
490
|
end
|
504
491
|
response[md5]['chunks'] = chunks
|
@@ -23,10 +23,10 @@ module WinRM
|
|
23
23
|
# Perform file transfer operations between a local machine and winrm endpoint
|
24
24
|
class FileManager
|
25
25
|
# Creates a new FileManager instance
|
26
|
-
# @param [
|
27
|
-
def initialize(
|
28
|
-
@
|
29
|
-
@logger =
|
26
|
+
# @param [WinRM::Connection] WinRM web connection client
|
27
|
+
def initialize(connection)
|
28
|
+
@connection = connection
|
29
|
+
@logger = connection.logger
|
30
30
|
end
|
31
31
|
|
32
32
|
# Gets the MD5 checksum of the specified file if it exists,
|
@@ -35,7 +35,7 @@ module WinRM
|
|
35
35
|
def checksum(path)
|
36
36
|
@logger.debug("checksum: #{path}")
|
37
37
|
script = WinRM::FS::Scripts.render('checksum', path: path)
|
38
|
-
@
|
38
|
+
@connection.shell(:powershell) { |e| e.run(script).stdout.chomp }
|
39
39
|
end
|
40
40
|
|
41
41
|
# Create the specifed directory recursively
|
@@ -44,7 +44,7 @@ module WinRM
|
|
44
44
|
def create_dir(path)
|
45
45
|
@logger.debug("create_dir: #{path}")
|
46
46
|
script = WinRM::FS::Scripts.render('create_dir', path: path)
|
47
|
-
@
|
47
|
+
@connection.shell(:powershell) { |e| e.run(script).exitcode == 0 }
|
48
48
|
end
|
49
49
|
|
50
50
|
# Deletes the file or directory at the specified path
|
@@ -53,7 +53,7 @@ module WinRM
|
|
53
53
|
def delete(path)
|
54
54
|
@logger.debug("deleting: #{path}")
|
55
55
|
script = WinRM::FS::Scripts.render('delete', path: path)
|
56
|
-
@
|
56
|
+
@connection.shell(:powershell) { |e| e.run(script).exitcode == 0 }
|
57
57
|
end
|
58
58
|
|
59
59
|
# Downloads the specified remote file to the specified local path
|
@@ -62,8 +62,8 @@ module WinRM
|
|
62
62
|
def download(remote_path, local_path)
|
63
63
|
@logger.debug("downloading: #{remote_path} -> #{local_path}")
|
64
64
|
script = WinRM::FS::Scripts.render('download', path: remote_path)
|
65
|
-
output = @
|
66
|
-
return false if output
|
65
|
+
output = @connection.shell(:powershell) { |e| e.run(script) }
|
66
|
+
return false if output.exitcode != 0
|
67
67
|
contents = output.stdout.gsub('\n\r', '')
|
68
68
|
out = Base64.decode64(contents)
|
69
69
|
IO.binwrite(local_path, out)
|
@@ -76,7 +76,7 @@ module WinRM
|
|
76
76
|
def exists?(path)
|
77
77
|
@logger.debug("exists?: #{path}")
|
78
78
|
script = WinRM::FS::Scripts.render('exists', path: path)
|
79
|
-
@
|
79
|
+
@connection.shell(:powershell) { |e| e.run(script).exitcode == 0 }
|
80
80
|
end
|
81
81
|
|
82
82
|
# Gets the current user's TEMP directory on the remote system, for example
|
@@ -84,7 +84,7 @@ module WinRM
|
|
84
84
|
# @return [String] Full path to the temp directory
|
85
85
|
def temp_dir
|
86
86
|
@guest_temp ||= begin
|
87
|
-
(@
|
87
|
+
(@connection.shell(:powershell) { |e| e.run('$env:TEMP') }).stdout.chomp.gsub('\\', '/')
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -107,8 +107,8 @@ module WinRM
|
|
107
107
|
# @yieldparam [String] Target path on the winrm endpoint
|
108
108
|
# @return [Fixnum] The total number of bytes copied
|
109
109
|
def upload(local_path, remote_path, &block)
|
110
|
-
@
|
111
|
-
file_transporter ||= WinRM::FS::Core::FileTransporter.new(
|
110
|
+
@connection.shell(:powershell) do |shell|
|
111
|
+
file_transporter ||= WinRM::FS::Core::FileTransporter.new(shell)
|
112
112
|
file_transporter.upload(local_path, remote_path, &block)[0]
|
113
113
|
end
|
114
114
|
end
|