PowerShell Code Snippets

Any solutions you find on these pages are provided “AS-IS” with no warranties. 

Find Applications with a specific dependency (Java, .Net, c++ runtime, ….)

Let’s assume you want to update your Java Application and you have to find all the Applications in SCCM where Java is set as dependency. The script below will give you the list.

#Enter the Application that is set as dependency
$Dependency = ‘%Java%’

# Fill in your database name and database server below
$SCCMDBName = ‘CM_P01’
$SCCMDBServerName = ‘SVRCMP01’

$objConnection = New-Object -comobject ADODB.Connection
$objRecordset = New-Object -comobject ADODB.Recordset
$con = “Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=$SCCMDBName;Data Source=$SCCMDBServerName”
$strSQL = @”
select rel.FromApplicationCIID from v_CIAppDependenceRelations as rel
inner join fn_ListLatestApplicationCIs(1033) AS app on app.CI_ID = rel.ToApplicationCIID
where app.DisplayName like ‘$Dependency’

$objConnection.CommandTimeout = 0
# *********** Check If connection is open *******************
If($objConnection.state -eq 0)
Write-Host “Error: Connection to database failed. ”
Exit 1
$CIID_Array = @()
$CIID = $objRecordset.Fields.Item(0).Value
$CIID_Array += $CIID
until ($objRecordset.EOF -eq $TRUE)

foreach ($ID in $CIID_Array)
$strSQL2 = @”
select DisplayName from fn_ListLatestApplicationCIs(1033) where CI_ID like ‘$ID’
If($objConnection.state -eq 0)
Write-Host “Error: Connection to database failed. ”
Exit 1
$value = $objRecordset.Fields.Item(0).Value
Write-Host $value

Create a scheduled task that cleans up IIS logs

By default, IIS creates a new log file every day and never deletes any old files. To limit the disk space of the files, it is therefore important to implement a cleanup task. The script below creates a scheduled task that will run once per week to execute a simple PowerShell command. There are lots of similar solutions available but the beauty of this one is that the scheduled task contains the code for the cleanup, so there’s no need to place a script on the disk. Mind that the code below will delete logs older than 30 days (therefore -30).

$action = New-ScheduledTaskAction -Execute ‘Powershell.exe’ -Argument ‘-NoProfile -WindowStyle Hidden -command “& {Get-ChildItem -Path c:\inetpub\logs\logfiles\w3svc*\*.log | where {$_.LastWriteTime -lt (get-date).AddDays(-30)} | Remove-Item}”‘
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Saturday -At 5am
$settingsSet = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 5)
Register-ScheduledTask -User ‘System’ -Force -Action $action -Trigger $trigger -Settings $settingsSet -TaskName “CleanIISLogs” -Description “Weekly cleanup of IIS log”


Managing IIS Log File Storage: https://docs.microsoft.com/en-us/iis/manage/provisioning-and-managing-iis/managing-iis-log-file-storage

Use PowerShell to Create Scheduled Tasks: https://devblogs.microsoft.com/scripting/use-powershell-to-create-scheduled-tasks/

Manage IIS Log Files and purge those older than N days with a Powershell script or a batch file: https://www.ryadel.com/en/manage-iis-log-files-purge-older-n-days-bat-file/#google_vignette

Modify the maximum runtime of software updates in SCCM

A frequent complaint is that the maximum runtime of software updates is too short. Or too long in case that small maintenance windows are being used. In most cases, the maxruntime is 10, 60, or sometimes 120 min. The script below allows you to modify the value (the feature to adjust the value was added in 1706).

function LoadCMModule
Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + ‘\ConfigurationManager.psd1’)

$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-location $SiteCode”:”

$updates = Get-CMSoftwareUpdate -Name “*2020-04*” -Fast #Better set a filter, this takes quite long
$count = 0

foreach ($update in $updates )
Write-Host $update.LocalizedDisplayName $update.MaxExecutionTime

