Guest User

Untitled

a guest
Feb 22nd, 2018
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.92 KB | None | 0 0
  1. function Expand-String
  2. {
  3. <# .SYNOPSIS Returns code to replace input expansion string as string #>
  4.  
  5. [cmdletbinding()]
  6. Param (
  7. [string]$String )
  8.  
  9. # Get the PowerShell Parser's ScanString method
  10. # (It's an 'internal' method, so we can't call it with the usual syntax)
  11. $ScanString = [System.Management.Automation.Language.Parser].GetMethod( 'ScanString', @( 'static','nonpublic','instance' ) )
  12.  
  13. # Ask PowerShell to do the work of finding the expressions within the String
  14. $StringExpression = $ScanString.Invoke( $Null, @( $String ) )
  15. $Nested = $StringExpression.NestedExpressions.Extent
  16.  
  17. # If there are no nested expression
  18. # (No change needed)
  19. # Return the original string
  20. If ( -not $Nested )
  21. {
  22. return $String
  23. }
  24.  
  25. # If the first nested expression is the first thing in the string
  26. # Add it to the expansion, with a cast to [string]
  27. # (All subsequent elements will be implicitly cast)
  28. If ( $Nested[0].StartOffset -eq 1 )
  29. {
  30. $Expansion = '( [string]' + $Nested[0].Text
  31. $Position = $Nested[0].EndOffset - 1
  32. $NestIndex = 1
  33. }
  34.  
  35. # Else (first part of the string is a string)
  36. # Add it to the expansion
  37. Else
  38. {
  39. $Expansion = '( "' + $String.Substring( 0, $Nested[0].StartOffset - 1 ) + '"'
  40. $Position = $Nested[0].StartOffset - 1
  41. $NestIndex = 0
  42. }
  43.  
  44. # While we are not at the end of the string...
  45. While ( $Position -lt $String.Length )
  46. {
  47.  
  48. # If the next thing in the the string is the next nested expression
  49. # Add it to the expansion
  50. If ( $Position -eq $Nested[$NestIndex].StartOffset - 1 )
  51. {
  52. $Expansion += " + " + $Nested[$NestIndex].Text
  53. $Position = $Nested[$NestIndex].EndOffset - 1
  54. $NestIndex++
  55. }
  56.  
  57. # Else (next thing in the string is a string)...
  58. Else
  59. {
  60. # If there is anothor expression ahead
  61. # Add a substring of string up to the next expression to the expansion
  62. If ( $Nested[$NestIndex] )
  63. {
  64. $Length = $Nested[$NestIndex].StartOffset - $Position - 1
  65. $Expansion += ' + "' + $String.Substring( $Position, $Length ) + '"'
  66. $Position += $Length
  67. }
  68.  
  69. # Else (the rest of the string is nothing but string)
  70. # Add it to the expansion
  71. Else
  72. {
  73. $Expansion += ' + "' + $String.Substring( $Position ) + '"'
  74. $Position = $String.Length
  75. }
  76. }
  77. }
  78. $Expansion += " )"
  79.  
  80. # return the result
  81. return $Expansion
  82. }
  83.  
  84. function Remove-CommentsAndWhiteSpaceAndVariablesAndCommands
  85. {
  86. # We are not restricting scriptblock type as Tokenize() can take several types
  87. Param (
  88. [parameter( ValueFromPipeline = $True )]
  89. $Scriptblock
  90. )
  91.  
  92. Begin
  93. {
  94. # Intialize collection
  95. $Items = @()
  96. }
  97.  
  98. Process
  99. {
  100. # Collect all of the inputs together
  101. $Items += $Scriptblock
  102. }
  103.  
  104. End
  105. {
  106. ## Process the script as a single unit
  107.  
  108. # Convert input to a single string if needed
  109. $OldScript = $Items -join [environment]::NewLine
  110.  
  111. # If no work to do
  112. # We're done
  113. If ( -not $OldScript.Trim( " `n`r`t" ) ) { return }
  114.  
  115. # Use the PowerShell tokenizer to break the script into identified tokens
  116. $Tokens = [System.Management.Automation.PSParser]::Tokenize( $OldScript, [ref]$Null )
  117.  
  118. #region Expand any expandable strings
  119.  
  120. $Expanded = $False
  121.  
  122. $ExpandableStringTokens = $Tokens |
  123. Where-Object { $_.Type -eq 'String' -and
  124. ( $OldScript.Substring( $_.Start, 1 ) -eq '"' -or
  125. $OldScript.Substring( $_.Start, 2 ) -eq '@"' ) } |
  126. Sort-Object -Property Start -Descending
  127.  
  128. ForEach ( $Token in $ExpandableStringTokens )
  129. {
  130. $String = $OldScript.Substring( $Token.Start, $Token.Length )
  131. If ( $String.StartsWith( '@' ) )
  132. {
  133. $String = $String.Substring( 2, $String.Length - 3 )
  134. }
  135. Else
  136. {
  137. $String = $String.Substring( 1, $String.Length - 2 )
  138. }
  139. $ExpandedString = Expand-String -String $String
  140.  
  141. If ( $ExpandedString -ne $String )
  142. {
  143. If ( $OldScript.Length -gt $Token.Start + $Token.Length )
  144. {
  145. $OldScript =
  146. $OldScript.Substring( 0, $Token.Start ) +
  147. $ExpandedString +
  148. $OldScript.Substring( $Token.Start + $Token.Length )
  149. }
  150. Else
  151. {
  152. $OldScript =
  153. $OldScript.Substring( 0, $Token.Start ) +
  154. $ExpandedString
  155. }
  156. $Expanded = $True
  157. }
  158. }
  159.  
  160. If ( $Expanded )
  161. {
  162. # Use the PowerShell tokenizer to break the script into identified tokens
  163. $Tokens = [System.Management.Automation.PSParser]::Tokenize( $OldScript, [ref]$Null )
  164. }
  165.  
  166. #endregion
  167.  
  168. # Define useful, allowed comments
  169. $AllowedComments = @(
  170. 'requires'
  171. '.SYNOPSIS'
  172. '.DESCRIPTION'
  173. '.PARAMETER'
  174. '.EXAMPLE'
  175. '.INPUTS'
  176. '.OUTPUTS'
  177. '.NOTES'
  178. '.LINK'
  179. '.COMPONENT'
  180. '.ROLE'
  181. '.FUNCTIONALITY'
  182. '.FORWARDHELPCATEGORY'
  183. '.REMOTEHELPRUNSPACE'
  184. '.EXTERNALHELP' )
  185.  
  186. # Strip out the Comments, but not useful comments
  187. # (Bug: This will break comment-based help that uses leading # instead of multiline <#,
  188. # because only the headings will be left behind.)
  189.  
  190. $Tokens = $Tokens.ForEach{
  191. If ( $_.Type -ne 'Comment' )
  192. {
  193. $_
  194. }
  195. Else
  196. {
  197. $CommentText = $_.Content.Substring( $_.Content.IndexOf( '#' ) + 1 )
  198. $FirstInnerToken = [System.Management.Automation.PSParser]::Tokenize( $CommentText, [ref]$Null ) |
  199. Where-Object { $_.Type -ne 'NewLine' } |
  200. Select-Object -First 1
  201. If ( $FirstInnerToken.Content -in $AllowedComments )
  202. {
  203. $_
  204. }
  205. } }
  206.  
  207. # Initialize script string
  208. $NewScriptText = ''
  209. $SkipNext = $False
  210.  
  211. #region Build Variable cache
  212.  
  213. # Initialize variable cache
  214. $VariableMap = @{}
  215. $VariableNext = 0
  216.  
  217. #region Automatic variables
  218.  
  219. # Add automatic variables to cache unchanged
  220.  
  221. # Add automatic variables to variable cache
  222. ( Get-Help about_Automatic_Variables ).
  223. Split( [environment]::Newline ) |
  224. Where-Object { $_.StartsWith( ' $' ) -or $_.StartsWith( ' $' ) } |
  225. ForEach-Object { $_.Trim( ' $' ) } |
  226. ForEach-Object {
  227. $VariableMap.Add( $_, "`$$_" )
  228. $VariableMap.Add( "Script:$_", "`$Script:$_" )
  229. $VariableMap.Add( "Global:$_", "`$Global:$_" )
  230. $VariableMap.Add( "Local:$_" , "`$Local:$_" ) }
  231.  
  232. # endregion
  233.  
  234.  
  235. #region Script parameter variables
  236.  
  237. # Add script parameter variables and any other variables referenced in
  238. # the script param block to the variable cache unchanged
  239.  
  240. # Add script parameter variables to variable cache
  241. $ParameterNames = @()
  242.  
  243. # Find the first use of keyword "Param"
  244. $ParamIndex = 0..($Tokens.Count-1) |
  245. Where-Object { $Tokens[$_].Content -eq 'param' -and $Tokens[$_].Type -eq 'Keyword' } |
  246. Select-Object -First 1
  247.  
  248. # Find the first use of keyword "Function"
  249. $FunctionIndex = 0..($Tokens.Count-1) |
  250. Where-Object { $Tokens[$_].Content -eq 'function' -and $Tokens[$_].Type -eq 'Keyword' } |
  251. Select-Object -First 1
  252.  
  253. # There are script parameters if there is a Param before
  254. # any Function definitions
  255. $ScriptParamUsed =
  256. ( $ParamIndex -lt $FunctionIndex -or
  257. $FunctionIndex -eq $Null ) -and
  258. $ParamIndex -ne $Null
  259.  
  260. # If script parameters exist...
  261. If ( $ScriptParamUsed )
  262. {
  263. # Start at the opening parenthesis for the Param block
  264. $ParenIndex = ($ParamIndex+1)..($Tokens.Count-1) |
  265. Where-Object { $Tokens[$_].Content -eq '(' -and $Tokens[$_].Type -eq 'GroupStart' } |
  266. Select-Object -First 1
  267.  
  268. # If the first parenthesis exists
  269. # Count parentheses to find the matching closing parenthesis
  270. If ( $ParenIndex )
  271. {
  272. # Starting one parenthesis deep
  273. $Level = 1
  274.  
  275. # Until we climb all the way out or run out scipt...
  276. # (with embedded increment of token position)
  277. While ( $Level -gt 0 -and ++$ParenIndex -le $Tokens.Count )
  278. {
  279. # If this token is a parenthesis, increment or decrement level
  280. $Level += ( $Tokens[$ParenIndex].Content.EndsWith( '(' ) -and $Tokens[$ParenIndex].Type -eq 'GroupStart' )
  281. $Level -= ( $Tokens[$ParenIndex].Content -eq ')' -and $Tokens[$ParenIndex].Type -eq 'GroupEnd' )
  282. }
  283.  
  284. # If we found the closing parenthesis for the param block...
  285. If ( $Level -eq 0 )
  286. {
  287. # Get all of the variables in the param block
  288. $ParameterNames += ( $ParamIndex..$ParenIndex ).
  289. Where{ $Tokens[$_].Type -eq 'Variable' }.
  290. ForEach{ $Tokens[$_].Content }
  291.  
  292. # (We'll add them to the cache in along with
  293. # the Function parameter variables below.)
  294.  
  295. # Note the location of the end of the param block
  296. # (This is a possible location for inserting Set-Alias commands.)
  297. $LastScriptParamToken = $ParenIndex
  298.  
  299. # If the following token is a new line or semicolon
  300. # Make that the location of the end of the param block
  301. If ( $Tokens[$ParenIndex+1].Type -in ( 'NewLine', 'StatementSeparator' ) )
  302. {
  303. $LastScriptParamToken++
  304. }
  305. }
  306. }
  307. }
  308. #endregion
  309.  
  310.  
  311. #region Function parameter variables
  312.  
  313. # Add function parameter variables to the variable cache unchanged
  314.  
  315. # Find all keyword "Function" tokens
  316. $FunctionIndices = ( 0..($Tokens.Count-1) ).
  317. Where{ $Tokens[$_].Content -eq 'function' -and $Tokens[$_].Type -eq 'Keyword' }
  318.  
  319. # For each Function token
  320. :FLoop
  321. ForEach ( $StartIndex in $FunctionIndices )
  322. {
  323.  
  324. # If the Function token is properly follewed by a function name...
  325. If ( $Tokens[$StartIndex+1].Type -eq 'CommandArgument' )
  326. {
  327.  
  328. # Get the function name
  329. $FunctionName = $Tokens[$StartIndex+1].Content
  330.  
  331. # Start at the function's open curly brace
  332. $BraceIndex = ($StartIndex+2)..($Tokens.Count-1) |
  333. Where-Object { $Tokens[$_].Content -eq '{' -and $Tokens[$_].Type -eq 'GroupStart' } |
  334. Select-Object -First 1
  335.  
  336. # If the open curly brace was found..
  337. If ( $BraceIndex )
  338. {
  339. # Start one level deep
  340. $Level = 1
  341.  
  342. # Until we climb out of the curly braces...
  343. While ( $Level -gt 0 )
  344. {
  345. # If we ran out of script
  346. # Stop processing Functions
  347. If ( ++$BraceIndex -ge $Tokens.Count ) { break FLoop }
  348.  
  349. # If this token is a curly brace, increment or decrement the level
  350. $Level += ( $Tokens[$BraceIndex].Content.EndsWith( '{' ) -and $Tokens[$BraceIndex].Type -eq 'GroupStart' )
  351. $Level -= ( $Tokens[$BraceIndex].Content -eq '}' -and $Tokens[$BraceIndex].Type -eq 'GroupEnd' )
  352. }
  353.  
  354. # Get the function definition
  355. $FunctionString = $OldScript.Substring( $Tokens[$StartIndex].Start, $Tokens[$BraceIndex].Start - $Tokens[$StartIndex].Start + 1 )
  356. try
  357. {
  358. ## Warning
  359. ## This loads an untrusted function into memory
  360.  
  361. # Run the function definition
  362. Invoke-Expression $FunctionString
  363.  
  364. # Get the function parameters
  365. # Add them to the list
  366. $Function = Get-command $FunctionName -CommandType Function
  367. $ParameterNames += $Function.Parameters.Keys
  368. }
  369. catch {}
  370. }
  371. }
  372. }
  373.  
  374. # Deduplicate script and function parameter variables
  375. $ParameterNames = $ParameterNames | Sort-Object -Unique
  376.  
  377. # For each script and function parameter
  378. # Add it to the cache unchanged
  379. ForEach ( $Name in $ParameterNames )
  380. {
  381. If ( $Name -notin $VariableMap.Keys )
  382. {
  383. $VariableMap.Add( $Name, "`$$Name" )
  384. $VariableMap.Add( "Script:$Name", "`$Script:$Name" )
  385. $VariableMap.Add( "Global:$Name", "`$Global:$Name" )
  386. $VariableMap.Add( "Local:$Name" , "`$Local:$Name" )
  387. }
  388. }
  389.  
  390. #endregion
  391.  
  392. #endregion
  393.  
  394.  
  395. #region Build command aliases
  396.  
  397. # Get all commands used in the script
  398. # (Includes all cmdlets, functions, aliases, external references, etc.
  399. $Commands = $Tokens.Where{ $_.Type -eq 'Command' }.Content |
  400. Sort-Object -Unique
  401.  
  402. # Initialize command map
  403. $CommandMap = @{}
  404.  
  405. # Initialize Set-Alias code block
  406. $AliasCode = [environment]::NewLine
  407.  
  408. # Initialize Set-Alias command separator loop
  409. $AS = 1
  410.  
  411. # For each command...
  412. ForEach ( $i in 0..($Commands.Count - 1) )
  413. {
  414. # Add the command and an alias to the map
  415. $CommandMap.Add( $Commands[$i], "C$i" )
  416.  
  417. # Add a Set-Alias command to the code block
  418. $AliasCode += "sal C$i $($Commands[$i])"
  419.  
  420. # Add a separator to the code block
  421. # (Three commands per line)
  422. $AliasCode += ( [environment]::NewLine, ';', ';' )[$AS++ % 3 ]
  423. }
  424.  
  425. # Replace the final separator in the code block with a new line
  426. $AliasCode = $AliasCode.TrimEnd( ';' + [environment]::NewLine ) + [environment]::NewLine
  427.  
  428.  
  429. # Find the last keyword "Using" token
  430. $LastUsingToken = ($Tokens.Count-1)..0 |
  431. Where-Object { $Tokens[$_].Content -eq 'Using' -and $Tokens[$_].Type -eq 'KeyWord' } |
  432. Select-Object -First 1
  433.  
  434. # Set if any Using statements are found
  435. $UsingUsed = [boolean]$LastUsingToken.Count
  436.  
  437. # If Using statements exist
  438. # Find the last token in the last Using statement
  439. # (This is a possible location for inserting the Set-Alias code block.)
  440. If ( $UsingUsed )
  441. {
  442. While ( $Tokens[++$LastUsingToken].Type -notin ( 'NewLine', 'StatementSeparator' ) -and
  443. $LastUsingToken -lt $Tokens.Count - 1)
  444. {}
  445. }
  446.  
  447. # Find the last "#requires" token
  448. $LastRequiresToken = ($Tokens.Count-1)..0 |
  449. Where-Object { $Tokens[$_].Type -eq 'Comment' -and $Tokens[$_].Content -like "#Requires*" -and ( $_ -eq 0 -or $Tokens[$_-1].Type -in ( 'NewLine', 'StatementSeparator' ) ) } |
  450. Select-Object -First 1
  451.  
  452. # Set if any #requires statemens are found
  453. $RequiresUsed = [boolean]$LastRequiresToken.Count
  454.  
  455. # If #requires statements exist
  456. # Find the last token in the last #requires statement
  457. # (This is a possible location for inserting the Set-Alias code block.)
  458. If ( $RequiresUsed )
  459. {
  460. $LastRequiresToken++
  461. }
  462.  
  463. # Set if the Set-Alias code block can't go at the beginning of the script
  464. $AliasDeferred = $ScriptParamUsed -or $UsingUsed -or $RequiresUsed
  465.  
  466. # Calculate the location after which to insert the Set-Alias code block
  467. # (After any parameter block, Using statements, or #requires statements
  468. $AliasToken = [math]::Max( [math]::Max( [int]$LastRequiresToken, [int]$LastScriptParamToken ), [int]$LastUsingToken )
  469.  
  470. # If the Set-Alias code block can be inserted at the start of the script
  471. # Add it to the script
  472. If ( -not $AliasDeferred )
  473. {
  474. $NewScriptText += $AliasCode
  475. }
  476.  
  477. #endregion
  478.  
  479. # If there are at least 2 tokens to process...
  480. If ( $Tokens.Count -gt 1 )
  481. {
  482. # For each token (except the last one)...
  483. ForEach ( $i in ( 0..($Tokens.Count-2) ) )
  484. {
  485. # If token is not a line continuation and not a repeated new line or semicolon...
  486. If ( -not $SkipNext -and
  487. $Tokens[$i ].Type -ne 'LineContinuation' -and (
  488. $Tokens[$i ].Type -notin ( 'NewLine', 'StatementSeparator' ) -or
  489. $Tokens[$i+1].Type -notin ( 'NewLine', 'StatementSeparator', 'GroupEnd' ) ) )
  490. {
  491. # Add Token to new script
  492. switch ( $Tokens[$i].Type )
  493. {
  494. 'Variable'
  495. {
  496. # If the variable is not in the variable cache
  497. # Add it to the variable cache
  498. If ( $Tokens[$i].Content -notin $VariableMap.Keys )
  499. {
  500. # Split out the variable name from the scope name
  501. $OldVariable = $OldScript.Substring( $Tokens[$i].Start, $Tokens[$i].Length ).Trim( '$' )
  502. $OldVariableSplit = $OldVariable.Split( ':', 2 )
  503. $VarName, [string]$Scope = $OldVariableSplit[-1..-2]
  504.  
  505. # If the scope is a recognized scope...
  506. If ( $Scope -in @( '', 'Global', 'Local', 'Script' ) )
  507. {
  508. # Get the next new variable name
  509. $NewVariable = 'V' + $VariableNext++
  510.  
  511. # Add the variations of the variable to the cache
  512. $VariableMap.Add( $VarName , "`$$NewVariable" )
  513. $VariableMap.Add( "Script:$VarName", "`$Script:$NewVariable" )
  514. $VariableMap.Add( "Global:$VarName", "`$Global:$NewVariable" )
  515. $VariableMap.Add( "Local:$VarName" , "`$Local:$NewVariable" )
  516. }
  517.  
  518. # Else (unrecognized scope)
  519. # Add it to the cache unchanged
  520. Else
  521. {
  522. $VariableMap.Add( $OldVariable, "`$$OldVariable" )
  523. }
  524. }
  525. # Add the cached new or unchanged variable reference to new script
  526. $NewScriptText += $VariableMap[$Tokens[$i].Content]
  527. }
  528. 'String'
  529. {
  530. # Add the string to the new script
  531. # (Get it from the old script, as .Content strips out the quote marks)
  532. $NewScriptText += $OldScript.Substring( $Tokens[$i].Start, $Tokens[$i].Length )
  533. }
  534. 'Command'
  535. {
  536. # If this command comes after the Set-Alias code block
  537. If ( $i -ge $AliasToken )
  538. {
  539. # Add the appropriate alias to the new script
  540. $NewScriptText += $CommandMap[$Tokens[$i].Content]
  541. }
  542.  
  543. # Else (this command comes before the Set-Alias commands)
  544. Else
  545. {
  546. # Add the command to the new script unchanged
  547. $NewScriptText += $Tokens[$i].Content
  548. }
  549. }
  550. Default
  551. {
  552. # Add the token to the new script unchanged
  553. $NewScriptText += $Tokens[$i].Content
  554. }
  555. }
  556.  
  557. # If the token does not never require a trailing space
  558. # And the next token does not never require a leading space
  559. # And this token and the next are on the same line
  560. # And this token and the next had white space between them in the original...
  561. If ( $Tokens[$i ].Type -notin ( 'NewLine', 'GroupStart', 'StatementSeparator' ) -and
  562. $Tokens[$i+1].Type -notin ( 'NewLine', 'GroupEnd', 'StatementSeparator' ) -and
  563. $Tokens[$i].EndLine -eq $Tokens[$i+1].StartLine -and
  564. $Tokens[$i+1].StartColumn - $Tokens[$i].EndColumn -gt 0 )
  565. {
  566. # Add a space to new script
  567. $NewScriptText += ' '
  568. }
  569.  
  570. # If the next token is a new line or semicolon following
  571. # an open parenthesis or curly brace, skip it
  572. $SkipNext = $Tokens[$i].Type -eq 'GroupStart' -and $Tokens[$i+1].Type -in ( 'NewLine', 'StatementSeparator' )
  573. }
  574.  
  575. # Else (Token is a line continuation or a repeated new line or semicolon)...
  576. Else
  577. {
  578. # [Do not include it in the new script]
  579.  
  580. # If the next token is a new line or semicolon following
  581. # an open parenthesis or curly brace, skip it
  582. $SkipNext = $SkipNext -and $Tokens[$i+1].Type -in ( 'NewLine', 'StatementSeparator' )
  583. }
  584.  
  585. # If this is the location to insert the Set-Alias command block
  586. # insert it
  587. If ( $AliasDeferred -and $i -eq $AliasToken )
  588. {
  589. $NewScriptText += $AliasCode
  590. }
  591. }
  592. }
  593.  
  594. # If there is a last token to process...
  595. If ( $Tokens )
  596. {
  597. $i++
  598. # Add last token to new script
  599. switch ( $Tokens[$i].Type )
  600. {
  601. 'Variable'
  602. {
  603. # If the variable is not in the variable cache
  604. # Add it to the variable cache
  605. If ( $Tokens[$i].Content -notin $VariableMap.Keys )
  606. {
  607. # Split out the variable name from the scope name
  608. $OldVariable = $OldScript.Substring( $Tokens[$i].Start, $Tokens[$i].Length ).Trim( '$' )
  609. $OldVariableSplit = $OldVariable.Split( ':', 2 )
  610. $VarName, [string]$Scope = $OldVariableSplit[-1..-2]
  611.  
  612. # If the scope is a recognized scope...
  613. If ( $Scope -in @( '', 'Global', 'Local', 'Script' ) )
  614. {
  615. # Get the next new variable name
  616. $NewVariable = 'V' + $VariableNext++
  617.  
  618. # Add the variations of the variable to the cache
  619. $VariableMap.Add( $VarName , "`$$NewVariable" )
  620. $VariableMap.Add( "Script:$VarName", "`$Script:$NewVariable" )
  621. $VariableMap.Add( "Global:$VarName", "`$Global:$NewVariable" )
  622. $VariableMap.Add( "Local:$VarName" , "`$Local:$NewVariable" )
  623. }
  624.  
  625. # Else (unrecognized scope)
  626. # Add it to the cache unchanged
  627. Else
  628. {
  629. $VariableMap.Add( $OldVariable, "`$$OldVariable" )
  630. }
  631. }
  632. # Add the cached new or unchanged variable reference to new script
  633. $NewScriptText += $VariableMap[$Tokens[$i].Content]
  634. }
  635. 'String'
  636. {
  637. # Add the string to the new script
  638. # (Get it from the old script, as .Content strips out the quote marks)
  639. $NewScriptText += $OldScript.Substring( $Tokens[$i].Start, $Tokens[$i].Length )
  640. }
  641. 'Command'
  642. {
  643. # If this command comes after the Set-Alias code block
  644. If ( $i -ge $AliasToken )
  645. {
  646. # Add the appropriate alias to the new script
  647. $NewScriptText += $CommandMap[$Tokens[$i].Content]
  648. }
  649.  
  650. # Else (this command comes before the Set-Alias commands)
  651. Else
  652. {
  653. # Add the command to the new script unchanged
  654. $NewScriptText += $Tokens[$i].Content
  655. }
  656. }
  657. Default
  658. {
  659. # Add the token to the new script unchanged
  660. $NewScriptText += $Tokens[$i].Content
  661. }
  662. }
  663. }
  664.  
  665. # Trim any leading new lines from the new script
  666. $NewScriptText = $NewScriptText.TrimStart( "`n`r;" )
  667.  
  668. # Return the new script as the same type as the input
  669. If ( $Items.Count -eq 1 )
  670. {
  671. If ( $Items[0] -is [scriptblock] )
  672. {
  673. # Return single scriptblock
  674. return [scriptblock]::Create( $NewScriptText )
  675. }
  676. Else
  677. {
  678. # Return single string
  679. return $NewScriptText
  680. }
  681. }
  682. Else
  683. {
  684. # Return array of strings
  685. return $NewScriptText -Split [environment]::NewLine
  686. }
  687. }
  688. }
Add Comment
Please, Sign In to add comment