Skip to content

Commit 4ec3e49

Browse files
committed
Add Show switch, plus various fixes and verbose logging added
1 parent 6a1fc3b commit 4ec3e49

File tree

1 file changed

+98
-36
lines changed

1 file changed

+98
-36
lines changed

src/PSAppDeployToolkit.Tools/Public/Convert-ADTDeployment.ps1

Lines changed: 98 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ function Convert-ADTDeployment
1818
.PARAMETER Destination
1919
Path to the output file or folder. If not specified it will default to creating either a Invoke-AppDeployToolkit.ps1 file or FolderName_Converted folder under the parent folder of the supplied Path value.
2020
21+
.PARAMETER Show
22+
Opens the newly created output in Windows Explorer.
23+
2124
.PARAMETER Force
2225
Overwrite the output path if it already exists.
2326
@@ -91,8 +94,12 @@ function Convert-ADTDeployment
9194
[System.String]$Path,
9295

9396
[Parameter(Mandatory = $false)]
97+
[ValidateNotNullOrEmpty()]
9498
[string]$Destination = (Split-Path -Path $Path -Parent),
9599

100+
[Parameter(Mandatory = $false)]
101+
[System.Management.Automation.SwitchParameter]$Show,
102+
96103
[Parameter(Mandatory = $false)]
97104
[System.Management.Automation.SwitchParameter]$Force,
98105

@@ -123,7 +130,7 @@ function Convert-ADTDeployment
123130
$variableReplacements = @('appVendor', 'appName', 'appVersion', 'appArch', 'appLang', 'appRevision', 'appScriptVersion', 'appScriptAuthor', 'installName', 'installTitle')
124131

125132
$customRulePath = [System.IO.Path]::Combine($MyInvocation.MyCommand.Module.ModuleBase, 'PSScriptAnalyzer\Measure-ADTCompatibility.psm1')
126-
$templateScriptPath = [System.IO.Path]::Combine($MyInvocation.MyCommand.Module.ModuleBase, 'Frontend\v4\Invoke-AppDeployToolkit.ps1')
133+
$templateScriptPath = [System.IO.Path]::Combine((Get-Module PSAppDeployToolkit).ModuleBase, 'Frontend\v4\Invoke-AppDeployToolkit.ps1')
127134
}
128135

129136
process
@@ -133,14 +140,15 @@ function Convert-ADTDeployment
133140
try
134141
{
135142
$tempFolderName = "Convert-ADTDeployment_$([System.IO.Path]::GetRandomFileName().Replace('.', ''))"
136-
$tempPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), $tempFolderName)
143+
$tempFolderPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), $tempFolderName)
137144

138-
if ([System.IO.File]::Exists($Path))
145+
if ($Path -like '*.ps1')
139146
{
140-
Write-Verbose -Message "Input path is a file: $Path"
147+
Write-Verbose -Message "Input path is a .ps1 file: [$Path]"
141148

142149
# Update destination path with a specific filename if current value does not end in .ps1
143150
$Destination = if ($Destination -like '*.ps1') { $Destination } else { [System.IO.Path]::Combine($Destination, 'Invoke-AppDeployToolkit.ps1') }
151+
Write-Verbose -Message "Destination path: [$Destination]"
144152

145153
# Halt if the destination file already exists and -Force is not specified
146154
if (!$Force -and [System.IO.File]::Exists($Destination))
@@ -155,28 +163,49 @@ function Convert-ADTDeployment
155163
Write-Error -ErrorRecord (New-ADTErrorRecord @naerParams)
156164
}
157165

158-
if ($Path -notmatch '(Deploy-Application\.ps1|Invoke-AppDeployToolkit\.ps1)$')
166+
if ($Path -notmatch '(?<=^|\\)(Deploy-Application\.ps1|Invoke-AppDeployToolkit\.ps1)$')
159167
{
160168
Write-Warning -Message "This function is designed to convert PSAppDeployToolkit deployment scripts such as Deploy-Application.ps1 or Invoke-AppDeployToolkit.ps1."
161169
}
162170

