test-kitchen 1.4.0.beta.2 → 1.4.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/features/kitchen_diagnose_command.feature +32 -0
- data/lib/kitchen/cli.rb +3 -0
- data/lib/kitchen/command/diagnose.rb +6 -1
- data/lib/kitchen/configurable.rb +48 -1
- data/lib/kitchen/diagnostic.rb +29 -0
- data/lib/kitchen/driver/base.rb +25 -0
- data/lib/kitchen/driver/dummy.rb +4 -0
- data/lib/kitchen/driver/proxy.rb +3 -0
- data/lib/kitchen/instance.rb +17 -0
- data/lib/kitchen/provisioner/base.rb +30 -1
- data/lib/kitchen/provisioner/chef_base.rb +7 -3
- data/lib/kitchen/provisioner/chef_solo.rb +4 -0
- data/lib/kitchen/provisioner/chef_zero.rb +5 -1
- data/lib/kitchen/provisioner/dummy.rb +4 -0
- data/lib/kitchen/provisioner/shell.rb +5 -0
- data/lib/kitchen/shell_out.rb +6 -2
- data/lib/kitchen/transport/base.rb +25 -0
- data/lib/kitchen/transport/dummy.rb +4 -0
- data/lib/kitchen/transport/ssh.rb +22 -1
- data/lib/kitchen/transport/winrm.rb +61 -90
- data/lib/kitchen/verifier/base.rb +30 -1
- data/lib/kitchen/verifier/busser.rb +4 -0
- data/lib/kitchen/verifier/dummy.rb +4 -0
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/configurable_spec.rb +35 -0
- data/spec/kitchen/diagnostic_spec.rb +53 -3
- data/spec/kitchen/driver/dummy_spec.rb +8 -0
- data/spec/kitchen/driver/proxy_spec.rb +4 -0
- data/spec/kitchen/driver/ssh_base_spec.rb +4 -0
- data/spec/kitchen/instance_spec.rb +75 -0
- data/spec/kitchen/provisioner/base_spec.rb +32 -6
- data/spec/kitchen/provisioner/chef_base_spec.rb +3 -2
- data/spec/kitchen/provisioner/chef_solo_spec.rb +10 -2
- data/spec/kitchen/provisioner/chef_zero_spec.rb +24 -2
- data/spec/kitchen/provisioner/dummy_spec.rb +8 -0
- data/spec/kitchen/provisioner/shell_spec.rb +10 -0
- data/spec/kitchen/shell_out_spec.rb +7 -0
- data/spec/kitchen/transport/ssh_spec.rb +90 -1
- data/spec/kitchen/transport/winrm_spec.rb +91 -11
- data/spec/kitchen/verifier/base_spec.rb +32 -6
- data/spec/kitchen/verifier/busser_spec.rb +8 -0
- data/spec/kitchen/verifier/dummy_spec.rb +8 -0
- data/support/chef_base_install_command.sh +183 -100
- data/test-kitchen.gemspec +1 -2
- metadata +11 -48
- data/lib/kitchen/transport/winrm/command_executor.rb +0 -188
- data/lib/kitchen/transport/winrm/file_transporter.rb +0 -454
- data/lib/kitchen/transport/winrm/logging.rb +0 -50
- data/lib/kitchen/transport/winrm/template.rb +0 -74
- data/lib/kitchen/transport/winrm/tmp_zip.rb +0 -187
- data/spec/kitchen/transport/winrm/command_executor_spec.rb +0 -400
- data/spec/kitchen/transport/winrm/file_transporter_spec.rb +0 -876
- data/spec/kitchen/transport/winrm/logging_spec.rb +0 -92
- data/spec/kitchen/transport/winrm/template_spec.rb +0 -51
- data/spec/kitchen/transport/winrm/tmp_zip_spec.rb +0 -132
- data/support/check_files.ps1.erb +0 -48
- data/support/decode_files.ps1.erb +0 -62
@@ -1,92 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
#
|
3
|
-
# Author:: Fletcher (<fnichol@nichol.ca>)
|
4
|
-
#
|
5
|
-
# Copyright (C) 2015, Fletcher Nichol
|
6
|
-
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
|
19
|
-
require_relative "../../../spec_helper"
|
20
|
-
|
21
|
-
require "kitchen"
|
22
|
-
require "kitchen/transport/winrm/logging"
|
23
|
-
|
24
|
-
require "logger"
|
25
|
-
|
26
|
-
class ILog
|
27
|
-
|
28
|
-
include Kitchen::Transport::Winrm::Logging
|
29
|
-
|
30
|
-
attr_reader :logger
|
31
|
-
|
32
|
-
def initialize(logger)
|
33
|
-
@logger = logger
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class CustomSubject < ILog
|
38
|
-
|
39
|
-
def log_subject
|
40
|
-
"Wham"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe Kitchen::Transport::Winrm::Logging do
|
45
|
-
|
46
|
-
let(:logged_output) { StringIO.new }
|
47
|
-
let(:logger) { Logger.new(logged_output) }
|
48
|
-
|
49
|
-
describe "#debug" do
|
50
|
-
|
51
|
-
it "nothing happens if logger is nil" do
|
52
|
-
ILog.new(nil).debug("I'm cool")
|
53
|
-
|
54
|
-
logged_output.string.must_equal ""
|
55
|
-
end
|
56
|
-
|
57
|
-
it "nothing happens if logger is above debug level" do
|
58
|
-
logger.level = Logger::INFO
|
59
|
-
ILog.new(logger).debug("I'm skipped")
|
60
|
-
|
61
|
-
logged_output.string.must_equal ""
|
62
|
-
end
|
63
|
-
|
64
|
-
it "message is logged on debug level" do
|
65
|
-
ILog.new(logger).debug("Debugging is fun")
|
66
|
-
|
67
|
-
logged_output.string.must_match debug_line("[ILog] Debugging is fun")
|
68
|
-
end
|
69
|
-
|
70
|
-
it "block is called and used for debug level" do
|
71
|
-
ILog.new(logger).debug { "Debugging is expensive" }
|
72
|
-
|
73
|
-
logged_output.string.must_match debug_line("[ILog] Debugging is expensive")
|
74
|
-
end
|
75
|
-
|
76
|
-
it "message is used over block" do
|
77
|
-
ILog.new(logger).debug("I win") { "I lose" }
|
78
|
-
|
79
|
-
logged_output.string.must_match debug_line("[ILog] I win")
|
80
|
-
end
|
81
|
-
|
82
|
-
it "custom log subject is used if overridden" do
|
83
|
-
CustomSubject.new(logger).debug("Bam")
|
84
|
-
|
85
|
-
logged_output.string.must_match debug_line("[Wham] Bam")
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def debug_line(msg)
|
90
|
-
%r{^D, .* : #{Regexp.escape(msg)}$}
|
91
|
-
end
|
92
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
#
|
3
|
-
# Author:: Fletcher (<fnichol@nichol.ca>)
|
4
|
-
#
|
5
|
-
# Copyright (C) 2015, Fletcher Nichol
|
6
|
-
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
|
19
|
-
require_relative "../../../spec_helper"
|
20
|
-
|
21
|
-
require "kitchen"
|
22
|
-
require "kitchen/transport/winrm/template"
|
23
|
-
|
24
|
-
describe Kitchen::Transport::Winrm::Template do
|
25
|
-
|
26
|
-
let(:path) { "/tmp/tmpl.erb" }
|
27
|
-
|
28
|
-
let(:template) do
|
29
|
-
Kitchen::Transport::Winrm::Template.new(path)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "#render returns the ERb template rendered with the hash context" do
|
33
|
-
with_fake_fs do
|
34
|
-
create_template(path)
|
35
|
-
template.render(:greeting => "Hello", :user => "Fletcher").
|
36
|
-
must_equal "Hello, Fletcher!"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
it "#% returns the ERb template rendered with the hash context" do
|
41
|
-
with_fake_fs do
|
42
|
-
create_template(path)
|
43
|
-
(template % { :greeting => "Hello", :user => "Fletcher" }).
|
44
|
-
must_equal "Hello, Fletcher!"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def create_template(path)
|
49
|
-
File.open(path, "wb") { |f| f.write("<%= greeting %>, <%= user %>!") }
|
50
|
-
end
|
51
|
-
end
|
@@ -1,132 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
#
|
3
|
-
# Author:: Fletcher (<fnichol@nichol.ca>)
|
4
|
-
#
|
5
|
-
# Copyright (C) 2015, Fletcher Nichol
|
6
|
-
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
|
19
|
-
require_relative "../../../spec_helper"
|
20
|
-
|
21
|
-
require "kitchen"
|
22
|
-
require "kitchen/transport/winrm/tmp_zip"
|
23
|
-
|
24
|
-
require "logger"
|
25
|
-
|
26
|
-
describe Kitchen::Transport::Winrm::TmpZip do
|
27
|
-
|
28
|
-
let(:logged_output) { StringIO.new }
|
29
|
-
let(:logger) { Logger.new(logged_output) }
|
30
|
-
|
31
|
-
let(:src_dir) do
|
32
|
-
tmpdir = Pathname.new(Dir.mktmpdir)
|
33
|
-
@tmpdirs << tmpdir
|
34
|
-
src_dir = tmpdir.join("src")
|
35
|
-
sub_dir = src_dir.join("veggies")
|
36
|
-
|
37
|
-
src_dir.mkpath
|
38
|
-
create_local_file(src_dir.join("apple.txt"), "appleapple")
|
39
|
-
create_local_file(src_dir.join("banana.txt"), "bananabanana")
|
40
|
-
create_local_file(src_dir.join("cherry.txt"), "cherrycherry")
|
41
|
-
sub_dir.mkpath
|
42
|
-
create_local_file(sub_dir.join("carrot.txt"), "carrotcarrot")
|
43
|
-
src_dir
|
44
|
-
end
|
45
|
-
|
46
|
-
let(:tmp_zip) { Kitchen::Transport::Winrm::TmpZip.new(src_dir, logger) }
|
47
|
-
|
48
|
-
before { @tmpdirs = [] }
|
49
|
-
|
50
|
-
after do
|
51
|
-
@tmpdirs.each(&:rmtree)
|
52
|
-
tmp_zip.unlink if tmp_zip.path
|
53
|
-
end
|
54
|
-
|
55
|
-
it "#path returns path to created zip file" do
|
56
|
-
tmp_zip.path.file?.must_equal true
|
57
|
-
end
|
58
|
-
|
59
|
-
it "#unlink removes the file" do
|
60
|
-
path = tmp_zip.path
|
61
|
-
path.file?.must_equal true
|
62
|
-
|
63
|
-
tmp_zip.unlink
|
64
|
-
|
65
|
-
path.file?.must_equal false
|
66
|
-
tmp_zip.path.must_equal nil
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "for a zip file containing the base directory" do
|
70
|
-
|
71
|
-
let(:tmp_zip) { Kitchen::Transport::Winrm::TmpZip.new(src_dir, logger) }
|
72
|
-
|
73
|
-
it "contains the input entries" do
|
74
|
-
zip = Zip::File.new(tmp_zip.path)
|
75
|
-
|
76
|
-
zip.map(&:name).sort.must_equal(
|
77
|
-
%W[src/apple.txt src/banana.txt src/cherry.txt src/veggies/carrot.txt]
|
78
|
-
)
|
79
|
-
zip.read("src/apple.txt").must_equal "appleapple"
|
80
|
-
zip.read("src/banana.txt").must_equal "bananabanana"
|
81
|
-
zip.read("src/cherry.txt").must_equal "cherrycherry"
|
82
|
-
zip.read("src/veggies/carrot.txt").must_equal "carrotcarrot"
|
83
|
-
end
|
84
|
-
|
85
|
-
it "logs to debug" do
|
86
|
-
tmp_zip
|
87
|
-
subject = "[TmpZip::#{tmp_zip.path}]"
|
88
|
-
logged = logged_output.string
|
89
|
-
|
90
|
-
logged.must_match debug_line("#{subject} +++ Adding src/apple.txt")
|
91
|
-
logged.must_match debug_line("#{subject} +++ Adding src/banana.txt")
|
92
|
-
logged.must_match debug_line("#{subject} +++ Adding src/cherry.txt")
|
93
|
-
logged.must_match debug_line("#{subject} +++ Adding src/veggies/carrot.txt")
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe "for a zip file containing entries under the base directory" do
|
98
|
-
|
99
|
-
let(:tmp_zip) { Kitchen::Transport::Winrm::TmpZip.new("#{src_dir}/", logger) }
|
100
|
-
|
101
|
-
it "contains the input entries" do
|
102
|
-
zip = Zip::File.new(tmp_zip.path)
|
103
|
-
|
104
|
-
zip.map(&:name).sort.must_equal(
|
105
|
-
%W[apple.txt banana.txt cherry.txt veggies/carrot.txt]
|
106
|
-
)
|
107
|
-
zip.read("apple.txt").must_equal "appleapple"
|
108
|
-
zip.read("banana.txt").must_equal "bananabanana"
|
109
|
-
zip.read("cherry.txt").must_equal "cherrycherry"
|
110
|
-
zip.read("veggies/carrot.txt").must_equal "carrotcarrot"
|
111
|
-
end
|
112
|
-
|
113
|
-
it "logs to debug" do
|
114
|
-
tmp_zip
|
115
|
-
subject = "[TmpZip::#{tmp_zip.path}]"
|
116
|
-
logged = logged_output.string
|
117
|
-
|
118
|
-
logged.must_match debug_line("#{subject} +++ Adding apple.txt")
|
119
|
-
logged.must_match debug_line("#{subject} +++ Adding banana.txt")
|
120
|
-
logged.must_match debug_line("#{subject} +++ Adding cherry.txt")
|
121
|
-
logged.must_match debug_line("#{subject} +++ Adding veggies/carrot.txt")
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def create_local_file(path, content)
|
126
|
-
path.open("wb") { |file| file.write(content) }
|
127
|
-
end
|
128
|
-
|
129
|
-
def debug_line(msg)
|
130
|
-
%r{^D, .* : #{Regexp.escape(msg)}$}
|
131
|
-
end
|
132
|
-
end
|
data/support/check_files.ps1.erb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
$hash_file = "<%= hash_file %>"
|
2
|
-
|
3
|
-
Function Cleanup($o) { if (($o -ne $null) -and ($o.GetType().GetMethod("Dispose") -ne $null)) { $o.Dispose() } }
|
4
|
-
|
5
|
-
Function Decode-Base64File($src, $dst) {
|
6
|
-
Try {
|
7
|
-
$in = (Get-Item $src).OpenRead()
|
8
|
-
$b64 = New-Object -TypeName System.Security.Cryptography.FromBase64Transform
|
9
|
-
$m = [System.Security.Cryptography.CryptoStreamMode]::Read
|
10
|
-
$d = New-Object -TypeName System.Security.Cryptography.CryptoStream $in,$b64,$m
|
11
|
-
Copy-Stream $d ($out = [System.IO.File]::OpenWrite($dst))
|
12
|
-
} Finally { Cleanup $in; Cleanup $out; Cleanup $d }
|
13
|
-
}
|
14
|
-
|
15
|
-
Function Copy-Stream($src, $dst) { $b = New-Object Byte[] 4096; while (($i = $src.Read($b, 0, $b.Length)) -ne 0) { $dst.Write($b, 0, $i) } }
|
16
|
-
|
17
|
-
Function Check-Files($h) {
|
18
|
-
return $h.GetEnumerator() | ForEach-Object {
|
19
|
-
$dst = Unresolve-Path $_.Key
|
20
|
-
New-Object psobject -Property @{
|
21
|
-
chk_exists = ($exists = Test-Path $dst -PathType Leaf)
|
22
|
-
src_md5 = ($sMd5 = $_.Value)
|
23
|
-
dst_md5 = ($dMd5 = if ($exists) { Get-MD5Sum $dst } else { $null })
|
24
|
-
chk_dirty = ($dirty = if ($sMd5 -ne $dMd5) { $true } else { $false })
|
25
|
-
verifies = if ($dirty -eq $false) { $true } else { $false }
|
26
|
-
}
|
27
|
-
} | Select-Object -Property chk_exists,src_md5,dst_md5,chk_dirty,verifies
|
28
|
-
}
|
29
|
-
|
30
|
-
Function Get-MD5Sum($src) {
|
31
|
-
Try {
|
32
|
-
$c = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
|
33
|
-
$bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
|
34
|
-
return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
|
35
|
-
} Finally { Cleanup $c; Cleanup $in }
|
36
|
-
}
|
37
|
-
|
38
|
-
Function Invoke-Input($in) {
|
39
|
-
$in = Unresolve-Path $in
|
40
|
-
Decode-Base64File $in ($decoded = "$($in).ps1")
|
41
|
-
$expr = Get-Content $decoded | Out-String
|
42
|
-
Remove-Item $in,$decoded -Force
|
43
|
-
return Invoke-Expression "$expr"
|
44
|
-
}
|
45
|
-
|
46
|
-
Function Unresolve-Path($p) { if ($p -eq $null) { return $null } else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) } }
|
47
|
-
|
48
|
-
Check-Files (Invoke-Input $hash_file) | ConvertTo-Csv -NoTypeInformation
|
@@ -1,62 +0,0 @@
|
|
1
|
-
$hash_file = "<%= hash_file %>"
|
2
|
-
|
3
|
-
Function Cleanup($o) { if (($o -ne $null) -and ($o.GetType().GetMethod("Dispose") -ne $null)) { $o.Dispose() } }
|
4
|
-
|
5
|
-
Function Decode-Base64File($src, $dst) {
|
6
|
-
Try {
|
7
|
-
$in = (Get-Item $src).OpenRead()
|
8
|
-
$b64 = New-Object -TypeName System.Security.Cryptography.FromBase64Transform
|
9
|
-
$m = [System.Security.Cryptography.CryptoStreamMode]::Read
|
10
|
-
$d = New-Object -TypeName System.Security.Cryptography.CryptoStream $in,$b64,$m
|
11
|
-
echo $null > $dst
|
12
|
-
Copy-Stream $d ($out = [System.IO.File]::OpenWrite($dst))
|
13
|
-
} Finally { Cleanup $in; Cleanup $out; Cleanup $d }
|
14
|
-
}
|
15
|
-
|
16
|
-
Function Copy-Stream($src, $dst) { $b = New-Object Byte[] 4096; while (($i = $src.Read($b, 0, $b.Length)) -ne 0) { $dst.Write($b, 0, $i) } }
|
17
|
-
|
18
|
-
Function Decode-Files($hash) {
|
19
|
-
$hash.GetEnumerator() | ForEach-Object {
|
20
|
-
$tmp = Unresolve-Path $_.Key
|
21
|
-
$sMd5 = (Get-Item $tmp).BaseName.Replace("b64-", "")
|
22
|
-
$tzip, $dst = (Unresolve-Path $_.Value["tmpzip"]), (Unresolve-Path $_.Value["dst"])
|
23
|
-
$decoded = if ($tzip -ne $null) { $tzip } else { $dst }
|
24
|
-
Decode-Base64File $tmp $decoded
|
25
|
-
Remove-Item $tmp -Force
|
26
|
-
$dMd5 = Get-MD5Sum $decoded
|
27
|
-
$verifies = if ($sMd5 -eq $dMd5) { $true } else { $false }
|
28
|
-
if ($tzip) { Unzip-File $tzip $dst; Remove-Item $tzip -Force }
|
29
|
-
New-Object psobject -Property @{ dst = $dst; verifies = $verifies; src_md5 = $sMd5; dst_md5 = $dMd5; tmpfile = $tmp; tmpzip = $tzip }
|
30
|
-
} | Select-Object -Property dst,verifies,src_md5,dst_md5,tmpfile,tmpzip
|
31
|
-
}
|
32
|
-
|
33
|
-
Function Get-MD5Sum($src) {
|
34
|
-
Try {
|
35
|
-
$c = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
|
36
|
-
$bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
|
37
|
-
return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
|
38
|
-
} Finally { Cleanup $c; Cleanup $in }
|
39
|
-
}
|
40
|
-
|
41
|
-
Function Invoke-Input($in) {
|
42
|
-
$in = Unresolve-Path $in
|
43
|
-
Decode-Base64File $in ($decoded = "$($in).ps1")
|
44
|
-
$expr = Get-Content $decoded | Out-String
|
45
|
-
Remove-Item $in,$decoded -Force
|
46
|
-
return Invoke-Expression "$expr"
|
47
|
-
}
|
48
|
-
|
49
|
-
Function Release-COM($o) { if ($o -ne $null) { [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($o) } }
|
50
|
-
|
51
|
-
Function Unresolve-Path($p) { if ($p -eq $null) { return $null } else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) } }
|
52
|
-
|
53
|
-
Function Unzip-File($src, $dst) {
|
54
|
-
$r = "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4"
|
55
|
-
if (($PSVersionTable.PSVersion.Major -ge 3) -and ((gp "$r\Full").Version -like "4.5*" -or (gp "$r\Client").Version -like "4.5*")) {
|
56
|
-
[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null; [System.IO.Compression.ZipFile]::ExtractToDirectory("$src", "$dst")
|
57
|
-
} else {
|
58
|
-
Try { $s = New-Object -ComObject Shell.Application; ($dp = $s.NameSpace($dst)).CopyHere(($z = $s.NameSpace($src)).Items(), 0x610) } Finally { Release-Com $s; Release-Com $z; Release-COM $dp }
|
59
|
-
}
|
60
|
-
}
|
61
|
-
|
62
|
-
Decode-Files (Invoke-Input $hash_file) | ConvertTo-Csv -NoTypeInformation
|