600 {Set-CMSoftwareUpdate -CI_ID $update.CI_ID -MaximumExecutionMins 15; $count++; Write-Host “Changing ” $update.LocalizedDisplayName ” Current MaximumExecutionMins: ” $update.MaxExecutionTime -ForegroundColor Yellow; break;}
3600 {Set-CMSoftwareUpdate -CI_ID $update.CI_ID -MaximumExecutionMins 90; $count++; Write-Host “Changing ” $update.LocalizedDisplayName ” Current MaximumExecutionMins: ” $update.MaxExecutionTime -ForegroundColor Yellow; break;}
7600 {Set-CMSoftwareUpdate -CI_ID $update.CI_ID -MaximumExecutionMins 180; $count++; Write-Host “Changing ” $update.LocalizedDisplayName ” Current MaximumExecutionMins: ” $update.MaxExecutionTime -ForegroundColor Yellow; break;}
Write-Host $count ” changes made” -ForegroundColor Green

Parsing Kerberos events

Parsing EventLog events is a bit tricky. The code snippets below shall help to parse events 4768 and 4769 with PowerShell on Domain Controllers (mind that only the first 100 events are requested)

Get 4768 events (authentication ticket (TGT) was requested):

Get-WinEvent -FilterHashtable @{LogName = 'Security';ID='4768'} | select -First 100 -Property * | ForEach-Object -Process {New-Object -TypeName PSObject -Property @{'TimeCreated'=$_.TimeCreated; 'Account Name'=$_.properties[0].Value; 
'Supplied Realm Name'=$_.properties[1].Value;

'User ID'=$_.properties[2].Value;
'Service Name'=$_.properties[3].Value;
'Service ID'=$_.properties[4].Value;
'Ticket Options'=$_.properties[5].Value;
'Result Code'='{0:x8}' -f $_.properties[5].Value;
'EncryptionType'='{0:x2}' -f $_.properties[7].Value}}

Link: 4768(S, F): A Kerberos authentication ticket (TGT) was requested

Get 4769 events (A Kerberos service ticket was requested):

Get-WinEvent -FilterHashtable @{LogName = 'Security';ID='4769'} | select -First 100 -Property * | ForEach-Object -Process {New-Object -TypeName PSObject -Property @{'TimeCreated'=$_.TimeCreated;
'TicketOptions'='{0:x8}' -f $_.properties[4].Value;
'TicketEncryptionType'='{0:x2}' -f $_.properties[5].Value;
'Logon GUID'=$_.properties[9].Value;

Link: 4769(S, F): A Kerberos service ticket was requested. https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4769

Little helpers:
Get SID of an account:

$AdObj = New-Object System.Security.Principal.NTAccount(‘s-sql3@happyadmin.inc’)
$SID = $AdObj.Translate([System.Security.Principal.SecurityIdentifier])

Get account from SID:

$sid = ‘S-1-5-21-291460342-2294237019-3453978477-502’
$objSID = New-Object System.Security.Principal.SecurityIdentifier($sid)
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])

Monitor inboxes

$filewatcher = New-Object System.IO.FileSystemWatcher
#Mention the folder to monitor
$filewatcher.Path = “E:\Program Files\Microsoft Configuration Manager\inboxes” #Correct this!!
$filewatcher.Filter = “*.*”
#include subdirectories $true/$false
$filewatcher.IncludeSubdirectories = $true
$filewatcher.EnableRaisingEvents = $true

$writeaction = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = “$(Get-Date), $changeType, $path”
Add-content “$PSScriptRoot\InboxWatch1.log” -value $logline
WriteLog -Path “$PSScriptRoot\InboxWatch.log” -Message ($logline | Out-String) -Component ‘InboxWatch’ -Type Info

#The Register-ObjectEvent cmdlet subscribes to events that are generated by .NET objects on the local computer or on a remote computer.
#When the subscribed event is raised, it is added to the event queue in your session. To get events in the event queue, use the Get-Event cmdlet.
Register-ObjectEvent $filewatcher “Created” -Action $writeaction
Register-ObjectEvent $filewatcher “Changed” -Action $writeaction
Register-ObjectEvent $filewatcher “Deleted” -Action $writeaction
Register-ObjectEvent $filewatcher “Renamed” -Action $writeaction
while ($true) {sleep 5}