param ( [string]$vcenter = "", [string]$folder = "", [string]$outputfile = "GIStatus.xlsx", [switch]$savecred, [switch]$Help = $false, [Parameter(ValueFromRemainingArguments=$true)] $UnmappedArguments ) # Variables $fileVersion = "1.0.0" $fileDate = "2026-07-29" $scriptName = Split-Path -Path $PSCommandPath -Leaf # Display Script Banner Write-Host "--------------------------------------------------" -ForegroundColor White Write-Host "Check VMs for Network Introspection Service" -ForegroundColor Green Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green Write-Host "Written by Charlie Silverman" -ForegroundColor Green Write-Host "--------------------------------------------------" -ForegroundColor White if ($UnmappedArguments) { Write-Warning "Invalid parameters: $UnmappedArguments" exit } function CheckModuleInstalled($moduleName, $command) { Write-Host "Checking that package $moduleName is installed..." -NoNewLine if (-not(get-command $command -erroraction silentlycontinue)) { Write-Host " Missing" -ForegroundColor Red if (-not (Get-Module -ListAvailable -Name $moduleName)) { $response = "" while (($response -ne "yes") -and ($response -ne "no")) { $response = (Read-Host "$moduleName module not instaled. Install now? (yes/no)").ToLower() } if ($response -eq "no") { Write-Host "Operation Cancelled." -ForegroundColor Yellow exit } Write-Host "Installing PowerShell module $moduleName..." -NoNewLine Install-Module -Name $moduleName -Scope CurrentUser -Force Write-Host " Success" -ForegroundColor Green } Write-Host "Loading PowerShell module $moduleName..." -NoNewLine Import-Module $moduleName Write-Host " Success" -ForegroundColor Green } else { Write-Host " Found" -ForegroundColor Green } } if ($Help) { Write-Host "Command Syntax:" -ForegroundColor Green Write-Host '$scriptName -vcenter [VCURI] -folder [FOLDER] -csvfile [CSVFILE] [-help] [-savecred]' -ForegroundColor Green Write-Host "" Write-Host "Command line options:" -ForegroundColor Green Write-Host "---------------------" -ForegroundColor Green Write-Host "-vcenter - Specify the URI for the vCenter server" -ForegroundColor Green Write-Host "-folder - Specify the folder to query. If not specified, all VMs will be processed." -ForegroundColor Green Write-Host "-outputfile - Specify the path to the CSV file for output. If not specified, the file name." -ForegroundColor Green Write-Host " ""GIStatus.csv"" will be saved to the current directory." -ForegroundColor Green Write-Host "-savecred - Save Credentials. If credentials were previously saved and this option is not selected," -ForegroundColor Green Write-Host " they will be used." -ForegroundColor Green Write-Host "-help - Show this help information." -ForegroundColor Green exit } # Check for required PowerShell Modules CheckModuleInstalled -moduleName "VCF.PowerCLI" -command "connect-viserver" CheckModuleInstalled -moduleName "ImportExcel" -command "import-excel" $quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false if ($vCenter -eq "") { $vCenter = Read-Host "Enter name of vCenter Server" } if (!(Test-Connection -ComputerName $vcenter -ErrorAction SilentlyContinue)) { Write-Error "ERROR: Unable to reach vCenter server $vcenter" exit } if ($SaveCred) { $credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter" $credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred Write-Host "Saving credentials." } if (Test-Path -path $env:USERPROFILE\kistools-$vcenter.cred -PathType Leaf) { $credentials = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred Write-Host "Using stored credentials" } else { $credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter" if (!$credentials) { Write-Warning "WARNING: No credentials were entered" } } if (Test-Path -path $outputfile -PathType Leaf -ErrorAction SilentlyContinue) { Write-Warning "File $outputfile already exists. Overwrite?" -NoNewLine Write-Host " (Y/N) " -NoNewLine if ((Read-Host) -eq "Y") { Remove-Item -Path $outputfile } else { Write-Error "Operation Aborted." exit } } try { Write-Host -NoNewLine "Connecting to vCenter $vcenter... " $vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue Write-Host "Success" -ForegroundColor green } catch { Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine Write-Host exit } if ($folder) { try { Write-Host -NoNewLine "Checking for folder $folder... " $vmfolder = Get-Folder $folder -ErrorAction SilentlyContinue if (!$vmfolder) { Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine Write-Host Write-Error "ERROR: Folder $folder not found. Please try again." exit } else { Write-Host "Success" -ForegroundColor green } } catch { Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine Write-Host Write-Error "ERROR: Unable to validate folder." exit } $vms = $vmfolder | Get-VM | Where-Object { $_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running" } | Sort-Object -Property Name } else { $VMs = Get-VM | Where-Object { $_.PowerState -eq "PoweredOn" -and $_.Guest.State -eq "Running" } | Sort-Object -Property Name } $vmresult = @() $counter = 0 foreach ($vm in $VMs) { $counter ++ $percent = ($counter / ($VMs.count + 1)) * 100 Write-Progress -Activity "Querying VMs" -Status "Checking VM $counter of $($VMs.count) - $([Math]::Round($percent))% complete" -PercentComplete $percent if ($vm.Guest.OSFullName -match "Windows") { try { if ($_.ExtensionData.Guest.ToolsVersionStatus -eq "guestToolsNeedUpgrade") { $note = " - VMware Tools Out of Date" } $script = "sc query vnetwfp" $ProgressPreference = 'SilentlyContinue' $result = Invoke-VMScript -VM $vm -ScriptText $script -ScriptType bat -WarningAction SilentlyContinue -ErrorAction Stop $ProgressPreference = 'Continue' if ($result.ScriptOutput -notmatch "RUNNING") { $vmresult += [PSCustomObject]@{ VMName = $vm.Name OS = $vm.Guest.OSFullName VMToolsVersion = $vm.ExtensionData.Guest.ToolsVersion VMToolsStatus = $vm.ExtensionData.Guest.ToolsVersionStatus Status = "Network Introspection not enabled" Note = $note } } else { $vmresult += [PSCustomObject]@{ VMName = $vm.Name OS = $vm.Guest.OSFullName VMToolsVersion = $vm.ExtensionData.Guest.ToolsVersion VMToolsStatus = $vm.ExtensionData.Guest.ToolsVersionStatus Status = "Network Introspection enabled" Note = $note } } } catch { $vmresult += [PSCustomObject]@{ VMName = $vm.Name OS = $vm.Guest.OSFullName VMToolsVersion = $vm.ExtensionData.Guest.ToolsVersion VMToolsStatus = $vm.ExtensionData.Guest.ToolsVersionStatus Status = "ERROR" Note = "Unable to query status$note" } } } } Write-Progress -Activity "Querying VMs" -Completed $sheetTitle = "Network Introspection Status For $vcenter" if ($vmfolder) { $sheetTitle += " - Folder $folder" } echo $vmresult Write-Host "Writing information about $($vmresult.length) VMs to file $outputfile..." -NoNewLine $exceltable = $vmresult | Export-Excel -path $outputfile -WorksheetName "Network Introspection Status" -PassThru -Autosize -FreezeTopRow ` -TableName "NIStatus" -TableStyle Medium15 -Title $sheetTitle -TitleBold -TitleSize 22 $exceltable.Workbook.WorkSheets[1].Tables["NIStatus"].ShowFilter = $false Close-ExcelPackage $exceltable Write-Host " Success" -ForegroundColor Green