Write-CustomAction.ps1

function Write-CustomAction
{
    [CmdletBinding(DefaultParameterSetName='Action')]
    param(
    # The script block used to fill in the contents of a custom control.
    # The script block can either be an arbitrary script, which will be run, or it can include a
    # number of speicalized commands that will translate into parts of the formatter.
    [Parameter(ParameterSetName='Action',
        Mandatory=$true,
        ValueFromPipelineByPropertyName=$true)]
    [ScriptBlock[]]
    $Action,
    
    # The indentation depth of the custom control
    [Parameter(ParameterSetName='Action',
        ValueFromPipelineByPropertyName=$true)]
    [int]
    $Indent,

    # If set, the content will be created as a control, which can be used
    [Parameter(ParameterSetName='Action',ValueFromPipelineByPropertyName=$true)]
    [Switch]$AsControl,
    
    # The name of the action
    [Parameter(ParameterSetName='Action',ValueFromPipelineByPropertyName=$true)]    
    [String]$Name,
        
    # The VisibilityCondition parameter is used to add a condition that will determine
    # if the content will be rendered.
    [ScriptBlock[]]$VisibilityCondition = {}
    )
    
    process {
$header = @"
        <CustomControl>
            <CustomEntries>
                <CustomEntry>
                  <CustomItem>
                    <Frame>
                    $(if ($Indent) { "<LeftIndent>$Indent</LeftIndent>" } )
<CustomItem>
"@


$footer = @"
</CustomItem>
                    </Frame>
                    </CustomItem>
                </CustomEntry>
            </CustomEntries>
        </CustomControl>
"@
        


            $c =0
            $middle = foreach ($sb in $Action) {                 
                $VisibilityXml =""                
                if ("$($VisibilityCondition[$c])") {
                    $VisibilityXml = "<ItemSelectionCondition><ScriptBlock>
$([Security.SecurityElement]::Escape($VisibilityCondition[$c]))
</ScriptBlock></ItemSelectionCondition>"

                }
                $c++
                $tokens = @([Management.Automation.PSParser]::Tokenize($sb, [ref]$null) | 
                    Where-Object { "Comment", "NewLine" -notcontains $_.Type })
                Write-Verbose "$($tokens | Out-String)"
                if ($tokens.Count -eq 1) {
                    if ($tokens[0].Type -eq "Command" -and $tokens[0].Content -ieq "Write-Newline") {
                        "<NewLine />"
                    } elseif ($tokens[0].Type -eq "String") {
                        $content = $tokens[0].Content
                        # If the expanded size is the same as the original size, then the string most likely didn't
                        # contain expansion, and we can write out a text field instead
                        if (-not ($content.Contains('$'))) {
                            "<Text>$([Security.SecurityElement]::Escape($content))</Text>"
                        } else {
                            "<ExpressionBinding>
                                $VisibilityXml
                                <ScriptBlock>`"$([Security.SecurityElement]::Escape($content))`"</ScriptBlock>
                            </ExpressionBinding>"

                        }
                    } else {
                        "<ExpressionBinding>
                            $VisibilityXml
                            <ScriptBlock>$([Security.SecurityElement]::Escape($sb))</ScriptBlock>
                        </ExpressionBinding>"
                    
                    }
                } elseif ($tokens[0].Type -eq "Command" -and $tokens[0].Content -eq "Show-CustomAction") {
                    # If the script block was Expand-FormatView go ahead and run it
                    $result = & $sb
                    if ($result) {
                        $result.Insert("<ExpressionBinding>".Length + 1, $VisibilityXml)
                    }
                } else {
                    "<ExpressionBinding>
                        $VisibilityXml
                        <ScriptBlock>$([Security.SecurityElement]::Escape($sb))</ScriptBlock>
                    </ExpressionBinding>"
                
                }                
            }
            if (-not $AsControl) {
                $header + $middle + $footer           
            } else {
                if (-not $Name) {
                    Write-Error "Custom Controls must be named"
                    return
                }
                
                "<Control><Name>$Name</Name>" + $header + $middle + $footer + "</Control>"
            }
    }
}