163171
# Create the temp folder
164-
New-Item -Path $tempPath -ItemType Directory -Force | Out-Null
165-
# Create a temp copy of the script to run ScriptAnalyzer fixes on - prefix filename with _ in case it's named Invoke-AppDeployToolkit.ps1
166-
$inputScriptPath = [System.IO.Path]::Combine(([System.IO.Path]::GetDirectoryName($fullPath)), "_$([System.IO.Path]::GetFileName($fullPath))")
167-
Copy-Item -LiteralPath $Path -Destination $inputScriptPath -Force -PassThru
172+
Write-Verbose -Message "Creating temp folder [$tempFolderPath]"
173+
New-Item -Path $tempFolderPath -ItemType Directory -Force | Out-Null
174+
175+
# Create a temp copy of the script to run ScriptAnalyzer fixes on - prefix filename with _ if it's named Invoke-AppDeployToolkit.ps1
176+
$inputScriptPath = if ($Path -match '(?<=^|\\)Invoke-AppDeployToolkit.ps1$')
177+
{
178+
[System.IO.Path]::Combine(([System.IO.Path]::GetDirectoryName($Path)), "_$([System.IO.Path]::GetFileName($Path))")
179+
}
180+
else
181+
{
182+
$Path
183+
}
184+
185+
Write-Verbose -Message "Creating copy of [$Path] as [$inputScriptPath]"
186+
Copy-Item -LiteralPath $Path -Destination $inputScriptPath -Force
187+
168188
# Copy over our template v4 script
169-
$tempScriptPath = (Copy-Item -LiteralPath $templateScriptPath -Destination $tempPath -Force -PassThru).FullName
189+
Write-Verbose -Message "Copying template script to [$tempFolderPath\Invoke-AppDeployToolkit.ps1]"
190+
$outputScriptPath = (Copy-Item -LiteralPath $templateScriptPath -Destination $tempFolderPath -Force -PassThru).FullName
170191
}
171-
elseif ([System.IO.Directory]::Exists($Path))
192+
else
172193
{
173-
Write-Verbose -Message "Input path is a folder: $Path"
194+
Write-Verbose -Message "Input path is a folder: [$Path]"
174195

175196
# Re-use the same folder name with _Converted suffix for the new folder
176197
$folderName = "$(Split-Path -Path $Path -Leaf)_Converted"
177198

178-
# Update destination path to append this new folder name
179-
$Destination = [System.IO.Path]::Combine($Destination, $folderName)
199+
# Update destination path to append this new folder name. If Destination is empty, it would mean that Path was something like C:\ with no parent, so just append the folder name to Path instead.
200+
$Destination = if ([string]::IsNullOrEmpty($Destination))
201+
{
202+
[System.IO.Path]::Combine($Path, $folderName)
203+
}
204+
else
205+
{
206+
[System.IO.Path]::Combine($Destination, $folderName)
207+
}
208+
Write-Verbose -Message "Destination path: [$Destination]"
180209

181210
# Halt if the destination folder already exists and is not empty and -Force is not specified
182211
if (!$Force -and [System.IO.Directory]::Exists($Destination) -and ([System.IO.Directory]::GetFiles($Destination) -or [System.IO.Directory]::GetDirectories($Destination)))
@@ -191,17 +220,18 @@ function Convert-ADTDeployment
191220
Write-Error -ErrorRecord (New-ADTErrorRecord @naerParams)
192221
}
193222

194-
# Use New-ADTTemplate to generate our temp folder
223+
Write-Verbose -Message "Creating ADT Template in [$tempFolderPath]"
195224
New-ADTTemplate -Destination ([System.IO.Path]::GetTempPath()) -Name $tempFolderName
196225

197-
# Create a temp copy of Deploy-Application.ps1 to run ScriptAnalyzer fixes on
198-
$inputScriptPath = (Copy-Item -LiteralPath ([System.IO.Path]::Combine($Path, 'Deploy-Application.ps1')) -Destination $tempPath -Force -PassThru).FullName
226+
Write-Verbose -Message "Creating copy of [$Path\Deploy-Application.ps1] as [$tempFolderPath\Deploy-Application.ps1]"
227+
$inputScriptPath = (Copy-Item -LiteralPath ([System.IO.Path]::Combine($Path, 'Deploy-Application.ps1')) -Destination $tempFolderPath -Force -PassThru).FullName
199228

200229
# Set the path of our v4 template script
201-
$tempScriptPath = [System.IO.Path]::Combine($tempPath, 'Invoke-AppDeployToolkit.ps1')
230+
$outputScriptPath = [System.IO.Path]::Combine($tempFolderPath, 'Invoke-AppDeployToolkit.ps1')
202231
}
203232

