Intune, ConfigMgr, PowerShell and more...
This post is the second of three for automating common debugging tools on Windows endpoints.
From the prior post:
Earlier this year I came across a scenario of an application dropping connections. This was occuring across many hundreds of users and sporadically. Typically, I would attempt to recreate the issue so I could debug, but that was not possible here. I needed a way to be ready for the drop to occur and have all debugging tools setup proactively across a large number of users.
We use ConfigMgr to run scripts on workstations from a central location and it worked well in this scenario.
This is where running this with ConfigMgr becomes convenient. Just target a collection with the software push and the script.
Invoke-CMScript -CollectionId <CollectionId> -ScriptGuid <scriptguid>
This automation was not difficult to setup. The programmatic capabilities of Wireshark made it fairly easy. The biggest challenge was cleanly ending the Wireshark processes and restarting, then ensuring only one instance was running at a time so that a capture was taken at all times.
Again, special thanks to my co-workers Darren Chinnon and Raul Colunga for the help on this one.
Wireshark paremeters
Customize the Wireshark parameters on line 53 and 68.
if (Test-Path 'C:\Program Files\Wireshark\Wireshark.exe') { # Check if Wireshark is installed
if (!(Test-Path c:\temp\capture)) { # Check if c:\temp\capture exists
New-Item -Path c:\temp -Name capture -ItemType Directory -Force # Create capture directory
}
$WSProcess = (Get-Process -Name Wireshark -ErrorAction SilentlyContinue)
if ($WSProcess -eq $null) {
# Gather the interface number
$IntAlias = Get-NetIPInterface -AddressFamily IPv4 -ConnectionState Connected -Dhcp Enabled | Select-Object -ExpandProperty InterfaceAlias
$IntListraw = & "C:\Program Files\Wireshark\Wireshark.exe" -D | Out-String
$IntList = ($IntListraw.Split("`n"))
$wsIntName = $IntList | Select-String -SimpleMatch ('(' + $IntAlias + ')')
$wsIntNumber = $wsIntName.ToString()[0]
Write-Output 'Wireshark not running, starting Wireshark.'
# Start the capture
& "C:\Program Files\Wireshark\Wireshark.exe" -i $wsIntNumber -b filesize:100000 -k -w "C:\temp\capture\$($env:username)-$($env:computername).pcapng"
} elseif ($WSProcess.count -ge 2) {
Write-Warning 'Multiple Wireshark processes running, killing, and starting Wireshark!'
Stop-Process -Name dumpcap -Force
Start-Sleep -Seconds 5
Stop-Process -Name wireshark -Force
# Gather the interface number
$IntAlias = Get-NetIPInterface -AddressFamily IPv4 -ConnectionState Connected -Dhcp Enabled | Select-Object -ExpandProperty InterfaceAlias
$IntListraw = & "C:\Program Files\Wireshark\Wireshark.exe" -D | Out-String
$IntList = ($IntListraw.Split("`n"))
$wsIntName = $IntList | Select-String -SimpleMatch ('(' + $IntAlias + ')')
$wsIntNumber = $wsIntName.ToString()[0]
# Start the capture
& "C:\Program Files\Wireshark\Wireshark.exe" -i $wsIntNumber -b filesize:100000 -k -w "C:\temp\capture\$($env:username)-$($env:computername).pcapng"
} else {
Write-Warning 'Wireshark is already running, not starting a new instance!'
}
}
Github link: Start-WiresharkCapture.ps1
Starting Wireshark for the first time
Starting Wireshark when it is already running or running multiple instances
This script was a bit more of a challenge than the Perfmon script, but allowed Wireshark to capture all network traffic at all times. This lead to the resolution of the issue we were experiencing, so it paid off.
This post is the first of three for automating common debugging tools on Windows endpoints.
Earlier this year I came across a scenario of an application dropping connections. This was occuring across many hundreds of users and sporadically. Typically, I would attempt to recreate the issue so I could debug, but that was not possible here. I needed a way to be ready for the drop to occur and have all debugging tools setup proactively across a large number of users.
We use ConfigMgr to run scripts on workstations from a central location and it worked well in this scenario.
Invoke-CMScript -CollectionId <CollectionId> -ScriptGuid <scriptguid>
This script is fairly basic, mostly just took figuring out how to interact with a Data Collector Set using logman.exe and make sure it didn’t clobber the existing DCS that is running.
Special thanks to Aussie Rob SQL, Jonathan Medd, and Rabi Achrafi for the example scripts I found online. References are in the script help text. Also thanks to my co-workers Darren Chinnon and Raul Colunga who helped put this together.
Edit the lines below to personalize as needed
$DCSName = 'PerfMonExample'
$DCSCheck = & logman query $DCSName # Query if DCS already exists
if ($DCSCheck[1] -like "*$($DCSName)") {
Write-Output 'DCS found!'
if ($DCSCheck[2] -like '*Running') {
Write-Output 'Trace running, exiting...'
} else {
Write-Output 'Trace not running, starting...'
& logman start $DCSName
}
} else {
Write-Output 'DCS not found, creating...'
# Create the Data Collector Set
$DCS = New-Object -COM Pla.DataCollectorSet
$DCS.DisplayName = $DCSName
$DCS.SetXml($DCSTemplate)
$DCS.Commit("$DCSName" , $null , 0x0003)
# Start the data collection
Write-Output 'Starting the DCS!'
$DCS.start($false)
}
Github Link: Start-PerfmonCapture.ps1
The script gives a little output for validation, not much though. This is mostly for validation during testing.
Starting the script, there may be additional output from logman.exe for the initial run
Starting the script when DCS is already running
Starting the script when DCS is not running
Overall, this process worked well and met the need. It wasn’t the first time I had to use Perfmon and it won’t be the last. Up next, Wireshark.
Even if you haven’t been paying attention to recent development for, or lack thereof, Microsoft Configuration Manager, or to any of the threads on Twitter/X, Reddit, or any other major social media platforms, you still probably know the writing is on the wall for ConfigMgr. Nearly all focus in Contosoland has been devoted to Intune.
This post outlines my personal running list of gaps that Intune doesn’t quite cover for the seasoned ConfigMgr administrator.
My friend and banter extraordinaire, Bryan Dam, posted recently a quote that makes sense in describing this list.
#ConfigMgr gave you 250% of what you need. #Intune gives you 90%, we’ll get it to 100% … eventually.
Much of this list may be in the last 150%, but that doesn’t change a lot of organizations’ dependency on these capabilities. Make your own determination how critical these capabilities are for your organization.
Kim Oppalfens has the best write up I have seen to date of these gaps.
My list includes a few more technical gaps ranging from critical to minor technical details.
For the majority of your software installations, Intune should cover your needs. But the following requirements may pose an issue.
If you are a large organization, you may hit the 200 maximum remediations limit. Our organization has well over 200 ConfigMgr baselines, so we are keeping this workload in ConfigMgr for now.
We all know that for modern endpoint management you generally want to target users, not devices. There is a lot of value targeting users, especially as Intune is designed to work better this way. However, you lose out on certain deployment abilities that ConfigMgr delivers beautifully with collections today. Good news though, coming soon to Intune is device inventory! This seems to be the first step in opening up more targeting capabilities besides Entra ID groups and virtual groups + filters.
Ironically, if you do need some of these dynamic capabilities for targeting you can use ConfigMgr to get them in Intune. Check out collection sync. Thanks Cristopher Alaya for the mention!
This is a lengthy list, and I have been keeping this list since we co-managed all our devices at the start of the pandemic in 2020. The good news is even just a year ago, this last had 5 more items. Many of these items are dropping off with every monthly Intune release and eventually Microsoft will get that last 10%. I personally expect co-management will still be necessary for the next 5 years though, we shall see.
When I threw this blog together, I had chose one of the default Permalinks options of:
http://domain/index.php/%postname%
I wanted to get that index.php out of there and that is where my journey began.
I am running WordPress on IIS 8.5 and Windows Server 2012 R2. First, I just went in and attempted to edit the Permalinks under settings, but when I went to save I got the below error.
This is my first post on my new blog. I migrated from Wordpress to Github pages with Jekyll. Just being to able to post straight from Visual Studio Code will be a pleasure.
My old blog was self-hosted on Wordpress, via potentengineer.com.
-Daniel