Help with formatting output on PS script

This topic contains 4 replies, has 2 voices, and was last updated by Profile photo of Allen Maloy Allen Maloy 2 years, 5 months ago.

  • Author
    Posts
  • #16785
    Profile photo of Allen Maloy
    Allen Maloy
    Participant

    Hello, i have cobbled together a PS script from an old article that gathers event logs from a list of servers in a text file and outputs the info in an HTML file. It does 99% of what i need except 2 things.

    1) if a server is unavailable, i need it to output something like "RPC is unavailable" per the debug warning. Right now, it just doesn't output anything.
    2) I'd like the HTML formatted with cells & rows to separate events.

    2 really simple things that's i'm not sure where to insert in the file attached.

    Thanks in advance.

  • #16787
    Profile photo of Mathieu Buisson
    Mathieu Buisson
    Participant

    Generally, the best way to implement a -Debug parameter in a script is to make it an advanced function.
    Don't let the word "advanced" scare you, it's pretty simple.
    First you define your script, or a section of your script as a function, for example :

     function Export-EventLog { 

    Then, the first line of your function should be :

    [CmdletBinding()] 

    This is this line which allows the magic to happen.
    This gives you all the Powershell common parameters for free, like -Verbose and [b]-Debug[/b].
    Then, you can remove the $Debug switch from your Param() block, because it is built into any advanced function.
    From then on, all you have to do is call your function with -Debug and this will output stuff wherever you have Write-Debug in your function.

    Regarding the "RPC is unavailable" not being output, this is because the error "RPC is unavailable" for the cmdlet Get-WmiObject is not a terminating error.
    Powershell will check for a Trap statement only if there is a terminating error, so in your script , the Trap statement is not evaluated at all.

    What you can do is flag all errors as terminating errors by setting the $ErrorActionPreference inside your function :

     $ErrorActionPreference = "Stop" 

    If you want to flag errors as terminating, but only for specific commands, use the -ErrorAction parameter instead :

     $cmd = 'Get-WmiObject -ComputerName $computername -query $query -ErrorAction Stop' 

    This will flag any error generated by your "Get-WmiObject" commands as terminating error and then, Powershell will evaluate your Trap statement.

  • #16788
    Profile photo of Allen Maloy
    Allen Maloy
    Participant

    Thanks Mathieu.

    I can't figure out where to place these items. I placed function at the beginning, naming the function the same name as the script filename. First line was the cmdletbinging and then I experimented a bit with the closing } for the Function.

    If I place it at the very end such as in the file attached and run the script. Nothing happens. No report generated, no screen output...nothing.

  • #16790
    Profile photo of Mathieu Buisson
    Mathieu Buisson
    Participant

    Yes, the closing } for the function should be after everything that the function contains.

    Also, the name of the script file doesn't have to match the name of the function ( a single script file can contain several functions).
    Your script actually contains 2 functions : eventlog_reporter_debug and Send-NetMail .

    A function does nothing by itself.
    To use a function, you need to source it , and then, call it.

    To source a function, if it is in a normal script (a .ps1 file) , you need to "dot source" the file, like so :

     . \Path\To\File.ps1 

    Then, you can call/run it , for example :

     eventlog_reporter_debug -smtp "MySMTPServer" -SendTo "address@email.com" -From "MyAddress@email.com" -username "MyUsername" -password "P@ssw0rd" 

    Another way is to call the function from inside the script.
    To do that, just insert the above command in your script file.
    Just make sure it is outside of the Function { ... } block, otherwise it won't work.
    That way, the command above will be automatically executed when you "dot source" the script file.

    3rd way to source/load functions :
    You could also package them in a script module (a .psm1 file, instead of .ps1).
    In this case, you need to add the following command after the closing } of the function(s), normally at the very end of the file :

     Export-ModuleMember -Function *
    # To export all functions contained in the module
    # or
    Export-ModuleMember -Function eventlog_reporter_debug
    # To export only your main function  

    The second option might be preferable if the function Send-NetMail is only called from inside the main function eventlog_reporter_debug, and you don't need(or want) to make it available from outside the main function.

    Once this is done, and your script is saved as a .psm1 file, you need to import the module to make all the functions it contains available , like so :

     Import-Module \Path\To\File.psm1 

    Now, you can call/run the function(s).

  • #16798
    Profile photo of Allen Maloy
    Allen Maloy
    Participant

    Well I appreciate the effort but this seems to have become 10x more complicated...argh!

You must be logged in to reply to this topic.