iainbrighton / PScribo

PowerShell documentation framework
MIT License
230 stars 35 forks source link

Feature Request: WriteLog as public function #89

Closed mc1903 closed 5 years ago

mc1903 commented 5 years ago

Would it be possible to expose WriteLog as a public function, so I can inject my own status messages into the PScribo output log, whilst keeping the same look & feel?

I have a few processes that take over 30 seconds to complete and currently I can find no way of informing the user this is normal/expected behaviour and that the script has not hung up.

Cheers Martin

iainbrighton commented 5 years ago

Hi @mc1903 , would the following work?

$pscribo = Import-Module PScribo -Force -PassThru
$document = Document CallInternalFunction { 
    ## Call internal WriteLog function
    & $pscribo { WriteLog -Message "Hello World!" }
} -Verbose

VERBOSE: [ 08:09:28:379 ] [ Document ] - Document 'CallInternalFunction' processing started.
VERBOSE: [ 08:09:28:440 ] [ Document ] - Hello World!
VERBOSE: [ 08:09:28:442 ] [ Document ] - Document 'CallInternalFunction' processing completed.
VERBOSE: [ 08:09:28:443 ] [ Document ] - Total processing time '0.06' seconds.
mc1903 commented 5 years ago

Morning Iain,

Yes please; the current WriteLog function just needs to be exported as a function.

I have tested that it works by adding 'WriteLog' to the list of $exportedFunctions/FunctionsToExport in the v0.7.24.122 .psm1/.psd1 files and then re-importing the module.

I am writing a new AsBuiltReport report module and, as the AsBuiltReport.Core module installs PScribo as a dependency via PowerShell Gallery, I don't want to fork and create my own modified version of PScribo; as it would need to be manually installed and this would be a PITA.

Thank you for your help.

Cheers, Martin

iainbrighton commented 5 years ago

@mc1903 That example works today - without any modification?!

mc1903 commented 5 years ago

Confused.

Your example from this morning worked with v0.7.24.122, but If I call WriteLog from my script it errors unless, I export it as I have previously mentioned.

Could you give a example of how I would call it in context of your Demo01.ps1 example script.

Cheers Martin

iainbrighton commented 5 years ago

Sure thing!

param ([System.Management.Automation.SwitchParameter] $PassThru)

$pscribo = Import-Module PScribo -PassThru ## << You need to use -PassThru to get the module's context (System.Management.Automation.PSModuleInfo)