204233
# First run the fixes on the input script to update function names and variables
234+
Write-Verbose -Message "Running ScriptAnalyzer fixes on [$inputScriptPath]"
205235
Invoke-ScriptAnalyzer -Path $inputScriptPath -CustomRulePath $customRulePath -Fix | Out-Null
206236

207237
# Parse the input script and find the if statement that contains the deployment code
@@ -225,8 +255,10 @@ function Convert-ADTDeployment
225255

226256
if ($ifClause)
227257
{
258+
Write-Verbose -Message "Found statement: if ($($ifClause.Item1.Extent.Text))"
259+
228260
# Re-read and parse the v4 template script after each replacement so that the offsets will still be valid
229-
$tempScriptContent = Get-Content -Path $tempScriptPath -Raw
261+
$tempScriptContent = Get-Content -Path $outputScriptPath -Raw
230262
$tempScriptAst = [System.Management.Automation.Language.Parser]::ParseInput($tempScriptContent, [ref]$null, [ref]$null)
231263

232264
# Find the function definition in the v4 template script to fill in
@@ -237,18 +269,24 @@ function Convert-ADTDeployment
237269

238270
if ($functionAst)
239271
{
272+
Write-Verbose -Message "Updating function [$($scriptReplacement.v4FunctionName)]"
273+
240274
# Update the content of the v4 template script
241275
$start = $functionAst.Body.Extent.StartOffset
242276
$end = $functionAst.Body.Extent.EndOffset
243277
$scriptContent = $tempScriptAst.Extent.Text
244278
$newScriptContent = ($scriptContent.Substring(0, $start) + $ifClause.Item2.Extent.Text + $scriptContent.Substring($end)).Trim()
245-
Set-Content -Path $tempScriptPath -Value $newScriptContent -Encoding UTF8
279+
Set-Content -Path $outputScriptPath -Value $newScriptContent -Encoding UTF8
246280
}
247281
}
282+
else
283+
{
284+
Write-Warning -Message "The if statement for [$($scriptReplacement.v4FunctionName)] was not found in the input script."
285+
}
248286
}
249287

250288
# Re-read and parse the script one more time
251-
$tempScriptContent = Get-Content -Path $tempScriptPath -Raw
289+
$tempScriptContent = Get-Content -Path $outputScriptPath -Raw
252290
$tempScriptAst = [System.Management.Automation.Language.Parser]::ParseInput($tempScriptContent, [ref]$null, [ref]$null)
253291

254292
# Find the hashtable in the v4 template script that holds the adtSession splat
@@ -259,12 +297,11 @@ function Convert-ADTDeployment
259297

260298
if ($hashtableAst)
261299
{
300+
Write-Verbose -Message 'Processing $adtSession hashtable'
301+
262302
# Get the text form of the hashtable definition
263303
$hashtableContent = $hashtableAst.Right.Extent.Text
264304

265-
# Update the appScriptDate value to the current date
266-
$hashtableContent = $hashtableContent -replace "(?m)(^\s*appScriptDate\s*=)\s*'[^']+'", "`$1 '$(Get-Date -Format "yyyy-MM-dd")'"
267-
268305
# Copy each variable value from the input script to the hashtable
269306
foreach ($variableReplacement in $variableReplacements)
270307
{
@@ -275,26 +312,41 @@ function Convert-ADTDeployment
275312

276313
if ($assignmentAst)
277314
{
315+
Write-Verbose -Message "Updating variable [$variableReplacement]"
278316
$variableValue = $assignmentAst.Right.Extent.Text
279317
$hashtableContent = $hashtableContent -replace "(?m)(^\s*$variableReplacement\s*=)\s*'[^']*'", "`$1 $variableValue"
280318
}
281319
}
282320

321+
Write-Verbose -Message 'Updating variable [appScriptDate]'
322+
$hashtableContent = $hashtableContent -replace "(?m)(^\s*appScriptDate\s*=)\s*'[^']+'", "`$1 '$(Get-Date -Format "yyyy-MM-dd")'"
323+
283324
# Update the content of the v4 template script
284325
$start = $hashtableAst.Right.Extent.StartOffset
285326
$end = $hashtableAst.Right.Extent.EndOffset
286327
$scriptContent = $tempScriptAst.Extent.Text
287328
$newScriptContent = ($scriptContent.Substring(0, $start) + $hashtableContent + $scriptContent.Substring($end)).Trim()
288-
Set-Content -Path $tempScriptPath -Value $newScriptContent -Encoding UTF8
329+
Set-Content -Path $outputScriptPath -Value $newScriptContent -Encoding UTF8
330+
}
331+
else
332+
{
333+
Write-Warning -Message 'Could not find [$adtSession] hashtable'
289334
}
290335

