functions/Export-AzScriptReport.ps1
function Export-AzScriptReport { <# .SYNOPSIS Exports the results of Read-AzScriptFile to csv or xlsx. .DESCRIPTION Exports the results of Read-AzScriptFile to csv or xlsx. It reformats some of the data and eliminates linebreaks in the "Before" column. In order to generate xlsx files, the additional module "ImportExcel" is required. .PARAMETER Path The path where to write the report to. May be a relative path, must include the filename. The parent folder must already exist. .PARAMETER Delimiter Which delimiter to use when generating a CSV file. Defaults to the current culture, but may be overridden as needed. This affects whether you can open the file in Excel by simple doubleclick or whether you need to first import the data. .PARAMETER ScriptPath The path where to write converted scripts. Specifying this parameter will save the scanned files to disk, with commands renamed to their new name. THESE SCRIPTS WILL NOT WORK!! This is a starting aid to help migrating, but commands do not always work the same way, may need different parameters or even map to two different vommands, depending on use. .PARAMETER InputObject The report objects from Read-AzScriptFile to export. .EXAMPLE PS C:\> Get-ChildItem C:\scripts -Recurse -Filter *.ps1 | Read-AzScriptFile | Export-AzScriptReport -Path .\report.csv Will search all PowerShell code under C:\scripts, search it for AzureAD and MSOnline commands and then export the finidngs to .\report.csv. #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory = $true)] [PsfValidateScript('PSFramework.Validate.FSPath.FileOrParent', ErrorString = 'PSFramework.Validate.FSPath.FileOrParent')] [string] $Path, [string] $Delimiter = (Get-PSFConfigValue -FullName 'PSAzureMigrationAdvisor.Export.CsvDelimiter'), [PsfValidateScript('PSFramework.Validate.FSPath.Folder', ErrorString = 'PSFramework.Validate.FSPath.Folder')] [string] $ScriptPath, [Parameter(ValueFromPipeline = $true)] $InputObject ) begin { #region Functions function Write-ScriptFile { [CmdletBinding()] param ( [string] $ScriptPath, $Result, $Item, $Delimiter ) # Already Saved $doSave = $true if ($Item._ScriptFile.Path -like "$ScriptPath*") { $doSave = $false } $newFileName = '{0}-{1}.{2}' -f ((Split-Path $datum.Path -Leaf) -replace '\.[^\.]+'), $Result.FileHash, ((Split-Path $datum.Path -Leaf) -replace '^.+\.') -replace '\[[^\[\]]+\]$' $newFilePath = Join-PSFPath $ScriptPath $newFileName if ($Result.Branch) { $newFilePath = Join-PSFPath $ScriptPath $Result.Organization $Result.Project $Result.Repository $Result.Branch $newFileName } $parentPath = Split-Path -Path $newFilePath if (-not (Test-Path -Path $parentPath)) { $null = New-Item -Path $parentPath -ItemType Directory -Force -ErrorAction Stop } $reportPath = Join-Path -Path $parentPath -ChildPath 'findings.csv' $Result | Export-Csv -Path $reportPath -NoTypeInformation -Append -Delimiter $Delimiter if (-not $doSave) { return } $Item._ScriptFile.Path = $newFilePath $Item._ScriptFile.Save() } #endregion Functions if ($ScriptPath) { $ScriptPath = Resolve-PSFPath -Path $ScriptPath } $useExcel = $Path -like "*.xlsx" if ($useExcel -and -not (Get-Command Export-Excel -ErrorAction Ignore)) { Stop-PSFFunction -String 'Export-AzScriptReport.NoExcel' -EnableException $true -Cmdlet $PSCmdlet } if ($useExcel) { $steppable = { Export-Excel -Path $Path }.GetSteppablePipeline() } else { $param = @{ Path = $Path } if ($Delimiter) { $param.Delimiter = $Delimiter } else { $param.UseCulture = $true } $steppable = { Export-Csv @param }.GetSteppablePipeline() } try { $steppable.Begin($true) } catch { Stop-PSFFunction -String 'Export-AzScriptReport.Export.Failed' -StringValues $Path -ErrorRecord $_ -EnableException $true -Cmdlet $PSCmdlet } # Ensure mappings for graph commands exist if (0 -eq $script:migrationCommandMapping.Count) { Import-MappingFile } } process { foreach ($datum in $InputObject) { #region Process Messages # Note: This approach breaks down for messages that had multiple lines $msgInfo = @() $msgWarning = @() $msgError = @() $msgTypes = $datum.MessageType -split "`n" $messages = $datum.Message -split "`n" if ($msgTypes) { foreach ($index in 0..$msgTypes.Count) { switch (($msgTypes)[$index]) { 'Info' { $msgInfo += $messages[$index] } 'Information' { $msgInfo += $messages[$index] } 'Warning' { $msgWarning += $messages[$index] } 'Error' { $msgError += $messages[$index] } } } } #endregion Process Messages $mapped = $script:migrationCommandMapping.$($datum.Command) $result = [PSCustomObject][ordered]@{ Path = $datum.Path Command = $datum.Command CommandLine = $datum.CommandLine Before = $datum.Before -replace "``[`r`n]+" -replace '\s+', ' ' # Eliminate backticks and linebreaks After = $datum.After GraphCommand = $mapped.NewCommand GraphModule = $mapped.NewCommandModule MsgInfo = $msgInfo -join " " MsgWarning = $msgWarning -join " " MsgError = $msgError -join " " FileHash = $datum.Filehash MessageType = $datum.MessageType # Keep in the full dataset, just in case somebody includes multiline messages Messages = $datum.Message ScopesDelegate = $mapped.ScopesDelegate -join ',' ScopesApplication = $mapped.ScopesApplication -join ',' Examples = $mapped.LinkExamples -join ', ' OnlineMapping = 'https://github.com/microsoft/AzureAD-to-MSGraph/blob/main/docs/{0}/{1}.md' -f $mapped.Module, $mapped.Name Organization = $datum.Organization Project = $datum.Project Repository = $datum.Repository Branch = $datum.Branch } $steppable.Process($result) if ($ScriptPath) { try { Write-ScriptFile -ScriptPath $ScriptPath -Result $result -Item $datum -Delimiter $Delimiter } catch { Write-PSFMessage -Level Error -String 'Export-AzScriptReport.ExportScript.Failed' -StringValues $result.Path -Target $result -ErrorRecord $_ -PSCmdlet $PSCmdlet } } } } end { $steppable.End() } } |