@@ -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