<# The document name is used in the file output #>
$document = Document 'PScribo Demo 1' -Verbose {
    TOC -Name 'Table of Contents';
    PageBreak;

    <# WARNING:
        Microsoft Word will include paragraphs styled with 'Heading*' style names to the TOC.
        To avoid this, define an identical style with a name not beginning with 'Heading'!
    #>
    Paragraph -Style Heading1 'This is Heading 1'
    Paragraph -Style Heading2 'This is Heading 2'
    Paragraph -Style Heading3 'This is Heading 3'
    Paragraph 'This is a regular line of text indented 0 tab stops'
    Paragraph -Tabs 1 'This is a regular line of text indented 1 tab stops. This text should not be displayed as a hanging indent, e.g. not just the first line of the paragraph indented.'
    Paragraph -Tabs 2 'This is a regular line of text indented 2 tab stops'
    Paragraph -Tabs 3 'This is a regular line of text indented 3 tab stops'
    Paragraph 'This is a regular line of text in the default font in italics' -Italic
    Paragraph 'This is a regular line of text in the default font in bold' -Bold
    Paragraph 'This is a regular line of text in the default font in bold italics' -Bold -Italic
    Paragraph 'This is a regular line of text in the default font in 14 point' -Size 14
    Paragraph 'This is a regular line of text in Courier New font' -Font 'Courier New'
    Paragraph "This is a regular line of text indented 0 tab stops with the computer name as data: $env:COMPUTERNAME"
    Paragraph "This is a regular line of text indented 0 tab stops with the computer name as data in bold: $env:COMPUTERNAME" -Bold
    Paragraph "This is a regular line of text indented 0 tab stops with the computer name as data in bold italics: $env:COMPUTERNAME" -Bold -Italic
    Paragraph "This is a regular line of text indented 0 tab stops with the computer name as data in 14 point bold italics: $env:COMPUTERNAME" -Bold -Italic -Size 14
    Paragraph "This is a regular line of text indented 0 tab stops with the computer name as data in 8 point Courier New bold italics: $env:COMPUTERNAME" -Bold -Italic -Size 8 -Font 'Courier New'

    & $pscribo { WriteLog -Message "Getting services..." } ## << This calls the function within the module's scope (gathered above)

    $services = Get-CimInstance -ClassName Win32_Service | Select-Object -Property DisplayName, State, StartMode | Sort-Object -Property DisplayName
    <# Add a custom style for highlighting table cells/rows #>
    Style -Name 'Stopped Service' -Color White -BackgroundColor Firebrick -Bold

    <#  Sections provide an easy way of creating a document structure and can support automatic
        section numbering (if enabled with the DocumentOption -EnableSectionNumbering parameter. You
        don't need to worry about the numbers - PScribo will automatically figure this out. #>
    Section -Style Heading1 'Standard-Style Tables' {
        Section -Style Heading2 'Autofit Width Autofit Cell No Highlighting' {
            Paragraph -Style Heading3 'Example of an autofit table width, autofit contents and no cell highlighting.'
            Paragraph "Services ($($services.Count) Services found):"
            $services | Table -Columns DisplayName,State,StartMode -Headers 'Display Name','Status','Startup Type' -Width 0
        }
        PageBreak
        Section -Style Heading2 'Full Width Autofit Cell Highlighting' {
            Paragraph -Style Heading3 'Example of a full width table with autofit columns and individual cell highlighting.'
            Paragraph "Services ($($services.Count) Services found):"
            <# Highlight individual cells with "StoppedService" style where state = stopped and startup = auto #>
            $stoppedAutoServicesCell = $services.Clone()
            $stoppedAutoServicesCell | Where { $_.State -eq 'Stopped' -and $_.StartMode -eq 'Auto'} | Set-Style -Property State -Style StoppedService
            $stoppedAutoServicesCell | Table -Columns DisplayName,State,StartMode -Headers 'Display Name','Status','Startup Type' -Tabs 1
        }

        PageBreak
        Section -Style Heading2 'Full Width Fixed Row Highlighting' {
            Paragraph -Style Heading3 'Example of a full width table with fixed columns widths and full row highlighting.'
            Paragraph "Services ($($services.Count) Services found)"
            <# Highlight an entire row with the "StoppedService" style where state = stopped and startup = auto #>
            $stoppedAutoServicesRow = $services.Clone()
            $stoppedAutoServicesRow | Where { $_.State -eq 'Stopped' -and $_.StartMode -eq 'Auto' } | Set-Style -Style StoppedService
            $stoppedAutoServicesRow | Table -Columns DisplayName,State,StartMode -ColumnWidths 70,15,15 -Headers 'Display Name','Status','Startup Type'
        }
    }

    PageBreak
    $listServices = Get-Service | Select -Property Name,CanPauseAndContinue,CanShutdown,CanStop,DisplayName,ServiceName,ServiceType,Status -First 2
    $listServices | Set-Style -Style StoppedService -Property ServiceType -Verbose

    Section -Style Heading1 'List-Style Tables' {
        Section -Style Heading2 'Autofit Width Autofit Cell No Highlighting' {
            $listServices | Table -Name 'AutofitWidth-AutofitCell-NoHighlighting' -List -Width 0
        }

        Section -Style Heading2 'Fixed Width Autofit Cell No Highlighting' {
            <#  You can include any standard Powershell code to enumerate and/or iterate over
                collections to create multiple paragraph or tables. #>
            foreach ($listService in $listServices) {
                Paragraph "Service $($listService.Name):"
                $listService | Table -Name "FixedWidth-AutofitCell-$($listService.Name)" -List -Width 60
            }
        }

        Section -Style Heading2 'Fixed Width Fixed Cell No Highlighting 1' {
            foreach ($listService in $listServices) {
                Paragraph "Service $($listService.Name):" -Bold
                $listService | Table -Name "FixedWidth-FixedCell-$($listService.Name)1" -List -ColumnWidths 25,75 -Width 60
            }
        }

        Section -Style Heading1 'Fixed Width Fixed Cell No Highlighting 2' {
            $listServices |  Table -Name "FixedWidth-FixedCell-$($listService.Name)2" -List -ColumnWidths 45,55 -Width 60 -Tabs 2
        }
    }
}
mc1903 commented 5 years ago

Morning Iain,

Thanks for your help & patience, I really appreciate it, but this method is not working for me.

It breaks my script and I am struggling to understand why. My script is called as a function of another script, which is where the PScribo document is created. The error message gives the calling line in first script and not the actual line in my script where the problem is.

So instead I included the WriteLog function in my script which works, albeit the plugin is not resolved so shows as 'Unknown', but I can sort that with the -Plugin switch; so I have a way forward. (I didn't think to do this until today - doh!)

Assuming there might be a future update of PScribo released, would you consider publically exporting the WriteLog function then; so that it can be called in the same straightforward way as Paragraph, Section, etc are? Having it exported directly from the owning module is a cleaner way of doing it, especially if the function ever gets updated.

Cheers Martin