Skip to content

Commit b208f3d

Browse files
SteveL-MSFTSteve Lee (POWERSHELL HE/HIM) (from Dev Box)
authored andcommitted
fix build script and handle input to scripts
1 parent cc6260e commit b208f3d

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

build.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ if (!$SkipBuild) {
430430
Copy-Item "*.dsc.resource.json" $target -Force -ErrorAction Ignore
431431
}
432432
else { # don't copy WindowsPowerShell resource manifest
433-
Copy-Item "*.dsc.resource.json" $target -Exclude 'windowspowershell.dsc.resource.json' -Force -ErrorAction Ignore
433+
$exclude = @('windowspowershell.dsc.resource.json', 'winpsscript.dsc.resource.json')
434+
Copy-Item "*.dsc.resource.json" $target -Exclude $exclude -Force -ErrorAction Ignore
434435
}
435436

436437
# be sure that the files that should be executable are executable

resources/PSScript/psscript.dsc.resource.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
"exitCodes": {
5252
"0": "Success",
5353
"1": "PowerShell script execution failed",
54-
"2": "PowerShell exception occurred"
54+
"2": "PowerShell exception occurred",
55+
"3": "Script had errors"
5556
},
5657
"schema": {
5758
"embedded": {

resources/PSScript/psscript.ps1

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ param(
99
[string]$jsonInput
1010
)
1111

12-
$traceQueue = [System.Collections.Queue]::new()
12+
$traceQueue = [System.Collections.Concurrent.ConcurrentQueue[object]]::new()
1313

1414
function Write-DscTrace {
1515
param(
@@ -57,57 +57,90 @@ if ($null -eq $script) {
5757
exit 0
5858
}
5959

60+
# use AST to see if script has param block, if any errors exit with error message
61+
$errors = $null
62+
$tokens = $null
63+
$ast = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$errors)
64+
if ($errors.Count -gt 0) {
65+
$errorMessage = $errors | ForEach-Object { $_.ToString() }
66+
Write-DscTrace -Now -Level Error -Message "Script has syntax errors: $errorMessage"
67+
exit 3
68+
}
69+
70+
$paramName = if ($ast.ParamBlock -ne $null) {
71+
# make sure it only specifies one parameter and get the name of that parameter
72+
if ($ast.ParamBlock.Parameters.Count -ne 1) {
73+
Write-DscTrace -Now -Level Error -Message 'Script must have exactly one parameter.'
74+
exit 3
75+
}
76+
$ast.ParamBlock.Parameters[0].Name.VariablePath.UserPath
77+
} else {
78+
$null
79+
}
80+
6081
$ps = [PowerShell]::Create().AddScript({
6182
$DebugPreference = 'Continue'
6283
$VerbosePreference = 'Continue'
6384
$ErrorActionPreference = 'Stop'
64-
})
85+
}).AddScript($script)
6586

6687
if ($null -ne $scriptObject.input) {
67-
$null = $ps.AddScript({
68-
$global:inputArg = $scriptObject.input
69-
})
88+
if ($null -eq $paramName) {
89+
Write-DscTrace -Now -Level Error -Message 'Input was provided but script does not have a parameter to accept input.'
90+
exit 3
91+
}
92+
$null = $ps.AddParameter($paramName, $scriptObject.input)
93+
} elseif ($null -ne $paramName) {
94+
Write-DscTrace -Now -Level Error -Message "Script has a parameter '$paramName' but no input was provided."
95+
exit 3
7096
}
7197

72-
$null = $ps.AddScript($script)
73-
7498
$ps.Streams.Error.add_DataAdded({
7599
param($sender, $args)
76-
Write-DscTrace -Level Error -Message $sender.Message
100+
Write-DscTrace -Level Error -Message ($sender.Message | Out-String)
77101
})
78102
$ps.Streams.Warning.add_DataAdded({
79103
param($sender, $args)
80-
Write-DscTrace -Level Warn -Message $sender.Message
104+
Write-DscTrace -Level Warn -Message ($sender.Message | Out-String)
81105
})
82106
$ps.Streams.Information.add_DataAdded({
83107
param($sender, $args)
84-
Write-DscTrace -Level Trace -Message $sender.MessageData.ToString()
108+
Write-DscTrace -Level Trace -Message ($sender.MessageData | Out-String)
85109
})
86110
$ps.Streams.Verbose.add_DataAdded({
87111
param($sender, $args)
88-
Write-DscTrace -Level Info -Message $sender.Message
112+
Write-DscTrace -Level Info -Message ($sender.Message | Out-String)
89113
})
90114
$ps.Streams.Debug.add_DataAdded({
91115
param($sender, $args)
92-
Write-DscTrace -Level Debug -Message $sender.Message
116+
Write-DscTrace -Level Debug -Message ($sender.Message | Out-String)
93117
})
94118
$outputObjects = [System.Collections.Generic.List[Object]]::new()
95119

120+
function write-traces() {
121+
$trace = $null
122+
while (!$traceQueue.IsEmpty) {
123+
if ($traceQueue.TryDequeue([ref] $trace)) {
124+
$host.ui.WriteErrorLine($trace)
125+
}
126+
}
127+
}
128+
96129
try {
97130
$asyncResult = $ps.BeginInvoke()
98131
while (-not $asyncResult.IsCompleted) {
99-
While ($traceQueue.Count -gt 0) {
100-
$trace = $traceQueue.Dequeue()
101-
$host.ui.WriteErrorLine($trace)
102-
}
132+
write-traces
133+
Start-Sleep -Milliseconds 100
103134
}
104135
$outputCollection = $ps.EndInvoke($asyncResult)
136+
write-traces
137+
105138
foreach ($output in $outputCollection) {
106139
$outputObjects.Add($output)
107140
}
108141
}
109142
catch {
110-
Write-DscTrace -Now -Level Error -Message $_.Exception.Message
143+
Write-DscTrace -Now -Level Error -Message ($_.Exception | Out-String)
111144
exit 1
112145
}
113146
finally {
@@ -120,11 +153,6 @@ if ($ps.HadErrors) {
120153
exit 1
121154
}
122155

123-
While ($traceQueue.Count -gt 0) {
124-
$trace = $traceQueue.Dequeue()
125-
$host.ui.WriteErrorLine($trace)
126-
}
127-
128156
# Test should return a single boolean value indicating if in the desired state
129157
if ($Operation -eq 'Test') {
130158
if ($outputObjects.Count -eq 1 -and $outputObjects[0] -is [bool]) {

resources/PSScript/psscript.tests.ps1

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ Describe 'Tests for PSScript resource' {
270270

271271
$yaml = @'
272272
getScript: |
273-
"Input: $input"
273+
param($inputObj)
274+
"Input: $inputObj"
274275
input: "This is a string"
275276
'@
276277
$result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
@@ -279,4 +280,29 @@ Describe 'Tests for PSScript resource' {
279280
$result.actualState.output[0] | Should -BeExactly "Input: This is a string"
280281
}
281282

283+
It 'Input without param block is an error for <resourecType>' -TestCases $testCases {
284+
param($resourceType)
285+
286+
$yaml = @'
287+
getScript: |
288+
"This should fail"
289+
input: "This is a string"
290+
'@
291+
dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
292+
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
293+
(Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*ERROR*:*Input was provided but script does not have a parameter to accept input.*'
294+
}
295+
296+
It 'Param without input is an error for <resourceType>' -TestCases $testCases {
297+
param($resourceType)
298+
299+
$yaml = @'
300+
getScript: |
301+
param($inputObj)
302+
"This should fail"
303+
'@
304+
dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
305+
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
306+
(Get-Content $TestDrive/error.txt -Raw) | Should -BeLike "*ERROR*:*Script has a parameter 'inputObj' but no input was provided.*"
307+
}
282308
}

0 commit comments

Comments
 (0)