winrm-elevated 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4572eca7fef32bcc8a6ca9176a7bdf6c9e2363d
4
- data.tar.gz: 64379eea77854e78f5693d2837f84366e985e667
3
+ metadata.gz: bf6b7a9059bf35fd4c3a836d039cbb0a7a66f755
4
+ data.tar.gz: 0dc1ab7fc96bbec50ac677c3423dc324a330c62e
5
5
  SHA512:
6
- metadata.gz: c46c73909c7cc83ed7b4290e57ad7ff7082d8673986dee063c31e5437f22460b136b26023a0d797afd201a5903dc7d257a609ba6a3ae12f9aa8745a08ac282fe
7
- data.tar.gz: 03c883e1fe01ecb29bb161c2cb8a09d5863ca3ec38a236f706a51b754d0f74935067c420f6b445a1ffa977bbfb0e64467aca7f5f2770f8fd1958e92abdc72d76
6
+ metadata.gz: 478b2550fa8e93024d9f9d8fefef28ed7513b236e517b793844393dc9df7111e5a2a47e9b0560abb4d423219ba92c24f1a09c3be50565ae1c47e227009f73ac2
7
+ data.tar.gz: 0ebb8820afbc2fca7faf59dbdfdf608821b519e8b1eacdb57cfd99dc907ea44016d0a924af372243e73e035b8c00724863c4df1bc9aa386fdc6ece98c0694ab0
@@ -1,17 +1,17 @@
1
- Style/FileName:
2
- Enabled: false
3
-
4
- Style/Encoding:
5
- Enabled: true
6
-
7
- Metrics/LineLength:
8
- Max: 120
9
-
10
- Metrics/MethodLength:
11
- Max: 20
12
-
13
- ClassLength:
14
- Max: 250
15
-
16
- Metrics/AbcSize:
17
- Max: 25
1
+ Style/FileName:
2
+ Enabled: false
3
+
4
+ Style/Encoding:
5
+ Enabled: true
6
+
7
+ Metrics/LineLength:
8
+ Max: 120
9
+
10
+ Metrics/MethodLength:
11
+ Max: 20
12
+
13
+ ClassLength:
14
+ Max: 250
15
+
16
+ Metrics/AbcSize:
17
+ Max: 25
@@ -1,10 +1,10 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.0
6
-
7
- # This prevents testing branches that are created just for PRs
8
- branches:
9
- only:
10
- - master
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+
7
+ # This prevents testing branches that are created just for PRs
8
+ branches:
9
+ only:
10
+ - master
data/README.md CHANGED
@@ -1,86 +1,99 @@
1
- # Runs PowerShell commands as elevated over Windows Remote Management (WinRM) via a scheduled task
2
- [![Gem Version](https://badge.fury.io/rb/winrm-elevated.svg)](http://badge.fury.io/rb/winrm-elevated)
3
-
4
- This gem allows you to break out of the magical WinRM constraints thus allowing to reach out to network shares and even install Windows updates, .NET, SQL Server etc.
5
-
6
- ## Running commands elevated
7
- ```ruby
8
- require 'winrm'
9
- require 'winrm-elevated'
10
-
11
- conn = WinRM::Connection.new(...
12
- conn.shell(:elevated) do |shell|
13
- shell.run('$PSVersionTable') do |stdout, stderr|
14
- STDOUT.print stdout
15
- STDERR.print stderr
16
- end
17
- end
18
- ```
19
-
20
- ### Impersonating a service account
21
- By passing a `nil` password, winrm-elevated will assume that the command should run as a service account:
22
- ```ruby
23
- require 'winrm'
24
- require 'winrm-elevated'
25
-
26
- conn = WinRM::Connection.new(...
27
- conn.shell(:elevated) do |shell|
28
- shell.username = 'System'
29
- shell.password = nil
30
- shell.run('$PSVersionTable') do |stdout, stderr|
31
- STDOUT.print stdout
32
- STDERR.print stderr
33
- end
34
- end
35
- ```
36
-
37
- ## How does it work?
38
-
39
- The gem works by creating a new logon session local to the Windows box by using a scheduled task. After this point WinRM is just used to read output from the scheduled task via a log file.
40
-
41
- 1. The command you'd like to run outside the WinRM context is saved to a temporary file.
42
- 2. This file is uploaded to the machine over WinRM.
43
- 3. A script is executed over WinRM and does the following:
44
- 1. Scheduled task is created which will execute your command and redirect stdout and stderr to a location known by elevated_shell.ps1.
45
- 2. The scheduled task is executed.
46
- 3. elevated_shell.ps1 polls the stdout and stderr log files and writes them back to WinRM. The script continues in this loop until the scheduled task is complete.
47
-
48
- ## Troubleshooting
49
-
50
- If you're having trouble, first of all its most likely a network or WinRM configuration
51
- issue. Take a look at the [WinRM gem troubleshooting](https://github.com/WinRb/WinRM#troubleshooting)
52
- first.
53
-
54
- ## Contributing
55
-
56
- 1. Fork it.
57
- 2. Create a branch (git checkout -b my_feature_branch)
58
- 3. Run the unit and integration tests (bundle exec rake integration)
59
- 4. Commit your changes (git commit -am "Added a sweet feature")
60
- 5. Push to the branch (git push origin my_feature_branch)
61
- 6. Create a pull requst from your branch into master (Please be sure to provide enough detail for us to cipher what this change is doing)
62
-
63
- ### Running the tests
64
-
65
- We use Bundler to manage dependencies during development.
66
-
67
- ```
68
- $ bundle install
69
- ```
70
-
71
- Once you have the dependencies, you can run the unit tests with `rake`:
72
-
73
- ```
74
- $ bundle exec rake spec
75
- ```
76
-
77
- To run the integration tests you will need a Windows box with the WinRM service properly configured. Its easiest to use the Vagrant Windows box in the Vagrantilfe of this repo.
78
-
79
- 1. Create a Windows VM with WinRM configured (see above).
80
- 2. Copy the config-example.yml to config.yml - edit this file with your WinRM connection details.
81
- 3. Run `bundle exec rake integration`
82
-
83
- ## WinRM-elevated Authors
84
- * Shawn Neal (https://github.com/sneal)
85
-
86
- [Contributors](https://github.com/WinRb/winrm-elevated/graphs/contributors)
1
+ # Runs PowerShell commands as elevated over Windows Remote Management (WinRM) via a scheduled task
2
+ [![Gem Version](https://badge.fury.io/rb/winrm-elevated.svg)](http://badge.fury.io/rb/winrm-elevated)
3
+
4
+ This gem allows you to break out of the magical WinRM constraints thus allowing to reach out to network shares and even install Windows updates, .NET, SQL Server etc.
5
+
6
+ ## Running commands elevated
7
+ ```ruby
8
+ require 'winrm'
9
+ require 'winrm-elevated'
10
+
11
+ conn = WinRM::Connection.new(...
12
+ conn.shell(:elevated) do |shell|
13
+ shell.run('$PSVersionTable') do |stdout, stderr|
14
+ STDOUT.print stdout
15
+ STDERR.print stderr
16
+ end
17
+ end
18
+ ```
19
+
20
+ ### Impersonating a service account
21
+ By passing a `nil` password, winrm-elevated will assume that the command should run as a service account:
22
+ ```ruby
23
+ require 'winrm'
24
+ require 'winrm-elevated'
25
+
26
+ conn = WinRM::Connection.new(...
27
+ conn.shell(:elevated) do |shell|
28
+ shell.username = 'System'
29
+ shell.password = nil
30
+ shell.run('$PSVersionTable') do |stdout, stderr|
31
+ STDOUT.print stdout
32
+ STDERR.print stderr
33
+ end
34
+ end
35
+ ```
36
+
37
+ ### Using an interactive task
38
+ By setting `interactive_logon` to `true`, the scheduled task will be configured to use an interactive logon allowing all command activity to be viewable from a RDP session if logged on as the same user as the winrm credentials:
39
+ ```ruby
40
+ require 'winrm'
41
+ require 'winrm-elevated'
42
+
43
+ conn = WinRM::Connection.new(...
44
+ conn.shell(:elevated) do |shell|
45
+ shell.interactive_logon = true
46
+ shell.run('notepad.exe')
47
+ end
48
+ ```
49
+
50
+ ## How does it work?
51
+
52
+ The gem works by creating a new logon session local to the Windows box by using a scheduled task. After this point WinRM is just used to read output from the scheduled task via a log file.
53
+
54
+ 1. The command you'd like to run outside the WinRM context is saved to a temporary file.
55
+ 2. This file is uploaded to the machine over WinRM.
56
+ 3. A script is executed over WinRM and does the following:
57
+ 1. Scheduled task is created which will execute your command and redirect stdout and stderr to a location known by elevated_shell.ps1.
58
+ 2. The scheduled task is executed.
59
+ 3. elevated_shell.ps1 polls the stdout and stderr log files and writes them back to WinRM. The script continues in this loop until the scheduled task is complete.
60
+
61
+ ## Troubleshooting
62
+
63
+ If you're having trouble, first of all its most likely a network or WinRM configuration
64
+ issue. Take a look at the [WinRM gem troubleshooting](https://github.com/WinRb/WinRM#troubleshooting)
65
+ first.
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it.
70
+ 2. Create a branch (git checkout -b my_feature_branch)
71
+ 3. Run the unit and integration tests (bundle exec rake integration)
72
+ 4. Commit your changes (git commit -am "Added a sweet feature")
73
+ 5. Push to the branch (git push origin my_feature_branch)
74
+ 6. Create a pull requst from your branch into master (Please be sure to provide enough detail for us to cipher what this change is doing)
75
+
76
+ ### Running the tests
77
+
78
+ We use Bundler to manage dependencies during development.
79
+
80
+ ```
81
+ $ bundle install
82
+ ```
83
+
84
+ Once you have the dependencies, you can run the unit tests with `rake`:
85
+
86
+ ```
87
+ $ bundle exec rake spec
88
+ ```
89
+
90
+ To run the integration tests you will need a Windows box with the WinRM service properly configured. Its easiest to use the Vagrant Windows box in the Vagrantilfe of this repo.
91
+
92
+ 1. Create a Windows VM with WinRM configured (see above).
93
+ 2. Copy the config-example.yml to config.yml - edit this file with your WinRM connection details.
94
+ 3. Run `bundle exec rake integration`
95
+
96
+ ## WinRM-elevated Authors
97
+ * Shawn Neal (https://github.com/sneal)
98
+
99
+ [Contributors](https://github.com/WinRb/winrm-elevated/graphs/contributors)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.1.0
@@ -1,39 +1,39 @@
1
- version: "master-{build}"
2
-
3
- os: Windows Server 2012 R2
4
- platform:
5
- - x64
6
-
7
- environment:
8
- winrm_user: test_user
9
- winrm_password: Pass@word1
10
-
11
- matrix:
12
- - ruby_version: "21"
13
- winrm_endpoint: http://localhost:5985/wsman
14
-
15
- clone_folder: c:\projects\winrm-elevated
16
- clone_depth: 1
17
- branches:
18
- only:
19
- - master
20
-
21
- install:
22
- - ps: net user /add $env:winrm_user $env:winrm_password
23
- - ps: net localgroup administrators $env:winrm_user /add
24
- - ps: winrm set winrm/config/client/auth '@{Basic="true"}'
25
- - ps: winrm set winrm/config/service/auth '@{Basic="true"}'
26
- - ps: winrm set winrm/config/service '@{AllowUnencrypted="true"}'
27
- - ps: $env:PATH="C:\Ruby$env:ruby_version\bin;$env:PATH"
28
- - ps: Write-Host $env:PATH
29
- - ps: ruby --version
30
- - ps: gem --version
31
- - ps: gem install bundler --quiet --no-ri --no-rdoc
32
- - ps: bundler --version
33
-
34
- build_script:
35
- - bundle install || bundle install || bundle install
36
-
37
- test_script:
38
- - SET SPEC_OPTS=--format progress
39
- - bundle exec rake integration
1
+ version: "master-{build}"
2
+
3
+ os: Windows Server 2012 R2
4
+ platform:
5
+ - x64
6
+
7
+ environment:
8
+ winrm_user: test_user
9
+ winrm_password: Pa$$word1
10
+
11
+ matrix:
12
+ - ruby_version: "21"
13
+ winrm_endpoint: http://localhost:5985/wsman
14
+
15
+ clone_folder: c:\projects\winrm-elevated
16
+ clone_depth: 1
17
+ branches:
18
+ only:
19
+ - master
20
+
21
+ install:
22
+ - ps: net user /add $env:winrm_user $env:winrm_password
23
+ - ps: net localgroup administrators $env:winrm_user /add
24
+ - ps: winrm set winrm/config/client/auth '@{Basic="true"}'
25
+ - ps: winrm set winrm/config/service/auth '@{Basic="true"}'
26
+ - ps: winrm set winrm/config/service '@{AllowUnencrypted="true"}'
27
+ - ps: $env:PATH="C:\Ruby$env:ruby_version\bin;$env:PATH"
28
+ - ps: Write-Host $env:PATH
29
+ - ps: ruby --version
30
+ - ps: gem --version
31
+ - ps: gem install bundler --quiet --no-ri --no-rdoc
32
+ - ps: bundler --version
33
+
34
+ build_script:
35
+ - bundle install || bundle install || bundle install
36
+
37
+ test_script:
38
+ - SET SPEC_OPTS=--format progress
39
+ - bundle exec rake integration
@@ -1,26 +1,31 @@
1
- # WinRM-Elevated Gem Changelog
2
-
3
- # 1.0.1
4
- - Fix to avoid profile conflicts
5
- - Fix inadequate Execution Policy errors
6
-
7
- # 1.0.0
8
- - Adjust to comply with winrm v2 APIs
9
- - Expose implementation as a class of `WinRM::Shells`
10
-
11
- # 0.4.0
12
- - Initialize `Elevated::Runner` with a `CommandExecutor` instead of a `WinrmService` client
13
- - Run commands from newer winrm executor
14
- - Use latest winrm-fs 0.4.2
15
- - Allow task to run as a service account
16
- - Provide an artificially long timeout to the task to keep the task from dying after 60 seconds
17
-
18
- # 0.3.0
19
- - [Name Powershell Script and Log Files Uniquely](https://github.com/WinRb/winrm-elevated/pull/6)
20
-
21
- # 0.2.0
22
- - [Only upload the elevated runner script once per winrm session](https://github.com/WinRb/winrm-elevated/pull/3)
23
- - Bump WinRM (1.5) and WinRM-fs (0.3.0) gem constraints
24
-
25
- # 0.1.0
26
- - Initial Release
1
+ # WinRM-Elevated Gem Changelog
2
+
3
+ # 1.1.0
4
+ - Allow tasks to be configured for interactive logon
5
+ - Fix broken credentials when they contain dollar signs
6
+ - Do not fail when temporary files cannot be deleted
7
+
8
+ # 1.0.1
9
+ - Fix to avoid profile conflicts
10
+ - Fix inadequate Execution Policy errors
11
+
12
+ # 1.0.0
13
+ - Adjust to comply with winrm v2 APIs
14
+ - Expose implementation as a class of `WinRM::Shells`
15
+
16
+ # 0.4.0
17
+ - Initialize `Elevated::Runner` with a `CommandExecutor` instead of a `WinrmService` client
18
+ - Run commands from newer winrm executor
19
+ - Use latest winrm-fs 0.4.2
20
+ - Allow task to run as a service account
21
+ - Provide an artificially long timeout to the task to keep the task from dying after 60 seconds
22
+
23
+ # 0.3.0
24
+ - [Name Powershell Script and Log Files Uniquely](https://github.com/WinRb/winrm-elevated/pull/6)
25
+
26
+ # 0.2.0
27
+ - [Only upload the elevated runner script once per winrm session](https://github.com/WinRb/winrm-elevated/pull/3)
28
+ - Bump WinRM (1.5) and WinRM-fs (0.3.0) gem constraints
29
+
30
+ # 0.1.0
31
+ - Initial Release
@@ -1,18 +1,18 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2015 Shawn Neal <sneal@sneal.net>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'winrm'
18
- require_relative 'winrm/shells/elevated'
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2015 Shawn Neal <sneal@sneal.net>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'winrm'
18
+ require_relative 'winrm/shells/elevated'
@@ -1,108 +1,116 @@
1
- $username = "<%= username %>"
2
- $password = "<%= password %>"
3
- $script_file = "<%= script_path %>"
4
-
5
- $pass_to_use = $password
6
- $logon_type = 1
7
- $logon_type_xml = "<LogonType>Password</LogonType>"
8
- if($pass_to_use.length -eq 0) {
9
- $pass_to_use = $null
10
- $logon_type = 5
11
- $logon_type_xml = ""
12
- }
13
-
14
- $task_name = "WinRM_Elevated_Shell"
15
- $out_file = [System.IO.Path]::GetTempFileName()
16
- $err_file = [System.IO.Path]::GetTempFileName()
17
-
18
- $task_xml = @'
19
- <?xml version="1.0" encoding="UTF-16"?>
20
- <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
21
- <Principals>
22
- <Principal id="Author">
23
- <UserId>{username}</UserId>
24
- {logon_type}
25
- <RunLevel>HighestAvailable</RunLevel>
26
- </Principal>
27
- </Principals>
28
- <Settings>
29
- <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
30
- <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
31
- <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
32
- <AllowHardTerminate>true</AllowHardTerminate>
33
- <StartWhenAvailable>false</StartWhenAvailable>
34
- <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
35
- <IdleSettings>
36
- <StopOnIdleEnd>false</StopOnIdleEnd>
37
- <RestartOnIdle>false</RestartOnIdle>
38
- </IdleSettings>
39
- <AllowStartOnDemand>true</AllowStartOnDemand>
40
- <Enabled>true</Enabled>
41
- <Hidden>false</Hidden>
42
- <RunOnlyIfIdle>false</RunOnlyIfIdle>
43
- <WakeToRun>false</WakeToRun>
44
- <ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
45
- <Priority>4</Priority>
46
- </Settings>
47
- <Actions Context="Author">
48
- <Exec>
49
- <Command>cmd</Command>
50
- <Arguments>{arguments}</Arguments>
51
- </Exec>
52
- </Actions>
53
- </Task>
54
- '@
55
-
56
- $arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file &gt; $out_file 2&gt;$err_file"
57
-
58
- $task_xml = $task_xml.Replace("{arguments}", $arguments)
59
- $task_xml = $task_xml.Replace("{username}", $username)
60
- $task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
61
-
62
- $schedule = New-Object -ComObject "Schedule.Service"
63
- $schedule.Connect()
64
- $task = $schedule.NewTask($null)
65
- $task.XmlText = $task_xml
66
- $folder = $schedule.GetFolder("\")
67
- $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null
68
-
69
- $registered_task = $folder.GetTask("\$task_name")
70
- $registered_task.Run($null) | Out-Null
71
-
72
- $timeout = 10
73
- $sec = 0
74
- while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
75
- Start-Sleep -s 1
76
- $sec++
77
- }
78
-
79
- function SlurpOutput($file, $cur_line, $out_type) {
80
- if (Test-Path $file) {
81
- get-content $file | select -skip $cur_line | ForEach {
82
- $cur_line += 1
83
- if ($out_type -eq 'err') {
84
- $host.ui.WriteErrorLine("$_")
85
- } else {
86
- $host.ui.WriteLine("$_")
87
- }
88
- }
89
- }
90
- return $cur_line
91
- }
92
-
93
- $err_cur_line = 0
94
- $out_cur_line = 0
95
- do {
96
- Start-Sleep -m 100
97
- $out_cur_line = SlurpOutput $out_file $out_cur_line 'out'
98
- $err_cur_line = SlurpOutput $err_file $err_cur_line 'err'
99
- } while (!($registered_task.state -eq 3))
100
-
101
- del $out_file
102
- del $err_file
103
- del $script_file
104
-
105
- $exit_code = $registered_task.LastTaskResult
106
- [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
107
-
108
- exit $exit_code
1
+ $username = '<%= username %>'
2
+ $password = '<%= password %>'
3
+ $script_file = '<%= script_path %>'
4
+
5
+ $interactive = '<%= interactive_logon %>'
6
+ $pass_to_use = $password
7
+ $logon_type = 1
8
+ $logon_type_xml = "<LogonType>Password</LogonType>"
9
+ if($pass_to_use.length -eq 0) {
10
+ $pass_to_use = $null
11
+ $logon_type = 5
12
+ $logon_type_xml = ""
13
+ }
14
+ if($interactive -eq 'true') {
15
+ $logon_type = 3
16
+ $logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
17
+ }
18
+
19
+ $task_name = "WinRM_Elevated_Shell"
20
+ $out_file = [System.IO.Path]::GetTempFileName()
21
+ $err_file = [System.IO.Path]::GetTempFileName()
22
+
23
+ $task_xml = @'
24
+ <?xml version="1.0" encoding="UTF-16"?>
25
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
26
+ <Principals>
27
+ <Principal id="Author">
28
+ <UserId>{username}</UserId>
29
+ {logon_type}
30
+ <RunLevel>HighestAvailable</RunLevel>
31
+ </Principal>
32
+ </Principals>
33
+ <Settings>
34
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
35
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
36
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
37
+ <AllowHardTerminate>true</AllowHardTerminate>
38
+ <StartWhenAvailable>false</StartWhenAvailable>
39
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
40
+ <IdleSettings>
41
+ <StopOnIdleEnd>false</StopOnIdleEnd>
42
+ <RestartOnIdle>false</RestartOnIdle>
43
+ </IdleSettings>
44
+ <AllowStartOnDemand>true</AllowStartOnDemand>
45
+ <Enabled>true</Enabled>
46
+ <Hidden>false</Hidden>
47
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
48
+ <WakeToRun>false</WakeToRun>
49
+ <ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
50
+ <Priority>4</Priority>
51
+ </Settings>
52
+ <Actions Context="Author">
53
+ <Exec>
54
+ <Command>cmd</Command>
55
+ <Arguments>{arguments}</Arguments>
56
+ </Exec>
57
+ </Actions>
58
+ </Task>
59
+ '@
60
+
61
+ $arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file &gt; $out_file 2&gt;$err_file"
62
+
63
+ $task_xml = $task_xml.Replace("{arguments}", $arguments)
64
+ $task_xml = $task_xml.Replace("{username}", $username)
65
+ $task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
66
+
67
+ $schedule = New-Object -ComObject "Schedule.Service"
68
+ $schedule.Connect()
69
+ $task = $schedule.NewTask($null)
70
+ $task.XmlText = $task_xml
71
+ $folder = $schedule.GetFolder("\")
72
+ $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null
73
+
74
+ $registered_task = $folder.GetTask("\$task_name")
75
+ $registered_task.Run($null) | Out-Null
76
+
77
+ $timeout = 10
78
+ $sec = 0
79
+ while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
80
+ Start-Sleep -s 1
81
+ $sec++
82
+ }
83
+
84
+ function SlurpOutput($file, $cur_line, $out_type) {
85
+ if (Test-Path $file) {
86
+ get-content $file | select -skip $cur_line | ForEach {
87
+ $cur_line += 1
88
+ if ($out_type -eq 'err') {
89
+ $host.ui.WriteErrorLine("$_")
90
+ } else {
91
+ $host.ui.WriteLine("$_")
92
+ }
93
+ }
94
+ }
95
+ return $cur_line
96
+ }
97
+
98
+ $err_cur_line = 0
99
+ $out_cur_line = 0
100
+ do {
101
+ Start-Sleep -m 100
102
+ $out_cur_line = SlurpOutput $out_file $out_cur_line 'out'
103
+ $err_cur_line = SlurpOutput $err_file $err_cur_line 'err'
104
+ } while (!($registered_task.state -eq 3))
105
+
106
+ # We'll make a best effort to clean these files
107
+ # But a reboot could possibly end the task while the process
108
+ # still runs and locks the file. If we can't delete we don't want to fail
109
+ try { Remove-Item $out_file -ErrorAction Stop } catch {}
110
+ try { Remove-Item $err_file -ErrorAction Stop } catch {}
111
+ try { Remove-Item $script_file -ErrorAction Stop } catch {}
112
+
113
+ $exit_code = $registered_task.LastTaskResult
114
+ [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
115
+
116
+ exit $exit_code