OK, obviously I’m not too good at posting on a regular basis… Sorry about that. Some things have changes since my last post, I’ve got a new job and am doing much more than just SCCM, so we’ll see some new scripts going up. I’ve also switched from BitBucket to GitHub. I’m going to try blogging about simple things like the issues I run into and the scripts I’m putting up in GitHub. I’m not going to worry about putting up a module, instead I’m just going to be putting each function up one at a time as I write them and I’ll leave how you use them up to you.
To that end, I’ve slightly updated my New-CmnLogentry and Get-SccmConnectionInfo (shown below) scripts mostly adding comments. They can be found in the GitHub repository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
function New-CmnLogEntry { <# .SYNOPSIS Writes log entry that can be read by CMTrace.exe .DESCRIPTION If you set 'logEntries' to $true, it writes log entries to a file. If the file is larger then MaxFileSize, it will rename it to *yyyymmdd-HHmmss.log and start a new file. You can specify if it's an (1) informational, (2) warning, or (3) error message as well. It will also add time zone information, so if you have machines in multiple time zones, you can convert to UTC and make sure you know exactly when things happened. Will always write the entry verbose for troubleshooting .PARAMETER entry This is the text that is the log entry. .PARAMETER type Defines the type of message, 1 = Informational (default), 2 = Warning, and 3 = Error. .PARAMETER component Specifies the Component information. This could be the name of the function or thread, or whatever you like, to further help identify what is being logged. .PARAMETER logFile File for writing logs to (default is C:\Windows\temp\error.log). .PARAMETER logEntries Set to $true to write to the log file. Otherwise, it will just be write-verbose (default is $false). .PARAMETER maxLogSize Max size for the log (default is 5MB). .PARAMETER maxLogHistory Specifies the number of history log files to keep (default is 5). .EXAMPLE New-CmnLogEntry -entry "Machine $computerName needs a restart." -type 2 -component 'Installer' -logFile $logFile -logEntries -MaxLogSize 10485760 This will add a warning entry, after expanding $computerName from the compontent Installer to the logfile and roll it over if it exceeds 10MB .LINK http://configman-notes.com .NOTES Author: James Parris Contact: jim@ConfigMan-Notes.com Created: 2016-03-22 Updated: 2017-03-01 Added log rollover 2018-10-23 Added Write-Verbose Added adjustment in TimeZond for Daylight Savings Time Corrected time format for renaming logs because I'm an idiot and put 3 digits in the minute field. PSVer: 3.0 Version: 2.0 #> [CmdletBinding(ConfirmImpact = 'Low')] Param ( [Parameter(Mandatory = $true, HelpMessage = 'This is the text that is the log entry.')] [String]$entry, [Parameter(Mandatory = $true, HelpMessage = 'Defines the type of message, 1 = Informational (default), 2 = Warning, and 3 = Error.')] [ValidateSet(1, 2, 3)] [INT32]$type, [Parameter(Mandatory = $true, HelpMessage = 'Specifies the Component information. This could be the name of the function or thread, or whatever you like, to further help identify what is being logged.')] [String]$component, [Parameter(Mandatory = $false, HelpMessage = 'File for writing logs to (default is C:\Windows\temp\error.log).')] [String]$logFile = 'C:\Windows\temp\error.log', [Parameter(Mandatory = $false, HelpMessage = 'Set to $true to write to the log file. Otherwise, it will just be write-verbose (default is $false).')] [Boolean]$logEntries = $false, [Parameter(Mandatory = $false, HelpMessage = 'Max size for the log (default is 5MB).')] [Int]$maxLogSize = 5242880, [Parameter(Mandatory = $false, HelpMessage = 'Specifies the number of history log files to keep (default is 5).')] [Int]$maxLogHistory = 5 ) # Get Timezone info $now = Get-Date $tzInfo = [System.TimeZoneInfo]::Local # Get Timezone Offset $tzOffset = $tzInfo.BaseUTcOffset.Negate().TotalMinutes # If it's daylight savings time, we need to adjust if ($tzInfo.IsDaylightSavingTime($now)) { $tzAdjust = ((($tzInfo.GetAdjustmentRules()).DaylightDelta).TotalMinutes)[0] $tzOffset -= $tzAdjust } # Now, to figure out the format. if the timezone adjustment is posative, we need to represent it as +### if ($tzOffset -ge 0) { $tzOffset = "$(Get-Date -Format "HH:mm:ss.fff")+$($tzOffset)" } # Otherwise, we need to represent it as -### else { $tzOffset = "$(Get-Date -Format "HH:mm:ss.fff")$tzOffset" } # Create entry line, properly formatted $cmEntry = "<![LOG[{0}]LOG]!><time=""{2}"" date=""{1}"" component=""{5}"" context="""" type=""{4}"" thread=""{3}"">" -f $entry, (Get-Date -Format "MM-dd-yyyy"), $tzOffset, $pid, $type, $component if ($PSBoundParameters['logEntries']) { # Now, see if we need to roll the log if (Test-Path $logFile) { # File exists, now to check the size if ((Get-Item -Path $logFile).Length -gt $MaxLogSize) { # Rename file $backupLog = ($logFile -replace '\.log$', '') + "-$(Get-Date -Format "yyyymmdd-HHmmss").log" Rename-Item -Path $logFile -NewName $backupLog -Force # Get filter information # First, we do a regex search, and just get the text before the .log and after the \ $logFile -match '(\w*).log' | Out-Null # Now, we add a trailing * for the filter $logFileName = "$($Matches[1])*" # Get the path for the log so we know where to search $logPath = Split-Path -Path $logFile # And we remove any extra rollover logs. Get-ChildItem -Path $logPath -filter $logFileName | Where-Object { $_.Name -notin (Get-ChildItem -Path $logPath -Filter $logFileName | Sort-Object -Property LastWriteTime -Descending | Select-Object -First $maxLogHistory).name } | Remove-Item } } # Finally, we write the entry $cmEntry | Out-File $logFile -Append -Encoding ascii } # Also, we write verbose, just incase that's turned on. Write-Verbose $entry } # End New-CmnLogEntry |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
Function Get-CmnSccmConnectionInfo { <# .SYNOPSIS Builds SccmConnectionInfo object for use in functions .DESCRIPTION Builds SccmConnectionInfo object for use in functions. Returns a PSObject with four properties: CimSession CimSession to be used when calling functions NameSpace NameSpace, also to be used when calling functions SCCMDBServer SCCM Database Server Name SCCMDB SCCM Database Name .PARAMETER SiteServer This is a variable containing name of the site server to connect to. .PARAMETER logFile File for writing logs to (default is c:\temp\eror.log). .PARAMETER logEntries Set to $true to write to the log file. Otherwise, it will just be write-verbose (default is $false). .PARAMETER maxLogSize Max size for the log (default is 5MB). .PARAMETER maxLogHistory Specifies the number of history log files to keep (default is 5). .EXAMPLE Get-CmnSccmConnectionInfo -siteServer Server1 Returns SccmDbServer : server1.domain.com CimSession : CimSession: server1 NameSpace : Root/SMS/Site_S01 SccmDb : CM_S01 .LINK http://configman-notes.com .NOTES Author: Jim Parris Email: Jim@ConfigMan-Notes.com Date: 2019-05-02 Updated: PSVer: 3.0 Version: 1.0.0 #> [CmdletBinding(ConfirmImpact = 'Low')] PARAM( [Parameter(Mandatory = $true, HelpMessage = 'This is a variable containing name of the site server to connect to.')] [PSObject]$siteServer, [Parameter(Mandatory = $false, HelpMessage = 'File for writing logs to (default is c:\temp\eror.log).')] [String]$logFile = 'C:\Temp\Error.log', [Parameter(Mandatory = $false, HelpMessage = 'Set to $true to write to the log file. Otherwise, it will just be write-verbose (default is $false).')] [Boolean]$logEntries = $false, [Parameter(Mandatory = $false, HelpMessage = 'Max size for the log (default is 5MB).')] [Int]$maxLogSize = 5242880, [Parameter(Mandatory = $false, HelpMessage = 'Specifies the number of history log files to keep (default is 5).')] [Int]$maxLogHistory = 5 ) begin { # Build splat for log entries $NewLogEntry = @{ LogFile = $logFile; Component = 'Get-CmnSccmConnectionInfo'; logEntries = $logEntries; maxLogSize = $maxLogSize; maxLogHistory = $maxLogHistory; } # Create a hashtable with your output info $returnHashTable = @{ } New-CmnLogEntry -entry 'Starting Function' -type 1 @NewLogEntry New-CmnLogEntry -entry "siteServer = $siteServer" -type 1 @NewLogEntry New-CmnLogEntry -entry "siteCode = $siteCode" -type 1 @NewLogEntry New-CmnLogEntry -entry "logFile = $logFile" -type 1 @NewLogEntry New-CmnLogEntry -entry "logEntries = $logEntries" -type 1 @NewLogEntry New-CmnLogEntry -entry "maxLogSize = $maxLogSize" -type 1 @NewLogEntry New-CmnLogEntry -entry "maxLogHistory = $maxLogHistory" -type 1 @NewLogEntry } process { New-CmnLogEntry -entry 'Beginning process loop' -type 1 @NewLogEntry try { # Establish new CimSession to the site server. $cimSession = New-CimSession -ComputerName $siteServer # Now, to get the siteCode. We do this in the try/catch area to handle any errors. $siteCode = (Get-CimInstance -CimSession $cimSession -ClassName SMS_ProviderLocation -Namespace root\SMS).SiteCode } catch { # We hope this never runs, but if it does, time to write out some logs. New-CmnLogEntry -entry "Failed to complete: $error" -type 3 @NewLogEntry throw "Failed to complete: $error" } # Now that we are connected, let's get the database information. First pull from the site what we need $DataSourceWMI = $(Get-CimInstance -Class 'SMS_SiteSystemSummarizer' -Namespace "root/sms/site_$siteCode" -CimSession $cimSession -Filter "Role = 'SMS SQL SERVER' and SiteCode = '$siteCode' and ObjectType = 1").SiteObject # Now, to clean it up and just get the server name $SccmDbServer = $DataSourceWMI -replace '.*\\\\([A-Z0-9_.]+)\\.*', '$+' # Finally, the database name. $SccmDb = $DataSourceWMI -replace ".*\\([A-Z_0-9]*?)\\$", '$+' # Build the returnHashTable. $returnHashTable.Add('CimSession', $cimSession) $returnHashTable.Add('NameSpace', "Root/SMS/Site_$siteCode") $returnHashTable.Add('SccmDbServer', $SccmDbServer) $returnHashTable.Add('SccmDb', $SccmDb) } End { New-CmnLogEntry -entry 'Completing Function' -Type 1 @NewLogEntry $obj = New-Object -TypeName PSObject -Property $returnHashTable $obj.PSObject.TypeNames.Insert(0, 'CMN.SccmConnectionInfo') Return $obj } } # End Get-CmnSccmConnectionInfo |