<# : Batch Commands (PowerShell Comments) Start @echo off & setlocal rem rem Regular Expression Text Search rem rem rem RegExS.bat [] [] [] rem [-e ] [-g ] rem [-h] [-i] [-n] [-r] [-s] [-x ] rem [-bc ] [-cc ] [-fc ] rem [-Q/-Interactive] rem rem rem text pattern in .NET regular expression rem You'll be prompted for it if not specified in the command rem line arguments or when this script is started by a double click. rem target folder in which search is performed rem You'll be prompted to choose one in the popped-up selection rem dialog box if not specified. rem comma-delimited list of filenames to be searched rem Wildcards may be used. The default value is "*". rem (e.g. "*.cpp, *.h") rem -e character encoding for the files without BOMs(Byte Order Marks) rem The default value is "Default" rem -g capture-group name or number rem The default value is "0". rem -h Search result is output to a HTML file. rem -i Uppercase/lowercase are ignored. rem -n Wide characters are converted into narrow ones prior to rem search. Useful when you don't want to distinguish them. rem -r Search is performed in subfolders recursively. rem -s Search is performed by a simple text match. rem -x comma-delimited list of filenames to be excluded from search rem Wildcards may be used. (e.g. "*.img, *.dat") rem The following binary format files are excluded by default. rem "*.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png" rem -bc background color for matches rem -cc foreground color for capture-group matches rem -fc foreground color for matches rem -Q Interactive mode is forcedly enabled. rem rem Created by earthdiver1 rem Version 2.00 rem Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. rem rem ---------------------------------------------------------------------------- echo %CMDCMDLINE% | findstr /i /c:"%~nx0" >NUL && set DC=1 rem The following is a preamble for converting a PowerShell script into polyglot rem one that also runs as a batch script. Change the file extension to .ps1 and rem run it from PowerShell console when debugging. set BATCH_ARGS=%* if defined BATCH_ARGS set BATCH_ARGS=%BATCH_ARGS:"=\"% if defined BATCH_ARGS set BATCH_ARGS=%BATCH_ARGS:^^=^% set P_CMD=$DoubleClicked=0%DC%;$PSScriptRoot='%~dp0'.TrimEnd('\');$input^|^ &([ScriptBlock]::Create((${%~f0}^|Out-String))) endlocal & PowerShell -NoProfile -Command "%P_CMD%" %BATCH_ARGS% exit/b rem ---------------------------------------------------------------------------- : Batch Commands (PowerShell Comments) End #> #Requires -Version 3 param ( [String]$Pattern, [String]$Dir, [String]$Include = "*", [Alias("e")][String]$Encoding = "Default", [Alias("x")][String]$Exclude = "", [Alias("g")][String]$Group = "0", [Alias("h")][Switch]$HtmlOutput = $False, [Alias("i")][Switch]$IgnoreCase = $False, [Alias("n")][Switch]$Narrow = $False, [Alias("r")][Switch]$Recurse = $False, [Alias("s")][Switch]$SimpleMatch = $False, [Alias("bc")][ConsoleColor]$BackgroundColor = "Blue", [Alias("cc")][ConsoleColor]$CapturegroupColor = "Red", [Alias("fc")][ConsoleColor]$ForegroundColor = "White", [Alias("Q")][Switch]$Interactive = $False ) #$DebugPreference = "Continue" Function RegExS { <# .SYNOPSIS Regular-Expression text Search .DESCRIPTION This function searches for text patterns in multiple text files. Matched characters are highlighted. .PARAMETER Pattern Specifies the text to find. Type a string or regular expression. If you type a string, use the SimpleMatch parameter. .PARAMETER Dir Specifies the target folder in which search is performed. .PARAMETER Include Specifies the comma-delimited list of filenames to be searched. Wildcards may be used; e.g. "*.cpp, *.h". The default value is "*". .PARAMETER Encoding Specifies the character encoding for the files without a BOM. (Alias: -e) The default value is "String". .PARAMETER BackgroundColor Specifies the background color for matches. (Alias: -bc) The default value is "Blue". .PARAMETER CapturegroupColor Specifies the foreground color for capture-group matches. (Alias: -cc) The default value is "Red". .PARAMETER ForegroundColor Specifies the foreground color for matches. (Alias: -fc) The default value is "White". .PARAMETER Group Specifies the name or number of capture group. (Alias: -g) The default value is "0". .PARAMETER HtmlOutput Redirects output to a HTML file. (Alias: -h) .PARAMETER IgnoreCase Makes matches case-insensitive. By default, matches are case-sensitive. (Alias: -i) .PARAMETER Narrow Converts wide characters into narrow ones. (Alias: -n) Useful when you don't want to distinguish between narrow and wide characters. .PARAMETER Recurse Searches all files in all subfolders. (Alias: -r) .PARAMETER SimpleMatch Uses a simple match rather than a regular expression match. (Alias: -s) .PARAMETER Exclude Specifies the comma-delimited list of filenames to be excluded. (Alias: -x) Wildcards may be used; e.g. "*.img, *.dat". Note that the following binary format files are excluded by default: *.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png . .NOTES Author: earthdiver1 Version: V2.00 Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. #> param ( [String]$Pattern, [String]$Dir, [String]$Include = "*", [ValidateSet("", "Unknown", "String", "Unicode", "Byte", "BigEndianUnicode", ` "UTF8", "UTF7", "UTF32", "Ascii", "Default", "Oem", "BigEndianUTF32")] [Alias("e")][String]$Encoding = "Default", [Alias("x")][String]$Exclude = "", [Alias("g")][String]$Group = "0", [Alias("h")][Switch]$HtmlOutput, [Alias("i")][Switch]$IgnoreCase, [Alias("n")][Switch]$Narrow, [Alias("r")][Switch]$Recurse, [Alias("s")][Switch]$SimpleMatch, [Alias("bc")][ConsoleColor]$BackgroundColor = "Blue", [Alias("cc")][ConsoleColor]$CapturegroupColor = "Red", [Alias("fc")][ConsoleColor]$ForegroundColor = "White" ) ############ Edit Here ############ $BinaryFiles = "*.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png" $HtmlFile = "$($script:PSScriptRoot)\RegExS_Output.htm" # $HtmlFile = "$($script:PSScriptRoot)\RegExS_Output_$((Get-Date).ToString('yyyyMMddHHmm')).htm" ################################### if (-not $Pattern) { Write-Host "'Pattern' not specified" -Fore Red; Get-Help RegExS; return } if (-not $Dir) { Write-Host "'Dir' not specified." -Fore Red; Get-Help RegExS; return } $Dir = Convert-Path -LiteralPath $Dir if (-not $Dir) { Write-Host "'Dir' does not exist." -Fore Red; Get-Help RegExS; return } [Array]$IsContainer = Get-Item $Dir | %{ $_.PSIsContainer } if ((-not $Recurse) -and $IsContainer.Length -eq 1 -and $IsContainer[0]) { $Dir += "\*" } if ($SimpleMatch) { $Pattern = [regex]::Escape($Pattern) } if ($IgnoreCase) { $Pattern = "(?i)" + $Pattern } if ($HtmlOutput) { HtmlHeader } [String[]]$IncludeList = $Include -Split "," | %{ $_.Trim() } [String[]]$ExcludeList = ($Exclude + "," + $BinaryFiles) -Split "," | %{ $_.Trim() } | ?{ $_ } $global:ErrorView = "CategoryView" if ($IncludeList.Length -eq 1) { # "-Filter" is faster than "-Include" $files = Get-ChildItem $Dir -Filter $Include -Exclude $ExcludeList -Recurse:$Recurse -File } else { $files = Get-ChildItem $Dir -Include $IncludeList -Exclude $ExcludeList -Recurse:$Recurse -File } $global:ErrorView = "NormalView" $ErrorActionPreference = "Stop" trap [System.Exception] { Write-Host "Sytem error occurred." -Fore Red Write-Host $Error[0].ToString() $Error[0].InvocationInfo.PositionMessage if ($HtmlOutput) { HtmlFooter try { [Text.Encoding]::UTF8.GetBytes($script:Html.ToString()) | Set-Content -Path $HtmlFile -Encoding Byte # UTF-8N [void]$script:Html.Clear() } catch [System.Exception] {} } return } [Int]$Nmfile = 0 [Int]$Nmatch = 0 [Int]$Nmline = 0 [Int]$Nmchar = 0 if ($files) { foreach ($file in $files) { Write-Debug "RegExS: $($file.FullName)" try { $enc = GetEncodingFromBOM $file if (-not $enc) { if (IsBinary $file) { Write-Host "Skipping binary format file: $($file.FullName)." -Fore Green continue } $enc = $Encoding } $io = Get-Content $file.FullName -Encoding $enc -Raw } catch [System.UnauthorizedAccessException], ` [System.Management.Automation.ItemNotFoundException], ` [System.IO.IOException] { Write-Host "$($Error[0].Exception.Message) Continuing processing." -Fore Red if ($HtmlOutput) { [void]$script:Html.Append("$(Htmlify $Error[0].Exception.Message) Continuing processing.`n") } continue } if ($Narrow) { Add-Type -AssemblyName "Microsoft.VisualBasic" $tmpfile = [System.IO.Path]::GetTempFileName() [Microsoft.VisualBasic.Strings]::StrConv($io,[Microsoft.VisualBasic.VbStrConv]::Narrow) >> $tmpfile $Pattern = [Microsoft.VisualBasic.Strings]::StrConv($Pattern,[Microsoft.VisualBasic.VbStrConv]::Narrow) [Array]$Matches = Select-String -Pattern $Pattern -CaseSensitive -LiteralPath $tmpfile -Encoding $enc ` | ?{ $_.Matches.Groups.Name -eq $Group -and $_.Matches.Groups.Success } Remove-Item $tmpfile -Force } else { [Array]$Matches = Select-String -Pattern $Pattern -CaseSensitive -LiteralPath $file.FullName -Encoding $enc ` | ?{ $_.Matches.Groups.Name -eq $Group -and $_.Matches.Groups.Success } } if ($Matches) { $Nmfile++ Write-Host $file.FullName -Fore Yellow $Regex = New-Object System.Text.RegularExpressions.Regex $Pattern if (-not $HtmlOutput) { if ($Group -eq "0") { foreach ($mm in $Matches) { $Nmline++ Write-Host $("{0,5}:" -F $mm.LineNumber) -NoNewline $index = 0 $m = $Regex.Match($mm.Line, $index).Groups[0] while ($m.Success) { $Nmatch++ if ($m.Index -ge $mm.Line.Length) { break } if ($m.Length -gt 0) { $Nmchar += $m.Length Write-Host $mm.Line.SubString($index, $m.Index - $index) -NoNewline Write-Host $m.Value -Back $BackgroundColor -Fore $ForegroundColor -NoNewline $index = $m.Index + $m.Length } else { Write-Host $mm.Line.SubString($index, $m.Index - $index + 1) -NoNewline $index = $m.Index + 1 } $m = $Regex.Match($mm.Line, $index).Groups[0] } Write-Host $mm.Line.SubString($index) } } else { foreach ($mm in $Matches) { $Nmline++ Write-Host $("{0,5}:" -F $mm.LineNumber) -NoNewline $index = 0 $match = $Regex.Match($mm.Line, $index) $m = $match.Groups[$Group] while ($m.Success) { $Nmatch++ if ($m.Index -ge $mm.Line.Length) { break } $m0 = $match.Groups[0] if ($m0.Length -gt 0) { $Nmchar += $m.Length Write-Host $mm.Line.SubString($index, $m0.Index - $index) -NoNewline Write-Host $mm.Line.SubString($m0.Index, $m.Index - $m0.Index) ` -Back $BackgroundColor -Fore $ForegroundColor -NoNewline Write-Host $m.Value -Back $BackgroundColor -Fore $CapturegroupColor -NoNewline $index = $m0.Index + $m0.Length $i = $m.Index + $m.Length Write-Host $mm.Line.SubString($i, $index - $i) -Back $BackgroundColor -Fore $ForegroundColor -NoNewline } else { Write-Host $mm.Line.SubString($index, $m0.Index - $index + 1) -NoNewline $index = $m0.Index + 1 } $match = $Regex.Match($mm.Line, $index) $m = $match.Groups[$Group] } Write-Host $mm.Line.SubString($index) } } } else { [void]$script:Html.Append("$($file.FullName)`n") if ($Group -eq "0") { foreach ($mm in $Matches) { $Nmline++ [void]$script:Html.Append(("{0,5}:" -F $mm.LineNumber)) $index = 0 $m = $Regex.Match($mm.Line, $index).Groups[0] while ($m.Success) { $Nmatch++ if ($m.Index -ge $mm.Line.Length) { break } if ($m.Length -gt 0) { $Nmchar += $m.Length [void]$script:Html.Append((Htmlify $mm.Line.SubString($index, $m.Index - $index))) [void]$script:Html.Append("$(Htmlify $m.Value)") $index = $m.Index + $m.Length } else { [void]$script:Html.Append($(Htmlify $mm.Line.SubString($index, $m.Index - $index + 1))) $index = $m.Index + 1 } $m = $Regex.Match($mm.Line, $index).Groups[0] } [void]$script:Html.Append("$(Htmlify $mm.Line.SubString($index))`n") } } else { foreach ($mm in $Matches) { $Nmline++ [void]$script:Html.Append(("{0,5}:" -F $mm.LineNumber)) $index = 0 $match = $Regex.Match($mm.Line, $index) $m = $match.Groups[$Group] while ($m.Success) { $Nmatch++ if ($m.Index -ge $mm.Line.Length) { break } $m0 = $match.Groups[0] if ($m0.Length -gt 0) { $Nmchar += $m.Length [void]$script:Html.Append((Htmlify $mm.Line.SubString($index, $m0.Index - $index))) [void]$script:Html.Append("$(Htmlify $mm.Line.SubString($m0.Index, $m.Index - $m0.Index))") [void]$script:Html.Append("$(Htmlify $m.Value)") $index = $m0.Index + $m0.Length $i = $m.Index + $m.Length [void]$script:Html.Append("$(Htmlify $mm.Line.SubString($i, $index - $i))") } else { [void]$script:Html.Append($(Htmlify $mm.Line.SubString($index, $m0.Index - $index + 1))) $index = $m0.Index + 1 } $match = $Regex.Match($mm.Line, $index) $m = $match.Groups[$Group] } [void]$script:Html.Append("$(Htmlify $mm.Line.SubString($index))`n") } } } } } } Write-Host "$Nmfile file, $Nmline line, $Nmatch string, $Nmchar character matches found." -Fore Green if ($HtmlOutput) { [void]$script:Html.Append("$Nmfile file, $Nmline line, $Nmatch string, $Nmchar character matches found.`n") HtmlFooter try { [Text.Encoding]::UTF8.GetBytes($script:Html.ToString()) | Set-Content -Path $HtmlFile -Encoding Byte # UTF-8N [void]$script:Html.Clear() Write-Host "The result has been output to $HtmlFile." -Fore Green Start-Process -FilePath "file:///$HtmlFile" } catch [System.Exception] { Write-Host "failed to output a HTML file." -Fore Red Write-Host $Error[0].Exception.Message } } } Function IsBinary($File) { if ($File.Length -lt 2) { return $False } if ($File.Length -gt 20000000) { return $True } $bytes = Get-Content $File.FullName -ReadCount 4096 -TotalCount 4096 -Encoding Byte [Int]$Nbo=0 [Int]$Nbe=0 [Int]$Nzo=0 [Int]$Nze=0 for ([Int]$i=0; $i -lt $bytes.Length; $i+=2) { $Nbo++ if ($bytes[$i] -eq 0) { $Nzo++ } } for ([Int]$i=1; $i -lt $bytes.Length; $i+=2) { $Nbe++ if ($bytes[$i] -eq 0) { $Nze++ } } if (($Nzo+$Nze -gt 0) -and ([System.Math]::Abs($Nzo/$Nbo-$Nze/$Nbe)/($Nbo+$Nbe) -lt 0.1)) { return $True } Write-Debug "IsBinary: $($file.Name) $($Nzo+$Nze), $([System.Math]::Abs($Nzo/$Nbo-$Nze/$Nbe)/($Nbo+$Nbe))" return $False } Function GetEncodingFromBOM($File) { $bytes = Get-Content $File.FullName -ReadCount 4 -TotalCount 4 -Encoding Byte $string = ($bytes | %{ "{0:X2}" -F $_ }) -Join "" switch -Regex ($string) { "^EFBBBF" { $enc="UTF8" ; break } "^FFFE0000" { $enc="UTF32" ; break } "^FFFE" { $enc="Unicode" ; break } "^0000FEFF" { $enc="BigEndianUTF32" ; break } "^FEFF" { $enc="BigEndianUnicode" ; break } "^2B2F76(38|39|2B|2F)" { $enc="UTF7" ; break } Default { $enc="" } } Write-Debug "GetEncodingFromBOM: $($File.Name) $($string) $($enc)" return $enc } Function RGBColor([ConsoleColor]$Color) { switch -Exact ($Color) { "Black" { return "#000000" } "DarkBlue" { return "#000080" } "DarkGreen" { return "#008000" } "DarkCyan" { return "#008080" } "DarkRed" { return "#800000" } "DarkMagenta" { return "#012456" } "DarkYellow" { return "#EEEDF0" } "Gray" { return "#C0C0C0" } "DarkGray" { return "#808080" } "Blue" { return "#0000FF" } "Green" { return "#008000" } "Cyan" { return "#00FFFF" } "Red" { return "#FF0000" } "Magenta" { return "#FF00FF" } "Yellow" { return "#FFFF00" } "White" { return "#FFFFFF" } Default { return "" } } } Function HtmlHeader() { $script:Html = New-Object System.Text.StringBuilder [void]$script:Html.Append("`n") [void]$script:Html.Append("`n") # <- You may want to change this [void]$script:Html.Append("`n") [void]$script:Html.Append("`n") [void]$script:Html.Append("RegExS Output`n") [void]$script:Html.Append("`n") [void]$script:Html.Append("`n`n
`n")
}

Function HtmlFooter() {
    [void]$script:Html.Append("
`n`n") } Function Htmlify($t) { $t = $t -Replace "&", "&" $t = $t -Replace ">", ">" $t = $t -Replace "<", "<" $t = $t -Replace """", """ return $t } Function Pause_and_Exit() { Write-Host "Press any key to exit . . ." -Fore Green $Host.UI.RawUI.FlushInputBuffer() $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") | Out-Null exit } Function Main() { if ($DoubleClicked) { $Interactive = $True } if ($Interactive) { if ($Pattern) { Write-Host "Enter a search text. [$Pattern]:" -NoNewline -Fore Green $Answer = "" try { $Answer = Read-Host } catch [System.Exception] {} if ($Answer) { $Pattern = $Answer } } else { Write-Host "Enter a search text.:" -NoNewline -Fore Green try { $Pattern = Read-Host } catch [System.Exception] {} if (-not $Pattern) { Pause_and_Exit } } Write-Host "Enter a capture-group name or number. [$Group]:" -NoNewline -Fore Green $Answer = "" try { $Answer = (Read-Host).Trim() } catch [System.Exception] {} if ($Answer) { $Group = $Answer } Write-Host "Select a target folder." -Fore Green Add-Type -AssemblyName System.Windows.Forms $fbd = New-Object System.Windows.Forms.FolderBrowserDialog $fbd.ShowNewFolderButton = $false $fbd.Description = "Select a target folder." if ($Dir -and (Test-Path -LiteralPath $Dir)) { $fbd.SelectedPath = Convert-Path -LiteralPath $Dir } else { $fbd.SelectedPath = [string]$PWD } $Result = $fbd.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true})) if ($Result -eq [System.Windows.Forms.DialogResult]::OK) { $Dir = $fbd.SelectedPath } else { Write-Host "invalid input" -Fore Red; Pause_and_Exit } $fbd.Dispose() #Begin Get-WindowFocus Add-Type @" using System; using System.Runtime.InteropServices; public class SFW { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); } "@ $PPID=$PID For ([Int]$i=0; $i -lt 2; $i++) { $PPID=(Get-WmiObject Win32_Process -Filter "ProcessID=$PPID").ParentProcessID try { $WindowTitle = (Get-Process -ID $PPID -ErrorAction SilentlyContinue).MainWindowTitle $WindowHandle = (Get-Process -ID $PPID -ErrorAction SilentlyContinue).MainWindowHandle if ($WindowTitle) { [void][SFW]::SetForegroundWindow($WindowHandle) break } } catch [System.Exception] { break } } #End Get-WindowFocus Write-Host "Include sub-folders? Y/N [$(if($Recurse){"Y"}else{"N"})]:" -NoNewline -Fore Green try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} switch ($Answer) { "Y" { $Recurse = $True } "N" { $Recurse = $False } "" { } default { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } Write-Host "Enter file names. (wildcard allowed) [$Include]:" -NoNewline -Fore Green $Answer = "" try { $Answer = (Read-Host).Trim() } catch [System.Exception] {} if ($Answer) { $Include = $Answer } Write-Host "Specify the other options? Y/N [N]:" -NoNewline -Fore Green $Answer = "" try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} if ($Answer -eq "Y") { Write-Host "Output the search result to a HTML file? Y/N [$(if($HtmlOutput){"Y"}else{"N"})]:" -NoNewline -Fore Green try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} switch ($Answer) { "Y" { $HtmlOutput = $True } "N" { $HtmlOutput = $False } "" { } default { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } Write-Host "Disable regular expression search? Y/N [$(if($SimpleMatch){"Y"}else{"N"})]:" -NoNewline -Fore Green try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} switch ($Answer) { "Y" { $SimpleMatch = $True } "N" { $SimpleMatch = $False } "" { } default { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } Write-Host "Ignore upper/lower cases? Y/N [$(if($IgnoreCase){"Y"}else{"N"})]:" -NoNewline -Fore Green try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} switch ($Answer) { "Y" { $IgnoreCase = $True } "N" { $IgnoreCase = $False } "" { } default { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } Write-Host "Convert wide characters into narrow ones before search? Y/N [$(if($Narrow){"Y"}else{"N"})]:" -NoNewline -Fore Green try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {} switch ($Answer) { "Y" { $Narrow = $True } "N" { $Narrow = $False } "" { } default { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } Write-Host "Enter file names to be excluded. (wildcard allowed) [$Exclude]:" -NoNewline -Fore Green $Answer = "" try { $Answer = (Read-Host).Trim() } catch [System.Exception] {} if ($Answer) { $Exclude = $Answer } Write-Host "Enter a character encoding for the files without BOMs. [$Encoding]:" -NoNewline -Fore Green $Answer = "" try { $Answer = (Read-Host).Trim() } catch [System.Exception] {} if ($Answer) { $Encoding = $Answer $EncodingList = @("unkown", "string", "unicode", "byte", "bigendianunicode", ` "utf8", "utf7", "utf32", "ascii", "default", "oem", "bigendianutf32") if (-not ($EncodingList -Contains $Encoding.ToLower())) { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } } elseif ($Answer -ne "N" -and $Answer -ne "") { Write-Host "invalid input" -Fore Red; Pause_and_Exit } } RegExS $Pattern $Dir $Include -e $Encoding -g $Group -h:$HtmlOutput -i:$IgnoreCase -n:$Narrow -r:$Recurse ` -s:$SimpleMatch -x $Exclude ` -bc $BackgroundColor -cc $CapturegroupColor -fc $ForegroundColor if ($Interactive) { Pause_and_Exit } } Main