291-
# Delete the temporary copy of the v3 script used for processing
336+
Write-Verbose -Message "Removing temp script [$inputScriptPath]"
292337
Remove-Item -LiteralPath $inputScriptPath -Force
293338

294339
if ($Path -like '*.ps1')
295340
{
296-
# Move the updated script to the destination
297-
Move-Item -LiteralPath $tempScriptPath -Destination $Destination -Force -PassThru:$PassThru
341+
Write-Verbose -Message "Moving file [$outputScriptPath] to [$Destination]"
342+
Move-Item -LiteralPath $outputScriptPath -Destination $Destination -Force -PassThru:$PassThru
343+
344+
# Display the newly created file in Windows Explorer (/select highlights the file in the folder).
345+
if ($Show)
346+
{
347+
Write-Verbose -Message "Selecting [$Destination] in Windows Explorer"
348+
& ([System.IO.Path]::Combine([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Windows), 'explorer.exe')) /select, $Destination
349+
}
298350
}
299351
else
300352
{
@@ -304,28 +356,31 @@ function Convert-ADTDeployment
304356
$subFolderPath = [System.IO.Path]::Combine($Path, $subFolder)
305357
if ([System.IO.Directory]::Exists($subFolderPath))
306358
{
307-
Copy-Item -LiteralPath $subFolderPath -Destination $tempPath -Recurse -Force
359+
Write-Verbose -Message "Copying $subFolder content"
360+
Copy-Item -LiteralPath $subFolderPath -Destination $tempFolderPath -Recurse -Force
308361
}
309362
}
310363

311-
# Remove the Destination if it already exists (Force checks were done earlier)
364+
# Remove the Destination if it already exists (we should have already exited by this point if folder exists and Force not specified)
312365
if (Test-Path -LiteralPath $Destination)
313366
{
314-
Remove-Item -LiteralPath $Destination -Recurse -Force -ErrorAction SilentlyContinue
367+
Write-Verbose -Message "Removing existing destination folder [$Destination]"
368+
Remove-Item -LiteralPath $Destination -Recurse -Force -ErrorAction SilentlyContinue -WhatIf
315369
}
316370

317371
# Sometimes previous actions were leaving a lock on the temp folder, so set up a retry loop
318372
for ($i = 0; $i -lt 5; $i++)
319373
{
320374
try
321375
{
322-
Move-Item -Path $tempPath -Destination $Destination -Force -PassThru:$PassThru
376+
Write-Verbose -Message "Moving folder [$tempFolderPath] to [$Destination]"
377+
Move-Item -Path $tempFolderPath -Destination $Destination -Force -PassThru:$PassThru
323378
Write-Information -MessageData "Conversion successful: $Destination"
324379
break
325380
}
326381
catch
327382
{
328-
Write-Verbose -Message "Failed to move [$tempPath] to [$Destination]. Trying again in 500ms."
383+
Write-Verbose -Message "Failed to move folder. Trying again in 500ms."
329384
[System.Threading.Thread]::Sleep(500)
330385
if ($i -eq 4)
331386
{
@@ -334,6 +389,13 @@ function Convert-ADTDeployment
334389
}
335390
}
336391

392+
# Display the newly created folder in Windows Explorer.
393+
if ($Show)
394+
{
395+
Write-Verbose -Message "Opening [$Destination] in Windows Explorer"
396+
& ([System.IO.Path]::Combine([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Windows), 'explorer.exe')) $Destination
397+
}
398+
337399
}
338400
}
339401
catch
@@ -343,10 +405,10 @@ function Convert-ADTDeployment
343405
}
344406
finally
345407
{
346-
if (Test-Path -LiteralPath $tempPath)
408+
if (Test-Path -LiteralPath $tempFolderPath)
347409
{
348-
Write-Verbose -Message "Removing temp path [$tempPath]"
349-
Remove-Item -Path $tempPath -Recurse -Force -ErrorAction SilentlyContinue
410+
Write-Verbose -Message "Removing temp folder [$tempFolderPath]"
411+
Remove-Item -Path $tempFolderPath -Recurse -Force -ErrorAction SilentlyContinue
350412
}
351413
}
352414
}

0 commit comments

Comments
 (0)