Show-ScriptCop.ps1

function Show-ScriptCop 
{            
    <#
    .Synopsis
        Shows a tool for helping you walk thru ScriptCop results
    .Description
        Shows a tool for helping you walk thru ScriptCop results.
         
        Show-ScriptCop was written using ShowUI. http://ShowUI.Codeplex.Com
    .Example
        Show-ScriptCop -AsJob
    .Link
        http://showui.codeplex.com/
    #>

    [OutputType([Windows.Controls.Border])]            
    param(
    # If set, runs ScriptCop full screen
    [Switch]$FullScreen,             
                
    # The name of the control
    [string]$Name,            
    # If the control is a child element of a Grid control (see New-Grid),
    # then the Row parameter will be used to determine where to place the
    # top of the control. Using the -Row parameter changes the
    # dependency property [Windows.Controls.Grid]::RowProperty
    [Int]$Row,            
    # If the control is a child element of a Grid control (see New-Grid)
    # then the Column parameter will be used to determine where to place
    # the left of the control. Using the -Column parameter changes the
    # dependency property [Windows.Controls.Grid]::ColumnProperty
    [Int]$Column,            
    # If the control is a child element of a Grid control (see New-Grid)
    # then the RowSpan parameter will be used to determine how many rows
    # in the grid the control will occupy. Using the -RowSpan parameter
    # changes the dependency property [Windows.Controls.Grid]::RowSpanProperty
    [Int]$RowSpan,            
    # If the control is a child element of a Grid control (see New-Grid)
    # then the RowSpan parameter will be used to determine how many columns
    # in the grid the control will occupy. Using the -ColumnSpan parameter
    # changes the dependency property [Windows.Controls.Grid]::ColumnSpanProperty
    [Int]$ColumnSpan,            
    # The -Width parameter will be used to set the width of the control
    [Int]$Width,             
    # The -Height parameter will be used to set the height of the control
    [Int]$Height,            
    # If the control is a child element of a Canvas control (see New-Canvas),
    # then the Top parameter controls the top location within that canvas
    # Using the -Top parameter changes the dependency property
    # [Windows.Controls.Canvas]::TopProperty
    [Double]$Top,            
    # If the control is a child element of a Canvas control (see New-Canvas),
    # then the Left parameter controls the left location within that canvas
    # Using the -Left parameter changes the dependency property
    # [Windows.Controls.Canvas]::LeftProperty
    [Double]$Left,            
    # If the control is a child element of a Dock control (see New-Dock),
    # then the Dock parameter controls the dock style within that panel
    # Using the -Dock parameter changes the dependency property
    # [Windows.Controls.DockPanel]::DockProperty
    [Windows.Controls.Dock]$Dock,            
    # If Show is set, then the UI will be displayed as a modal dialog within the current
    # thread. If the -Show and -AsJob parameters are omitted, then the control should be
    # output from the function
    [Switch]$Show,            
    # If AsJob is set, then the UI will displayed within a WPF job.
    [Switch]$AsJob            
            
    )            
                
    process {            
        $uiParameters = @{} + $psBoundParameters
        $uiParameters.Remove('FullScreen')
        $psBoundParameters.FullScreen  =$fullScreen    
        
        $globalLoadedModules = Get-Module | 
            Where-Object { 
                $env:PSModulePath -split ";" -contains (Split-Path (Split-Path -Path $_.Path))        
            } | Select-Object -ExpandProperty Name
       
            
        New-Border @uiParameters -ControlName Show-ScriptCop -HorizontalAlignment Stretch -VerticalAlignment Stretch -Resource @{                       
            ErrorUpdater = {
                $errors = Get-PowerShellOutput -ErrorOnly -Last
                $ErrorHolder.Visibility = 'Visible'
                $ErrorHolder.Content = $errors | Out-String -Width 1kb
            }
            GlobalLoadedModules = $globalLoadedModules
            Powershell_Ise = $psise
            PowerGui = $PGSE
        } -On_SizeChanged {                      
            if ($_.PreviousSize.Width -ne 0 -or $_.PreviousSize.Height -ne 0) {
                return
            }
            $sb= {param([string[]]$globalLoadedModules)
                Import-Module $globalLoadedModules
                Import-Module ScriptCop
                New-Object PSObject -Property @{
                    ModulesAvailable= @(Get-Module -ListAvailable)
                    CommandsAvailable=  Get-Command -CommandType Cmdlet, Function
                    Patrols = Get-ScriptCopPatrol
                    Rules = Get-ScriptCopRule
                }             
            }
            
            Invoke-Background -Parameter @{
                GlobalLoadedModules = $globalLoadedModules
            } -ScriptBlock $sb -control $parent -On_OutputChanged {
                $lastOut = Get-PowerShellOutput -Last -OutputOnly    
                if ($lastOut.ModulesAvailable -as [Management.Automation.PSModuleInfo[]]) {
                    # It's a module, update the module tree
                    foreach ($module in $lastOut.ModulesAvailable) {
                        $moduleExists = foreach ($m in $moduleTree.Items) {if ($m.Header -eq "$module") { $m }}
                        if ($moduleExists) {
                        } else {
                            $newTreeViewItem = 
                                New-TreeViewItem -Header "$module" -Tag $module -Items {
                                    foreach ($exc in $module.ExportedCommands.Values) {
                                        if (-not $exc) { continue } 
                                        New-TreeViewItem -Header "$exc" -Tag $exc 
                                    }
                                }
                            $moduleTree.Items.add($newTreeViewItem)
                            $moduleTree.UpdateLayout()
                        }
                    }
                }
                if ($lastOut.Patrols) {
                    $patrolComboBox.ItemsSource = @("") + @($lastOut.Patrols | Select-Object -ExpandProperty Name)
                }
                if ($lastOut.Rules) {
                    $ruleComboBox.ItemsSource = @("") + @($lastOut.Rules | Select-Object -ExpandProperty Name) 
                }
            } -On_ProgressChanged {
                $lastOut = Get-PowerShellOutput -Last -ProgressOnly
                if ($lastOut.RecordType -ne 'Completed') {
                    $ProgressHolder.Visibility = 'Visible'
                    $progressHolder.DataContext = $lastOut
                } else {
                    $ProgressHolder.Visibility = 'Collapsed'
                }
            } -On_ErrorChanged $ErrorUpdater 
        } -Child {
            New-Grid -MinWidth 640 -MinHeight 640 -Name ScriptCopGrid -Columns 2*, 'Auto', 10* -Rows '10*', 'Auto', '1*','Auto','Auto' -Children {

                New-TreeView -MaxWidth 640 -MaxHeight 640 -Name ModuleTree -On_SelectedItemChanged {
                    $runScriptCop.IsEnabled = $this.SelectedItem
                }                    
                
                New-GridSplitter -Column 1 -VerticalAlignment Stretch -HorizontalAlignment Center -Background Black -Width 2.5 -ShowsPreview                
                New-ListBox -On_MouseDoubleClick { 
                    if ($this.SelectedItem) {
                        $file = $this.SelectedItem.ItemWithProblem.ScriptBlock.File
                        if ($file) {
                            if ($powershell_ise) {
                                $powershell_ise.CurrentPowerShellTab.Files.Add($file)
                            } elseif ($powergui) {
                                $powergui.DocumentWindows.add($file)
                            }
                        }
                    }
                } -MaxWidth 640 -MaxHeight 640 -Visibility Collapsed -Column 2 -Name ScriptCopResults -ItemTemplate {
                    New-StackPanel -Orientation Horizontal -MaxWidth 640 -Children { 
                        New-TextBlock -Name "ItemWithProblem" -FontWeight DemiBold
                        New-TextBlock ":"
                        New-TextBlock -Name "Problem" -TextWrapping Wrap 
                    } | ConvertTo-DataTemplate @{
                        "ItemWithProblem.Text" = "ItemWithProblem"
                        "Problem.Text" = "Problem"
                    }
                } 
                New-GridSplitter -ColumnSpan 3 -Row 1 -VerticalAlignment Center -HorizontalAlignment Stretch -Background Black -Height 2.5 -ShowsPreview
                New-Grid -Name ToolbarGrid -Row 2 -ColumnSpan 3 -Columns 3 -Children {
                    New-Button -Name RunScriptCop -Margin 5 -Column 1 "Run ScriptCop" -On_Click {
                        $ScriptCopResults.Visibility = 'Visible'
                        $invokeBackgroundParameters = @{
                            Control = $parent
                            On_ProgressChanged =  {
                                $progress = Get-PowerShellOutput -Last -ProgressOnly
                                $statusDescription.Text = $progress.StatusDescription
                                $activityText.Text = $progress.activity
                                $progressPercent.Value = $progress.percentComplete
                                $progressHolder.UpdateLayout()
                            }
                            On_OutputChanged = {
                                $results = Get-PowerShellOutput -Last -OutputOnly
                                $progressHolder.Visibility = 'Collapsed'
                                $ScriptCopResults.ItemsSource = @($results.ScriptCopResults)
                                
                                if ($results.Module) {
                                    foreach ($it in $moduleTree.Items) {
                                        if ($it.header -eq "$($results.Module)") {
                                            $it.Items.Clear()
                                            $it.Tag = $results.Module
                                            foreach ($exc in $results.module.ExportedCommands.Values) {
                                                if (-not $exc) { continue }
                                                $tvi = New-TreeViewItem -Header "$exc" -Tag $exc 
                                                $it.Items.Add($tvi)
                                            }
                                            
                                            break
                                        }
                                    }
                                }                                                                  
                                $ScriptCopResults.UpdateLayout()                                                                                                                      
                            }
                            On_ErrorChanged = $errorUpdater                            
                        }
                        if ($moduleTree.SelectedItem.Tag -is [Management.Automation.PSModuleInfo]) {
                            $ProgressHolder.Visibility = 'Visible'
                            Invoke-Background @invokeBackgroundParameters -ScriptBlock {
                                param($moduleName, $patrol = "", $rule = "")
                                Import-Module ScriptCop
                                $results = Import-Module $moduleName -Force -PassThru | 
                                    Test-Command -Patrol $patrol -Rule $rule 
                                New-Object PSObject -Property @{
                                    ScriptCopResults = $results                                
                                    Module = Get-Module $ModuleName 
                                }
                            } -Parameter @{
                                moduleName =  $moduleTree.SelectedItem.Tag.Name 
                                rule = $ruleComboBox.Text
                                patrol = $patrolComboBox.Text
                            } 
                        }
                        
                        if ($moduleTree.SelectedItem.Tag -is [Management.Automation.CommandInfo]) {
                            $ProgressHolder.Visibility = 'Visible'
                            Invoke-Background @invokeBackgroundParameters  -ScriptBlock {
                                param($commandName, $patrol = "", $rule = "")
                                Import-Module ScriptCop
                                New-Object PSObject -Property @{
                                    ScriptCopResults=  Get-Command $commandName | 
                                        Test-Command -patrol $patrol -rule $rule                                                                   
                                }                                
                            } -Parameter @{
                                CommandName =  $moduleTree.SelectedItem.Tag.Name 
                                Patrol = $patrol.Text
                                Rule = $rule
                            } -On_ProgressChanged $ProgressUpdater -On_ErrorChanged $ErrorUpdater
                        }                                                
                    }
                    New-UniformGrid -Column 2 -Columns 2 -Rows 2 {
                        "Patrol" 
                        New-ComboBox -Name PatrolComboBox
                        "Rule" 
                        New-ComboBox -Name RuleComboBox
                    }
                }
                
                
                New-Label -Foreground Red -ColumnSpan 3 -Row 3 -Name ErrorHolder -Visibility Collapsed 
                New-Grid -ColumnSpan 3 -Row 4 -Name ProgressHolder -Visibility Collapsed -Children {
                    New-TextBlock -Margin 10 -Name ActivityText -TextWrapping Wrap -ZIndex 1 -HorizontalAlignment Left -FontWeight Bold -FontSize 12 -DataBinding @{            
                        "Text" = "Activity"            
                    }            
                    New-TextBlock -Margin 10 -ZIndex 1 -Name StatusDescription -TextWrapping Wrap -Column 1 -VerticalAlignment Bottom -HorizontalAlignment Right -FontStyle Italic -FontSize 12 -DataBinding @{            
                        "Text" = "StatusDescription"            
                    }            
                    New-ProgressBar -ColumnSpan 2 -Name ProgressPercent -DataBinding @{            
                        "Value" = "PercentComplete"            
                    }            
                }
            }
        }
    }            
}