{"id":146,"date":"2026-03-17T12:18:55","date_gmt":"2026-03-17T12:18:55","guid":{"rendered":"https:\/\/unen.nl\/?p=146"},"modified":"2026-03-17T13:22:50","modified_gmt":"2026-03-17T13:22:50","slug":"%f0%9f%94%a7-je-netwerk-echt-meten-met-powershell","status":"publish","type":"post","link":"https:\/\/unen.nl\/?p=146","title":{"rendered":"\ud83d\udd27 Je netwerk echt meten met PowerShell"},"content":{"rendered":"\n<p>Iedereen kent het moment.<\/p>\n\n\n\n<p>Teams call die hapert.<br>Download die blijft hangen op 2 MB\/s.<br>Of die ene collega die zegt: <em>\u201cbij mij werkt het gewoon hoor\u2026\u201d<\/em><\/p>\n\n\n\n<p>En dan begint het: speedtest.net openen, screenshot maken, weer vergeten.<\/p>\n\n\n\n<p>Dus dacht ik: dit moet slimmer kunnen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\ude80 Waarom ik dit script heb gemaakt<\/h2>\n\n\n\n<p>In mijn HomeLab \u00e9n bij klanten wilde ik niet alleen weten <em>hoe snel<\/em> de verbinding is, maar vooral:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Welke adapter wordt gebruikt?<\/li>\n\n\n\n<li>Zit je op WiFi of bekabeld?<\/li>\n\n\n\n<li>Wat is je publieke IP?<\/li>\n\n\n\n<li>Welke DNS gebruik je?<\/li>\n\n\n\n<li>Waar staat die testserver eigenlijk?<\/li>\n<\/ul>\n\n\n\n<p>En vooral: <strong>ik wil logging. Altijd.<\/strong><\/p>\n\n\n\n<p>Niet gokken, maar data.<\/p>\n\n\n\n<p>Daarom heb ik een PowerShell script gebouwd dat:<\/p>\n\n\n\n<p>\u2714 Speedtest draait via de offici\u00eble Ookla CLI<br>\u2714 Netwerkdata verzamelt<br>\u2714 Alles netjes wegschrijft naar JSON \u00e9n CSV<br>\u2714 Logs bijhoudt (ook handig voor Intune \/ troubleshooting)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde0 Wat maakt dit script anders?<\/h2>\n\n\n\n<p>Dit is geen simpele \u201crun speedtest en klaar\u201d.<\/p>\n\n\n\n<p>Het script:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Detecteert je actieve netwerkadapter<\/li>\n\n\n\n<li>Haalt publieke IP op via meerdere bronnen (fallback logic \ud83d\udcaa)<\/li>\n\n\n\n<li>Probeert je SSID te achterhalen (best effort, want Windows\u2026)<\/li>\n\n\n\n<li>Verrijkt data met geolocation<\/li>\n\n\n\n<li>Logt alles gestructureerd<\/li>\n\n\n\n<li>Draait ook volledig <strong>silent<\/strong> (handig voor automation \/ Intune)<\/li>\n<\/ul>\n\n\n\n<p>Oftewel: <strong>dit is production-ready spul<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udce6 Het script<\/h2>\n\n\n\n<p>Hieronder de volledige versie:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[CmdletBinding(SupportsShouldProcess=$true)]<br>param(<br>    [switch]$Silent,<br>    [string]$LogName = \"NetworkSpeedTest\",<br>    [string]$OutputFolder = \"C:\\log\"<br>)<br><br>&lt;#\t<br>\t.NOTES<br>\t===========================================================================<br>\t Created on:   \t2026-03-15<br>\t Created by:   \tVincent van Unen<br>\t Filename:     \tsca-commandlinespeedtest.ps1<br>\t===========================================================================<br>\t.DESCRIPTION<br>\t\tPowerShell script to perform a network speed test using Ookla's Speedtest CLI, gather network information, and log results in structured JSON and CSV formats. The script includes robust error handling, logging, and is designed to run in both interactive and silent modes.<br>    .SYNOPSIS<br>        This script performs a network speed test using Ookla's Speedtest CLI, gathers detailed network information, and logs results in structured JSON and CSV formats. It includes robust error handling and can run in both interactive and silent modes.<br>    .PARAMETER Silent<br>        Run the script in silent mode (no console output, only logs).<br>#><br><br><br># ==============================<br># Helper: Console + Log Writers<br># ==============================<br>function Write-Console {<br>    param(<br>        [Parameter(Mandatory=$true)][string]$Message,<br>        [ValidateSet(\"White\",\"Yellow\",\"Green\",\"Cyan\",\"Red\",\"Gray\")][string]$Color = \"White\"<br>    )<br>    if (-not $Silent) {<br>        Write-Host $Message -ForegroundColor $Color<br>    }<br>}<br><br># ===================================<br># Function: Get SSID (best effort)<br># ===================================<br>function Get-CurrentSSID {<br>    try {<br>        # Gebruik netsh, match alleen \"SSID\" (niet \"BSSID\")<br>        $w = netsh wlan show interfaces 2>$null | Select-String -Pattern \"^\\s*SSID\\s*:\"<br>        if ($w) {<br>            $raw = ($w -split \":\",2)[1].Trim()<br>            if ($raw -and $raw -ne \"SSID\") { return $raw }<br>        }<br>    } catch { }<br><br>    try {<br>        # Fallback via net connection profile<br>        $cp = Get-NetConnectionProfile | Where-Object { $_.InterfaceAlias -like \"*Wi-Fi*\" -or $_.InterfaceAlias -like \"*Wireless*\" } | Select-Object -First 1<br>        if ($cp) { return $cp.Name }<br>    } catch { }<br><br>    try {<br>        # Legacy WMI fallback<br>        $wifiAdapter = Get-WmiObject -Class Win32_NetworkAdapter | Where-Object { $_.Name -like \"*Wi-Fi*\" -or $_.Name -like \"*Wireless*\" } | Select-Object -First 1<br>        if ($wifiAdapter) {<br>            $wifiConfig = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.Index -eq $wifiAdapter.Index -and $_.IPEnabled -eq $true }<br>            if ($wifiConfig) { return $wifiConfig.Description }<br>        }<br>    } catch { }<br><br>    return $null<br>}<br><br># ==============================<br># Administrator Check<br># ==============================<br>if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(<br>    [Security.Principal.WindowsBuiltInRole] \"Administrator\")) {<br>    Write-Console \"This script requires administrator privileges.\" \"Yellow\"<br>    if (-not $Silent) { Read-Host \"Press Enter to exit\" }<br>    exit 1<br>}<br><br># ==============================<br># Global\/Script Configuration<br># ==============================<br>[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12<br>Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force -WarningAction Ignore -ErrorAction Ignore<br>Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process      -Force -WarningAction Ignore -ErrorAction Ignore<br>Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser  -Force -WarningAction Ignore -ErrorAction Ignore<br>$MaximumFunctionCount = 16384<br>$MaximumVariableCount = 16384<br><br># Dirs<br>$XIPMyModuleDir1 = \"C:\\temp\"<br>$XIPMyModuleDir2 = \"C:\\tmp\"<br>$XIPMyModuleDir3 = \"C:\\log\"<br><br>foreach ($dir in @($XIPMyModuleDir1,$XIPMyModuleDir2,$XIPMyModuleDir3,$OutputFolder)) {<br>    if (!(Test-Path -Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }<br>}<br><br># Script meta<br>$ScriptAuthor         = \"Vincent van Unen\"<br>$ScripVersion         = \"1.0.1\"<br>$ScriptChangeDate     = (Get-Date -Format 'yyyy-MM-dd')<br>$ScriptChangeLog      = \"Fixed Get-CurrentSSID scope + math rounders\"<br>$ScriptCurrentUser    = $env:UserName<br>$ScriptRunningDevice  = $env:COMPUTERNAME<br>$Getcurrentdate       = Get-Date -Format 'yyyy-MM-dd'<br>$NowStamp             = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'<br><br># Speedtest config<br>$speedtestVersion     = \"1.2.0\"<br>$speedtestUrl         = \"https:\/\/install.speedtest.net\/app\/cli\/ookla-speedtest-$speedtestVersion-win64.zip\"<br>$tempPath             = Join-Path $env:TEMP \"speedtest_cli_$NowStamp\"<br>$zipFile              = Join-Path $env:TEMP \"speedtest_$NowStamp.zip\"<br><br># Logging file<br>$LogFile = Join-Path $XIPMyModuleDir3 (\"{0} {1}.log\" -f $LogName, $Getcurrentdate)<br><br># ==============================<br># Logger<br># ==============================<br>function WriteToLogFile {<br>    [CmdletBinding()]<br>    Param(<br>        [Parameter(Mandatory=$False)]<br>        [ValidateSet(\"INFO\",\"WARN\",\"ERROR\",\"FATAL\",\"DEBUG\")]<br>        [String] $Level = \"INFO\",<br><br>        [Parameter(Mandatory=$True)]<br>        [string] $Message,<br><br>        [Parameter(Mandatory=$False)]<br>        [string] $logfile = $LogFile<br>    )<br>    if ($Message -eq \" \") {<br>        Add-Content $logfile -Value \" \" -ErrorAction SilentlyContinue<br>    } else {<br>        $Date = (Get-Date).ToUniversalTime().ToString('yyyy-MM-dd HH:mm:ss.fff')<br>        Add-Content $logfile -Value \"[$Date] [$Level] $Message\" -ErrorAction SilentlyContinue<br>    }<br>}<br><br># ==============================<br># Transcript<br># ==============================<br>$TranscriptFile = Join-Path $XIPMyModuleDir3 (\"{0}_{1}_Transcript.log\" -f $Getcurrentdate, $LogName)<br>try { Start-Transcript -Path $TranscriptFile -ErrorAction SilentlyContinue | Out-Null } catch {}<br><br># ==============================<br># Initial Log Lines<br># ==============================<br>WriteToLogFile -Message \"Current Date        = $Getcurrentdate\"<br>WriteToLogFile -Message \"Script Author       = $ScriptAuthor\"<br>WriteToLogFile -Message \"Script Version      = $ScripVersion\"<br>WriteToLogFile -Message \"Script ChangeDate   = $ScriptChangeDate\"<br>WriteToLogFile -Message \"Current User        = $ScriptCurrentUser\"<br>WriteToLogFile -Message \"Current Device      = $ScriptRunningDevice\"<br><br># ===================================<br># Function: Get Network Information<br># ===================================<br>function Get-NetworkInfo {<br>    Write-Console \"`nGathering network information...\" \"Cyan\"<br>    WriteToLogFile -Level \"INFO\" -Message \"Gathering network information\"<br><br>    # Active adapter (exclude loopback)<br>    $activeAdapter = Get-NetAdapter | Where-Object { $_.Status -eq \"Up\" -and $_.InterfaceType -ne \"Software Loopback\" } | Select-Object -First 1<br><br>    if (-not $activeAdapter) {<br>        WriteToLogFile -Level \"ERROR\" -Message \"No active network adapter found.\"<br>        throw \"No active network adapter found.\"<br>    }<br><br>    # IP config for active adapter<br>    $ipConfig = Get-NetIPConfiguration | Where-Object { $_.NetAdapter -and $_.NetAdapter.Name -eq $activeAdapter.Name }<br><br>    # DNS (IPv4)<br>    $dnsServersObj = Get-DnsClientServerAddress | Where-Object { $_.InterfaceAlias -eq $activeAdapter.Name -and $_.AddressFamily -eq 2 }<br>    $dnsList = @()<br>    if ($dnsServersObj) {<br>        foreach ($o in $dnsServersObj) {<br>            if ($o.ServerAddresses) { $dnsList += $o.ServerAddresses }<br>        }<br>    }<br><br>    # Public IP (try multiple sources)<br>    $publicIp = $null<br>    $publicIpSources = @(<br>        \"https:\/\/api.ipify.org\",<br>        \"https:\/\/icanhazip.com\",<br>        \"https:\/\/ipinfo.io\/ip\"<br>    )<br>    foreach ($source in $publicIpSources) {<br>        try {<br>            $r = Invoke-RestMethod -Uri $source -TimeoutSec 5<br>            if ($r) {<br>                $publicIp = $r.ToString().Trim()<br>                break<br>            }<br>        } catch { continue }<br>    }<br><br>    # Compute local fields safely<br>    $localIPv4 = $ipConfig.IPv4Address.IPAddress<br>    $prefixLen = $ipConfig.IPv4Address.PrefixLength<br>    $gw        = $ipConfig.IPv4DefaultGateway.NextHop<br><br>    return @{<br>        ActiveAdapter   = $activeAdapter<br>        IPConfig        = $ipConfig<br>        DNSServers      = $dnsList<br>        PublicIP        = $publicIp<br>        DefaultGateway  = $gw<br>        LocalIP         = $localIPv4<br>        SubnetMask      = $prefixLen<br>    }<br>}<br><br># ===================================<br># Main<br># ===================================<br>$ResultsObject = $null<br>$JsonOut = Join-Path $OutputFolder (\"SpeedTest_{0}_{1}.json\" -f $env:COMPUTERNAME,$NowStamp)<br>$CsvOut  = Join-Path $OutputFolder (\"SpeedTest_{0}_{1}.csv\"  -f $env:COMPUTERNAME,$NowStamp)<br><br>try {<br>    # 1) Netwerk info<br>    $networkInfo = Get-NetworkInfo<br><br>    # Log public\/private quick<br>    try {<br>        $GetpublicIP  = $networkInfo.PublicIP<br>    } catch { $GetpublicIP = $null }<br>    try {<br>        $GetprivateIP = (Get-NetIPAddress | Where-Object { $_.AddressState -eq \"Preferred\" -and $_.ValidLifetime -lt \"24:00:00\" -and $_.AddressFamily -eq 'IPv4' } | Select-Object -First 1).IPAddress<br>    } catch { $GetprivateIP = $null }<br><br>    WriteToLogFile -Message \"Current Public IP   = $GetpublicIP\"<br>    WriteToLogFile -Message \"Current Private IP  = $GetprivateIP\"<br>    WriteToLogFile -Message \"Active Adapter      = $($networkInfo.ActiveAdapter.Name) \/ $($networkInfo.ActiveAdapter.InterfaceDescription)\"<br><br>    # 2) Download Speedtest CLI<br>    Write-Console \"Downloading Speedtest CLI...\" \"Green\"<br>    WriteToLogFile -Message \"Downloading Speedtest from $speedtestUrl\"<br>    Invoke-WebRequest -Uri $speedtestUrl -OutFile $zipFile -UseBasicParsing -ErrorAction Stop<br><br>    # 3) Extract<br>    Write-Console \"Extracting files...\" \"Green\"<br>    WriteToLogFile -Message \"Extracting to $tempPath\"<br>    Expand-Archive -Path $zipFile -DestinationPath $tempPath -Force -ErrorAction Stop<br><br>    # Locate speedtest.exe (support nested folder structure)<br>    $speedtestExe = Get-ChildItem -Path $tempPath -Filter \"speedtest.exe\" -Recurse | Select-Object -First 1<br>    if (-not $speedtestExe) {<br>        throw \"speedtest.exe not found after extraction.\"<br>    }<br><br>    # 4) Run speed test<br>    Write-Console \"Running speed test...\" \"Green\"<br>    WriteToLogFile -Message \"Starting speed test\"<br>    Push-Location $speedtestExe.Directory.FullName<br>    $ResultsJson = &amp; .\\speedtest.exe --accept-license --accept-gdpr --format=json<br>    Pop-Location<br><br>    Write-Console \"Speed test completed!\" \"Green\"<br>    WriteToLogFile -Message \"Speed test completed\"<br><br>    if (-not $Silent) { Clear-Host }<br><br>    # 5) Parse + compute metrics (FIXED rounding)<br>    $results      = $ResultsJson | ConvertFrom-Json<br>    $downloadMbps = [math]::Round($results.download.bandwidth * 8 \/ 1MB, 2)<br>    $uploadMbps   = [math]::Round($results.upload.bandwidth   * 8 \/ 1MB, 2)<br>    $pingLatency  = [math]::Round($results.ping.latency, 2)<br>    $jitter       = [math]::Round($results.ping.jitter,  2)<br>    $packetLoss   = $results.packetLoss<br><br>    # 6) Geo info (best effort)<br>    $geoInfo = $null<br>    try {<br>        if ($networkInfo.PublicIP) {<br>            $geoInfo = Invoke-RestMethod -Uri (\"http:\/\/ip-api.com\/json\/{0}\" -f $networkInfo.PublicIP) -TimeoutSec 10<br>        }<br>    } catch {<br>        WriteToLogFile -Level \"WARN\" -Message \"Could not retrieve geolocation information: $($_.Exception.Message)\"<br>    }<br><br>    # 7) SSID (function now defined!)<br>    $SSID = Get-CurrentSSID<br><br>    # 8) Compose single PSCustomObject<br>    $ResultsObject = [PSCustomObject]@{<br>        # Speed Test Results<br>        SpeedTestDateTime     = (Get-Date).ToString(\"yyyy-MM-dd HH:mm:ss\")<br>        SSID                  = $SSID<br>        DownloadSpeed_Mbps    = $downloadMbps<br>        UploadSpeed_Mbps      = $uploadMbps<br>        PingLatency_ms        = $pingLatency<br>        Jitter_ms             = $jitter<br>        PacketLoss_Percent    = $packetLoss<br>        ISP                   = $results.isp<br>        TestServer            = \"$($results.server.name) - $($results.server.location), $($results.server.country)\"<br>        TestURL               = $results.result.url<br><br>        # Network Information<br>        ActiveAdapter         = $networkInfo.ActiveAdapter.Name<br>        AdapterType           = $networkInfo.ActiveAdapter.InterfaceDescription<br>        LinkSpeed             = $networkInfo.ActiveAdapter.LinkSpeed<br>        MACAddress            = $networkInfo.ActiveAdapter.MacAddress<br>        LocalIP               = (\"{0}\/{1}\" -f $networkInfo.LocalIP, $networkInfo.SubnetMask)<br>        DefaultGateway        = $networkInfo.DefaultGateway<br>        PublicIP              = $networkInfo.PublicIP<br>        DNSServers            = ($networkInfo.DNSServers -join \", \")<br>        ConnectionState       = $networkInfo.ActiveAdapter.Status<br><br>        # Geolocation Information<br>        Country               = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.country    } else { \"N\/A\" }<br>        Region                = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.regionName } else { \"N\/A\" }<br>        City                  = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.city       } else { \"N\/A\" }<br>        ZipCode               = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.zip        } else { \"N\/A\" }<br>        Latitude              = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.lat        } else { \"N\/A\" }<br>        Longitude             = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.lon        } else { \"N\/A\" }<br>        Timezone              = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.timezone   } else { \"N\/A\" }<br>        GeoISP                = if ($geoInfo -and $geoInfo.status -eq \"success\") { $geoInfo.isp        } else { \"N\/A\" }<br><br>        # Script\/Host context<br>        ScriptAuthor          = $ScriptAuthor<br>        ScriptVersion         = $ScripVersion<br>        ScriptChangeDate      = $ScriptChangeDate<br>        RunUser               = $ScriptCurrentUser<br>        RunDevice             = $ScriptRunningDevice<br>    }<br><br>    # 9) Log key metrics<br>    WriteToLogFile -Message \"Download: $downloadMbps Mbps | Upload: $uploadMbps Mbps | Ping: $pingLatency ms | Jitter: $jitter ms | Loss: $packetLoss\"<br>    WriteToLogFile -Message \"Server: $($ResultsObject.TestServer) | ISP: $($ResultsObject.ISP)\"<br>    WriteToLogFile -Message \"PublicIP: $($ResultsObject.PublicIP) | LocalIP: $($ResultsObject.LocalIP)\"<br><br>    # 10) Persist JSON + CSV<br>    $ResultsObject | ConvertTo-Json -Depth 6 | Out-File -FilePath $JsonOut -Encoding utf8<br>    $ResultsObject | Export-Csv -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Path $CsvOut<br>    WriteToLogFile -Message \"Saved JSON to $JsonOut\"<br>    WriteToLogFile -Message \"Saved CSV  to $CsvOut\"<br><br>} catch {<br>    WriteToLogFile -Level \"ERROR\" -Message $_.Exception.Message<br>    Write-Console \"Error: $($_.Exception.Message)\" \"Red\"<br>} finally {<br>    # Cleanup<br>    try { Set-Location $env:TEMP } catch {}<br>    foreach ($p in @($zipFile,$tempPath)) {<br>        try {<br>            if (Test-Path $p) {<br>                if ((Get-Item $p) -is [System.IO.DirectoryInfo]) {<br>                    Remove-Item $p -Recurse -Force -ErrorAction SilentlyContinue<br>                } else {<br>                    Remove-Item $p -Force -ErrorAction SilentlyContinue<br>                }<br>                WriteToLogFile -Level \"DEBUG\" -Message \"Cleaned up $p\"<br>            }<br>        } catch {}<br>    }<br><br>    # Transcript stop &amp; copy to IME logs<br>    try { Stop-Transcript | Out-Null } catch {}<br>    try {<br>        $imeLogs = \"C:\\ProgramData\\Microsoft\\IntuneManagementExtension\\Logs\"<br>        if (!(Test-Path $imeLogs)) { New-Item -ItemType Directory -Path $imeLogs | Out-Null }<br>        Copy-Item -Path $TranscriptFile -Destination $imeLogs -Force -ErrorAction SilentlyContinue<br>        WriteToLogFile -Message \"Transcript copied to $imeLogs\"<br>    } catch {}<br>}<br><br># Final output to pipeline for programmatic use<br>if ($ResultsObject) {<br>    $ResultsObject<br>}<br><br>if (-not $Silent) {<br>    Read-Host \"Press Enter to exit\"<br>}<\/pre>\n\n\n\n<p>\ud83d\udc49 <em>Tip: op je website kun je hier een \u201ccopy\u201d knop bij zetten \u2014 werkt altijd lekker.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcca Wat krijg je eruit?<\/h2>\n\n\n\n<p>Na het draaien van het script krijg je:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">JSON output (perfect voor automation)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ideaal voor API\u2019s, dashboards of logging pipelines<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">CSV output (lekker voor Excel)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Snel analyseren<\/li>\n\n\n\n<li>Trends bekijken<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Log file<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Volledige run geschiedenis<\/li>\n\n\n\n<li>Errors + debug info<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd0d Voorbeeld van data die je krijgt<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Download \/ upload snelheid (Mbps)<\/li>\n\n\n\n<li>Ping + jitter + packet loss<\/li>\n\n\n\n<li>ISP + testserver<\/li>\n\n\n\n<li>Adapter + MAC address<\/li>\n\n\n\n<li>DNS servers<\/li>\n\n\n\n<li>Public &amp; private IP<\/li>\n\n\n\n<li>Locatie (land, stad, timezone)<\/li>\n<\/ul>\n\n\n\n<p>Kort gezegd: <strong>alles wat je nodig hebt om een netwerkprobleem \u00e9cht te begrijpen<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\uddf0 Waar gebruik ik dit voor?<\/h2>\n\n\n\n<p>Een paar real-life use cases:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcbc Intune monitoring<\/h3>\n\n\n\n<p>Silent draaien op endpoints \u2192 resultaten verzamelen<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfe0 HomeLab insights<\/h3>\n\n\n\n<p>WiFi vs bekabeld vergelijken (spoiler: WiFi verliest altijd \ud83d\ude04)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddd1\u200d\ud83d\udcbb Troubleshooting bij klanten<\/h3>\n\n\n\n<p>Niet meer discussi\u00ebren \u2014 gewoon data laten zien<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcc8 Performance logging<\/h3>\n\n\n\n<p>Periodiek draaien \u2192 trends ontdekken<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u26a0\ufe0f Kleine kanttekeningen<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Admin rechten zijn verplicht<\/li>\n\n\n\n<li>Speedtest CLI wordt gedownload (internet nodig)<\/li>\n\n\n\n<li>Geolocation is \u201cbest effort\u201d (API afhankelijk)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udca1 Bonus tip<\/h2>\n\n\n\n<p>Wil je dit naar een hoger niveau tillen?<\/p>\n\n\n\n<p>Combineer dit met:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Task Scheduler (periodiek meten)<\/li>\n\n\n\n<li>Azure Log Analytics<\/li>\n\n\n\n<li>Power BI dashboard<\/li>\n<\/ul>\n\n\n\n<p>En ineens heb je <strong>enterprise-level netwerk monitoring<\/strong>\u2026 met PowerShell.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udfaf Conclusie<\/h2>\n\n\n\n<p>Dit script is ontstaan uit frustratie, maar ge\u00ebindigd als iets wat ik nu standaard gebruik.<\/p>\n\n\n\n<p>Geen nattevingerwerk meer.<br>Geen \u201chet zal wel aan WiFi liggen\u201d.<\/p>\n\n\n\n<p>Gewoon:<\/p>\n\n\n\n<p>\ud83d\udc49 meten<br>\ud83d\udc49 loggen<br>\ud83d\udc49 weten<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Iedereen kent het moment. Teams call die hapert.Download die blijft hangen op 2 MB\/s.Of die ene collega die<\/p>\n","protected":false},"author":2,"featured_media":148,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-146","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"_links":{"self":[{"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/posts\/146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/unen.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=146"}],"version-history":[{"count":2,"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/posts\/146\/revisions"}],"predecessor-version":[{"id":149,"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/posts\/146\/revisions\/149"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/unen.nl\/index.php?rest_route=\/wp\/v2\/media\/148"}],"wp:attachment":[{"href":"https:\/\/unen.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unen.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unen.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}