CTToolkit.psm1
Class CTReturnObject { [String] $Status [String] $ErrorMessage [System.Exception] $Exception [System.Collections.ArrayList] $Tracelog [System.Collections.ArrayList] $Input = ([Hashtable] $PSBoundParameters) [System.Collections.ArrayList] $Output = @() } #Not in use, because of issue with $PSBoundparameters as default value Function Get-CTReturnObject { param( [String] $Status = "Unknown", [String] $ErrorMessage, [System.Collections.ArrayList] $Tracelog = $Script:Tracelog, [Hashtable] $InputParameters = ([Hashtable] $PSBoundParameters), [System.Collections.ArrayList] $Output = [System.Collections.ArrayList] @() ) return [CTReturnObject] @{ Status = $Status ErrorMessage = $ErrorMessage Tracelog = $Tracelog Input = $InputParameters Output = $Output } } Function Get-TraceLogMessage { <# .Synopsis Generates shorter strings from a long string. .DESCRIPTION Used to limit a tracelog file and split into multiple pieces, for use with a limited field, such as windows event log. #> param($RunbookName, $Message, $maxLength) $Message += "Runbook Name: $RunbookName`n" $Message += "Runas domain: $($env:userdomain)`n" #add last part of tracelog. $Message += "Last part of Trace Log:`n" # $maxLength = 30000 $NumberOfMessages = [Math]::Ceiling(($Script:Tracelog.Length / $maxLength)) For ($i = 0; $i -lt $NumberOfMessages; $i++) { $start = (0 + ($maxLength * $i)) $end = $maxLength if ($end -gt $Script:Tracelog.Length - $start) { $end = $Script:Tracelog.Length - $start } $Message = $Script:Tracelog.Substring($start, $end) if ($Message.Length -eq $maxLength) { $Message = $Message + "`ncontinued.." } $Message } } Function Write-EventLogTraceLog { <# .Synopsis Splits tracelog into multiple strings and then writes them to the windows event log .DESCRIPTION uses the Get-TraceLogMessages function to split the tracelog and write it to event log. #> param($LogName, $SourceName, $RunbookName, $EntryType, $EventId, $Message) $Messages = Get-TraceLogMessage -RunbookName $RunbookName -Message $Message -maxLength 30000 #write event log if (!([System.Diagnostics.EventLog]::SourceExists($SourceName))) { New-EventLog -LogName $LogName -Source $SourceName } foreach ($message in $messages) { Write-EventLog -LogName $LogName -Source $SourceName -EntryType $EntryType -EventId $EventId -Message $Message } } Function Add-Tracelog { <# .Synopsis Adds a tracelog message to tracelog .DESCRIPTION Uses a script scope tracelog variable to have alle scopes write to a sinlg etracelog. Outputs each message to the Verbose stream. #> param($Message) if ([String]::IsNullOrEmpty($script:Tracelog)) { $script:TraceLogId = 0 [System.Collections.ArrayList] $script:Tracelog = @() } $Message = "{0}: {1:yyyy-MM-dd HH:mm:ss.fff}: {2}`n" -f $script:TraceLogId,(get-date),$Message $script:TraceLogId++ #$Message = "$(get-date) - $Message`n" Write-Verbose $Message $script:Tracelog.Add($Message.ToString()) } Function Get-TraceLog { [System.Collections.ArrayList] $script:TraceLog } Function Write-TextLog { <# .Synopsis Writes the tracelog to a text file. .DESCRIPTION Writes the tracelog to a text file. If the text file looks "weird" in notepad, it is becausenotepad cannot alway list the line breaks correctly. Use another editor to view the log. #> param($Message, $LogFolderPath, $LogName, $StartTime) #Write to file $Message + "`n" + ($script:TraceLog -join "`n") | Out-file $LogFolderPath\$($LogName)_$($StartTime.ToString("yyyyMMddhhmmss")).log -Encoding ASCII } Function ConvertTo-IndexedTable { <# .Synopsis Converts an array of objects to a array of hashtables for performance .DESCRIPTION Converts an array of objects to a hashtable of hashtables for performance The hashtable has takes one field as index, for example name and the index field can be used to filter/sort much quicker than and array of objects. (see example for details) .Example Get-CMDevice -CollectionName "All Systems" -Fast | ConvertTo-IndexedTable Name Name Value ---- ----- Object ... Name NCOP-CCMP-CCM01 the index field is available directly, while the complete object is available in the object key of the hash table. #> param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $false, Position = 0)] $IndexFieldName, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 1)] [Object]$Object ) #begin { $ReturnArray = @() } #New-Object System.Collections.ArrayList } process { @{ $IndexFieldName = $Object.$IndexFieldName Object = $Object } } #end { $ReturnArray } } Function Clear-Tracelog { <# .Synopsis Clears the tracelog .DESCRIPTION Clears the tracelog #> $script:Tracelog = [System.Collections.ArrayList] @() } Function Write-CTError { param($PSError,$returnObject) #get error messa $CurrentError = $PSError $ErrorMessage = $CurrentError.Exception.Message + "`n $($CurrentError.InvocationInfo.PositionMessage)" Add-Tracelog -Message "Error in control runbook: $ErrorMessage" Write-Error -Message $ErrorMessage #-ErrorAction Continue #output error without stopping, for logging purposes. } |