Automation
PowerShell: Mapping GPOs to their Linked Organizational Units

As an Active Directory environment grows, keeping track of where specific Group Policy Objects (GPOs) are linked becomes a significant challenge. The “Group Policy Management Console” (GPMC) is great for looking at one GPO at a time, but if you need a bird’s-eye view of your entire inheritance structure, you need automation.
This PowerShell script sweeps through all Organizational Units (OUs), identifies the unique GUIDs of linked policies, resolves those GUIDs into human-readable GPO names, and exports the mapping to a CSV file.
The PowerShell Script
Before running, create a folder at C:\temp\GroupPolicyandLinkedOU\. This script requires the Active Directory and Group Policy modules (included with RSAT).
# Initialize the output file with headers$Header = "GPO_Name;OU_Name;OU_DistinguishedName"$Path = "C:\temp\GroupPolicyandLinkedOU\out.csv"if (!(Test-Path "C:\temp\GroupPolicyandLinkedOU\")) { New-Item -ItemType Directory -Path "C:\temp\GroupPolicyandLinkedOU\" }$Header | Out-File $Path# Get all OUs with their linked GPO attributes$policies = Get-ADOrganizationalUnit -Filter * -Properties LinkedGroupPolicyObjects$policies | ForEach-Object { $OUName = $_.Name $OUDN = $_.DistinguishedName $LinkedGPOs = $_.LinkedGroupPolicyObjects foreach($LinkedGPO in $LinkedGPOs) { # Extract the GUID from the DistinguishedName string # String format is usually: cn={GUID},cn=policies,cn=system,DC=domain... $GUID = $LinkedGPO.Split(",")[0].Replace("cn={","").Replace("}","").Replace("CN={","") try { # Resolve the GUID to a friendly Display Name $GPO = Get-GPO -Guid $GUID $msg = "$($GPO.DisplayName);$OUName;$OUDN" # Output to console and file Write-Host "Mapped: $($GPO.DisplayName) -> $OUName" -ForegroundColor Cyan $msg | Out-File $Path -Append } catch { Write-Warning "Could not resolve GPO GUID: $GUID linked at $OUName" } }}
How it Works
- LinkedGroupPolicyObjects Property: The script looks at the raw attribute on the OU object. In Active Directory, links aren’t stored as names; they are stored as the DistinguishedName of the GPO container, which includes the GUID.
- String Manipulation: The script uses
.Splitand.Replaceto strip away the LDAP syntax, leaving only the raw GUID string. - Get-GPO -Guid: This cmdlet takes that raw ID and queries the domain for the actual GPO metadata, allowing us to retrieve the DisplayName.
- Semicolon Delimited: The output uses
;as a delimiter. When opening the file in Excel, you can easily use “Text to Columns” to separate the data into clean fields.
Why Use This Script?
- Inheritance Audits: Quickly see if a legacy GPO is linked to an OU it shouldn’t be.
- Troubleshooting: If a user is getting a strange setting, you can search the CSV for their OU and see every policy applied.
- Clean-up: Identify “ghost” links—SIDs/GUIDs that remain linked to an OU even though the GPO itself has been deleted.
#PowerShell #ActiveDirectory #GroupPolicy #SysAdmin #WindowsServer #ITAutomation #LazyAdmin #TechTips #ITPro #Infrastructure
PowerShell: Resolve Bulk IP Addresses to Hostnames

When you’re dealing with a large list of IP addresses from a firewall log or a network scan, manually running nslookup is not an option. You need a fast, automated way to perform a reverse DNS lookup to identify the devices on your network.
This script leverages the .NET [System.Net.Dns] class to perform high-speed lookups, converting a simple text file of IPs into a comma-separated list of hostnames.
The PowerShell Script
Save the code below as ResolveIPs.ps1. Create a file named hosts.txt in the same folder and paste your IP addresses (one per line).
PowerShell
# Get list from file, initialize empty array$ListOfIPs = Get-Content ".\hosts.txt"$ResultList = @()# Roll through the list, resolving with the .NET DNS resolverforeach ($IP in $ListOfIPs) { # Suppress errors for IPs that don't resolve $ErrorActionPreference = "silentlycontinue" $Result = $null # Status update for the user Write-Host "Resolving $IP..." -ForegroundColor Cyan # Pass the current IP to .NET for name resolution $Result = [System.Net.Dns]::GetHostEntry($IP) # Add results to the list if ($Result) { $ResultList += "$IP," + [string]$Result.HostName } else { $ResultList += "$IP,unresolved" }}# Export to file and notify completion$ResultList | Out-File .\resolved.txtWrite-Host "Name resolution complete! Check .\resolved.txt" -ForegroundColor Green
How it Works
[System.Net.Dns]::GetHostEntry($IP): This is the heart of the script. It queries your configured DNS servers for a Pointer (PTR) record associated with the IP address.- Error Action Silencing: Since it’s common for some IPs (like guest devices or unmanaged switches) to lack DNS records, we use
silentlycontinueto prevent the red error text from cluttering your console. - Array Building: The script creates a simple “IP,Hostname” format, which can easily be renamed to
.csvand opened in Excel for further analysis.
💡 Lazy Admin Tips
- DNS Suffixes: Ensure your machine has the correct DNS search suffixes configured. If the script only returns short names and you need FQDNs (Fully Qualified Domain Names), check your network adapter settings.
- Speed: The
.NETmethod used here is generally faster than the standardResolve-DnsNamecmdlet when dealing with large batches of legacy records. - Check Your PTRs: If the script returns “unresolved” for IPs you know are active, it’s a sign that your Reverse Lookup Zones in AD DNS might be missing records or need scavenging.
#PowerShell #Networking #DNS #SysAdmin #WindowsServer #Automation #ITPro #LazyAdmin #NetworkSecurity #TechTips
VBScript: Batch Audit Service Status Across Multiple Windows Servers

Keeping track of critical services—like SQL, IIS, or Print Spooler—across a large server farm is a common headache for admins. While PowerShell is the modern go-to, many legacy environments and specific automation workflows still rely on the reliability of VBScript and WMI (Windows Management Instrumentation).
This script allows you to pull a full inventory of every service on a list of servers, including their start mode (Automatic/Manual), current state (Running/Stopped), and the Service Account being used.
Prerequisites & Setup
- Create the workspace: Create a folder named
C:\Temp\ServiceDetails. - The Server List: Create a file named
Servers.txtin that folder. List your server names or IP addresses, one per line. - Permissions: You must run this script from an account that has Local Administrator rights on all target servers to query WMI.
The VBScript Solution
Save the code below as ServiceDetails.vbs in your C:\Temp\ServiceDetails folder.
' --- START OF SCRIPT ---ServerList = "C:\Temp\ServiceDetails\Servers.txt"arrServices = Array("") ' Leave empty to get all servicesDim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")Dim objOut : Set objOut = objFSO.CreateTextFile("C:\Temp\ServiceDetails\ServiceQuery.csv")arrComputers = Split(objFSO.OpenTextFile(ServerList).ReadAll, vbNewLine) ' Write CSV HeadersObjOut.WriteLine "SERVER, SERVICE DISPLAY NAME, SERVICE STARTMODE, SERVICE STATUS, SERVICE ACCOUNT"For Each strComputer In arrComputers If Trim(strComputer) <> "" Then strAlive = IsAlive(strComputer) objFound = 0 If strAlive = "Alive" Then On Error Resume Next Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") If Err.Number <> 0 Then ObjOut.WriteLine strComputer & ", WMI ERROR, N/A, N/A, N/A" Err.Clear Else Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Service") For Each objItem In colItems ObjOut.WriteLine strComputer & "," & objItem.DisplayName & "," & objItem.StartMode & "," & objItem.State & "," & objItem.StartName objFound = 1 Next End If Else ObjOut.WriteLine strComputer & "- UnResolved, N/A, N/A, N/A, N/A" End If End IfNextobjOut.CloseMsgBox "Service Export Complete!", 64, "LazyAdmin Notification"' Function to Ping the server before attempting WMI connectionFunction IsAlive(strComputer) Set WshShell = WScript.CreateObject("WScript.Shell") Set objExecObject = WshShell.Exec("%comspec% /c ping -n 1 -w 500 " & strComputer) strText = objExecObject.StdOut.ReadAll() If Instr(strText, "Reply from") > 0 Then IsAlive = "Alive" Else IsAlive = "Dead" End If End Function
How it Works
- WMI (Win32_Service): The script connects to the
root\CIMV2namespace on the remote machine to query theWin32_Serviceclass. This is the same data you see inservices.msc. - The Ping Check: Before trying to connect (which can be slow if a server is down), the
IsAlivefunction pings the host. This significantly speeds up the script if you have offline servers in your list. - CSV Output: All data is appended to a
.csvfile, making it ready for a pivot table in Excel to find services running under old service accounts or identifying disabled critical services.
#SysAdmin #WindowsServer #VBScript #WMI #ITAutomation #ServerManagement #TechTips #LazyAdmin #Infrastructure #ITAudit
PowerShell Script: Quickly Convert SIDs to Usernames

Have you ever looked at a security log or a orphaned folder permission and seen a string like S-1-5-21-3623811015-3361044348-30300820-1013? Those are SIDs (Security Identifiers). While they are great for the Windows OS, they are nearly impossible for humans to read.
If you have a list of these SIDs from an audit or a log file, you don’t have to look them up one by one. This PowerShell script will take a bulk list of SIDs and “translate” them into readable Usernames (UIDs).
The PowerShell Script
Save this script as SIDtoUID.ps1. It uses the .NET SecurityIdentifier class to perform the translation locally or against your Active Directory domain.
# Create or clear the output fileOut-File UID.txt# Loop through each SID in the source text fileforeach ($SID in (Get-Content SID.txt)){ # Create a SID object $objSID = New-Object System.Security.Principal.SecurityIdentifier ($SID) Try { # Attempt to translate the SID to an NT Account name $objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) # Append the Username to the output file $objUser.Value >> UID.txt Write-Host "Translated: $SID -> $($objUser.Value)" -ForegroundColor Green } Catch { # If translation fails (e.g., deleted account), keep the original SID $SID >> UID.txt Write-Warning "Failed to translate: $SID" }}
How to Use It
- Create your input: Create a file named
SID.txtin the same folder as the script. Paste your SIDs there, one per line. - Run the script: Open PowerShell and execute
.\SIDtoUID.ps1. - Check your results: A new file named
UID.txtwill appear, containing the translated usernames in the same order as your original list.
Why do SIDs sometimes fail to translate?
In the Catch block of the script, we tell PowerShell to just output the original SID if it can’t find a match. This usually happens for two reasons:
- Deleted Accounts: The user or group no longer exists in Active Directory, leaving behind an “orphaned” SID.
- Connectivity: Your machine cannot reach the Domain Controller to perform the lookup.
#PowerShell #ActiveDirectory #SysAdmin #ITPro #CyberSecurity #WindowsServer #Automation #LazyAdmin #TechTips #ITAudit
PowerShell Script: Export User Group Memberships to CSV

Auditing which users belong to which groups is one of the most frequent requests for a System Administrator. Whether it’s for a security audit, a helpdesk ticket, or a “copy permissions” request, digging through the Member Of tab in Active Directory is slow and prone to error.
This PowerShell script simplifies the process by generating a clean, object-based list of memberships that you can easily export to CSV, HTML, or plain text.
The PowerShell Script
Save the following code as Get-UserGroupMembership.ps1. It is designed to handle single users, lists from text files, or entire Organizational Units (OUs) via the pipeline.
Param ( [Parameter(Mandatory=$true,ValueFromPipeLine=$true)] [Alias("ID","Users","Name")] [string[]]$User)Begin { Try { Import-Module ActiveDirectory -ErrorAction Stop } Catch { Write-Host "Unable to load Active Directory module. Is RSAT installed?"; Break }}Process { ForEach ($U in $User) { Try { $UN = Get-ADUser $U -Properties MemberOf $Groups = ForEach ($Group in ($UN.MemberOf)) { (Get-ADGroup $Group).Name } # Sort groups alphabetically for a cleaner report $Groups = $Groups | Sort ForEach ($Group in $Groups) { New-Object PSObject -Property @[ordered]@{ User = $UN.Name Group = $Group } } } Catch { Write-Warning "Could not find user: $U" } }}
How to Use the Script
1. Single User Lookup
To quickly see the groups for one specific user:
PowerShell
.\Get-UserGroupMembership.ps1 -User "John.Doe"
2. Bulk Export from a Text File
If you have a list of usernames in users.txt, use this command to generate a full CSV report:
PowerShell
Get-Content C:\Temp\users.txt | .\Get-UserGroupMembership.ps1 | Export-CSV C:\Temp\UserMemberships.csv -NoTypeInformation
3. Audit an Entire OU
To see the memberships for every user within a specific department or location:
PowerShell
Get-ADUser -Filter * -SearchBase "OU=Users,DC=yourdomain,DC=local" | .\Get-UserGroupMembership.ps1 | Export-CSV C:\audit_output.csv -NoTypeInformation
Why This Method Beats the GUI
- Alphabetical Sorting: Groups are presented A-Z, making it much easier to read than the random order in ADUC.
- Pipeline Support: Because it outputs a PSObject, you can pipe it directly into
ConvertTo-HTMLfor a report orOut-GridViewfor an interactive window. - Automation Ready: You can schedule this script to run weekly to maintain a “snapshot” of your environment’s security posture.
#PowerShell #ActiveDirectory #SysAdmin #WindowsServer #ITAdmin #CyberSecurity #Automation #LazyAdmin #TechTips #ITAudit
Automating Active Directory: Export All AD Groups and Members to CSV

Auditing Active Directory groups is a fundamental part of identity management. Whether you are performing a quarterly security review or preparing for a domain migration, knowing exactly who is in which group—and what the scope of those groups is—is essential.
This PowerShell script does more than just list group names; it iterates through every group in your domain, identifies the members (skipping disabled users to keep your data clean), and exports everything into a dated CSV file.
The PowerShell Script
Save this script as ADGroupsExport.ps1 in C:\Temp\ExportADgroups. Ensure you are running this from a machine with the RSAT (Remote Server Administration Tools) installed and logged in with a domain account that has read permissions.
# Get year and month for the filename$DateTime = Get-Date -f "yyyy-MM"# Set CSV file destination$CSVFile = "C:\Temp\ExportADgroups\AD_Groups_"+$DateTime+".csv"if (!(Test-Path "C:\Temp\ExportADgroups")) { New-Item -ItemType Directory -Path "C:\Temp\ExportADgroups" }$CSVOutput = @()# Fetch all AD groups$ADGroups = Get-ADGroup -Filter *$i = 0$tot = $ADGroups.countforeach ($ADGroup in $ADGroups) { $i++ $status = "{0:N0}" -f ($i / $tot * 100) Write-Progress -Activity "Exporting AD Groups" -status "Processing Group $i of $tot : $status% Completed" -PercentComplete ($i / $tot * 100) $Members = "" # Fetch members and filter for enabled objects $MembersArr = Get-ADGroup $ADGroup.DistinguishedName -Properties Member | Select-Object -ExpandProperty Member if ($MembersArr) { foreach ($Member in $MembersArr) { $ADObj = Get-ADObject -Filter "DistinguishedName -eq '$Member'" -Properties Enabled # Skip disabled users to keep the report relevant if ($ADObj.ObjectClass -eq "user" -and $ADObj.Enabled -eq $false) { continue } $Members = $Members + "," + $ADObj.Name } if ($Members) { $Members = $Members.Substring(1) } } # Create ordered hash table for clean CSV columns $HashTab = [ordered]@{ "Name" = $ADGroup.Name "Category" = $ADGroup.GroupCategory "Scope" = $ADGroup.GroupScope "Members" = $Members } $CSVOutput += New-Object PSObject -Property $HashTab}# Sort by name and export$CSVOutput | Sort-Object Name | Export-Csv $CSVFile -NoTypeInformationWrite-Host "Export Complete: $CSVFile" -ForegroundColor Green
Key Features of this Script
- Progress Bar: Since large domains can take a long time to process, the
Write-Progressbar gives you a real-time percentage of the completion. - Clean Membership Lists: The script concatenates all members into a single “Members” column, separated by commas, making it easy to read in Excel.
- Disabled User Filtering: It intelligently checks the
Enabledstatus of user objects. If a user is disabled, they are omitted from the report to focus on active security risks. - Scope & Category: Clearly identifies if a group is Security vs. Distribution and Global vs. Universal.
#ActiveDirectory #PowerShell #SysAdmin #ITAutomation #WindowsServer #IdentityManagement #LazyAdmin #TechTips #Reporting #CyberSecurity
Deep Audit: Listing Nested Active Directory Group Members via VBScript | Lazy Admin Blog

Have you ever looked at a “Domain Admins” group and thought it looked suspiciously small? The culprit is usually nesting. Standard AD queries often fail to “recurse,” meaning they show you the subgroup but not the people inside it.
This script, ListGroupMembers_IncludingNested.vbs, uses a recursive function to dive into every sub-group and extract the actual users, ensuring your security audits are 100% accurate.
The Script: How it Works
The script utilizes a Dictionary Object to keep track of groups it has already scanned. This is a critical “Lazy Admin” safety feature—it prevents the script from getting stuck in an infinite loop if two groups are members of each other.
Usage Instructions
- Copy the code below into Notepad.
- Edit the
StrGroupNamevariable to match your target group. - Save the file as
ListGroupMembers.vbs. - Run it from the command prompt using
cscript ListGroupMembers.vbs.
' -- Save as ListGroupMembers_IncludingNested.vbsOption ExplicitDim ObjRootDSE, ObjConn, ObjRS, ObjCustomDim StrDomainName, StrGroupName, StrSQL, StrGroupDN, StrEmptySpaceSet ObjRootDSE = GetObject("LDAP://RootDSE")StrDomainName = Trim(ObjRootDSE.Get("DefaultNamingContext"))' -- Edit the line below with your Group NameStrGroupName = "YourGroupNameHere" StrSQL = "Select ADsPath From 'LDAP://" & StrDomainName & "' Where ObjectCategory = 'Group' AND Name = '" & StrGroupName & "'"Set ObjConn = CreateObject("ADODB.Connection")ObjConn.Provider = "ADsDSOObject": ObjConn.Open "Active Directory Provider"Set ObjRS = ObjConn.Execute(StrSQL)If ObjRS.EOF Then WScript.Echo "Group not found: " & StrGroupNameElse StrGroupDN = Trim(ObjRS.Fields("ADsPath").Value) Set ObjCustom = CreateObject("Scripting.Dictionary") GetAllNestedMembers StrGroupDN, " ", ObjCustomEnd If
Why VBScript in 2026?
While PowerShell is the modern standard, many legacy environments and automated scheduled tasks still rely on VBScript because it requires zero execution policy changes and runs natively on every Windows machine since Server 2000. It is the “Old Reliable” of the AD world.
Key Features of this Script
- Recursive Discovery: It doesn’t just stop at the first layer.
- Class Identification: Clearly marks if a member is a
User,Computer, or anotherGroup. - Loop Protection: Uses the
Scripting.Dictionaryto escape circular nesting traps.
#ActiveDirectory #WindowsServer #CyberSecurity #SysAdmin #ITAudit #VBScript #Automation #LazyAdmin #TechArchive
Stop Hunting for Web Servers: How to Auto-Discover Every IIS Instance in Your Domain | Lazy Admin Blog

Have you ever been asked for a list of every active web server in your environment, only to realize your documentation is six months out of date? You could check your DNS records manually, or you could let PowerShell do the detective work for you.
This script scans your Active Directory for Windows Servers, checks if the World Wide Web Publishing Service (W3SVC) is actually running, and then pulls a deep-profile of the hardware, OS, and network configuration for every active hit.
The Setup
- Create the workspace: Create a folder at
C:\Temp\ServersRunningIIS. - Prepare the list: The script will automatically generate a list of all Windows Servers from AD, but ensure you have the Active Directory PowerShell module installed.
- Run with Privileges: Since the script uses WMI to query remote system info (RAM, OS Version, etc.), run your PowerShell ISE or Console as a Domain Admin.
The PowerShell Script
# Script: IIS Server Discovery & Profiler# Location: lazyadminblog.com# Purpose: Identify active IIS nodes and collect hardware/OS specsImport-Module ActiveDirectory# 1. Harvest all Windows Servers from ADWrite-Host "Gathering server list from Active Directory..." -ForegroundColor Cyan$servers = Get-ADComputer -Filter {operatingsystem -Like "Windows server*"} | Select-Object -ExpandProperty Name$servers | Out-File "C:\Temp\ServersRunningIIS\serverlist.txt"# 2. Load the list for processing$serversall = Get-Content "C:\Temp\ServersRunningIIS\serverlist.txt" Start-Transcript -Path "C:\Temp\ServersRunningIIS\log_output.txt" -Appendforeach($vm in $serversall) { try { # Check if IIS Service (W3SVC) exists and is running $iis = Get-WmiObject Win32_Service -ComputerName $vm -Filter "name='W3SVC'" -ErrorAction SilentlyContinue if($iis.State -eq "Running") { Write-Host "FOUND: IIS is active on $vm" -BackgroundColor DarkBlue -ForegroundColor DarkYellow # Collect Network Info $ipinfo = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $vm | Where-Object {$_.IPEnabled -eq $true -and $_.IPAddress -like "1*"} | Select-Object -First 1 # Collect Hardware Info $hwinfo = Get-WmiObject Win32_Computersystem -ComputerName $vm # Collect OS Info $osinfo = Get-WmiObject Win32_OperatingSystem -ComputerName $vm # Flattening data for CSV-style output $allinfo = "$($hwinfo.Name);$($hwinfo.Domain);$($ipinfo.IPAddress);$($ipinfo.IPSubnet);$($ipinfo.DefaultIPGateway);$($hwinfo.TotalPhysicalMemory);$($hwinfo.Manufacturer);$($hwinfo.Model);$($osinfo.Caption);$($osinfo.OSArchitecture);$($osinfo.ServicePackMajorVersion);$($osinfo.SystemDrive);$($osinfo.Version)" # Save results to our 'Running' list $allinfo | Out-File "C:\Temp\ServersRunningIIS\RunningWebServers.txt" -Append } } catch { Write-Host "Could not connect to $vm" -ForegroundColor Red }}Stop-TranscriptWrite-Host "Audit Complete! Check C:\Temp\ServersRunningIIS\RunningWebServers.txt" -ForegroundColor Green
What’s inside the report?
The output file (RunningWebServers.txt) uses a semicolon (;) delimiter, making it easy to import into Excel. It captures:
- Network: IP Address, Subnet, and Gateway.
- Hardware: Manufacturer, Model, RAM, and Domain membership.
- Software: OS Version, Architecture (x64/x86), and System Drive.
Lazy Admin Tip
If you want to open the results immediately in Excel, just rename the output file from .txt to .csv and use the “Text to Columns” feature in Excel with the semicolon as the separator!
From Zero to Complete IP Inventory in 5 Seconds: The Multi-Host VBScript | Lazy Admin Blog

Manually documenting IP addresses, MACs, and DNS settings is the definition of “busy work.” This VBScript automates the entire process. It reads a list of servers from a text file, queries each one via WMI, and builds a professional Excel report in real-time.
How to Use This Script
- Prepare the Input: Create a text file (e.g.,
servers.txt) and list your hostnames or IP addresses, one per line. - Save the Script: Save the code below as
IPAddressInventory.vbs. - Run: Double-click the
.vbsfile. When prompted, provide the full path to your text file (e.g.,C:\Scripts\servers.txt). - Requirement: You must have Microsoft Excel installed on the machine where you run the script.
The VBScript Code
VBScript
' Save as IPAddressInventory.vbs' Input: Text file with Hostnames/IPs' Output: Excel Spreadsheet (IP_Addresses.xlsx)On Error Resume NextConst FOR_READING = 1'--- File Input ---strSrvListFile = InputBox ("Please enter the server list file path OR UNC file path" & vbCrLf & "Eg: C:\Scripts\server.txt" & vbCrLf & "Eg: \\servername\scripts\server.txt","File Input location")Set objFSO = CreateObject ("Scripting.FileSystemObject")Set objReadFile = objFSO.OpenTextFile (strSrvListFile, FOR_READING)'--- File Output ---strOutput = objfso.GetParentFolderName(strSrvListFile) &"\"'--- Error Handling ---If Err.Number <> 0 Then WScript.Echo "Please Enter a Valid file Name" Err.Clear WScript.QuitEnd If'--- Excel Object Creation ---Set objExcel = CreateObject ("Excel.application")objExcel.Visible = TrueSet objWorkbook = objExcel.Workbooks.Add()Set objWorksheet = objWorkbook.Worksheets("Sheet1")x = 1y = 1'--- Define Headers ---objWorksheet.Cells (x, y).value = "S.No"objWorksheet.Cells (x, y+1).value = "Server Name"objWorksheet.Cells (x, y+2).value = "Description"objWorksheet.Cells (x, y+3).value = "IP_Address"objWorksheet.Cells (x, y+4).value = "Subnet"objWorksheet.Cells (x, y+5).value = "MACAddress"objWorksheet.Cells (x, y+6).value = "Gateway" objWorksheet.Cells (x, y+7).value = "Preffered DNS"objWorksheet.Cells (x, y+8).value = "Primary DNS"objWorksheet.Cells (x, y+9).value = "Secondary DNS"objWorksheet.Cells (x, y+10).value = "Additional DNS 1"objWorksheet.Cells (x, y+11).value = "Additional DNS 2"objWorksheet.Cells (x, y+12).value = "WINS Primary"objWorksheet.Cells (x, y+13).value = "WINS Secondary"objWorksheet.Cells (x, y+14).value = "DNS Suffix"objWorksheet.Cells (x, y+15).value = "DNS Suffix Order"objWorksheet.Cells (x, y+16).value = "Remarks"s = 1Do Until objReadFile.AtEndOfStream k = 0 arrComputer = objReadFile.ReadLine strServer = Split (arrComputer, ",") objWorksheet.Cells (x+1, y).value = s objWorksheet.Cells (x+1, y+1).value = strServer(k) Set objWMIService = GetObject ("winmgmts:" & "!\\" & strServer(k) & "\root\cimv2") '--- Query Network Information --- If Err.Number = 0 Then WScript.Echo strServer(k) &": Inventoring" Set colAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True") For Each objAdapter in colAdapters objWorksheet.Cells(x+1, y+2).Value = objAdapter.Description ' IP Address Logic If Not IsNull(objAdapter.IPAddress) Then For i = LBound(objAdapter.IPAddress) To UBound(objAdapter.IPAddress) If Not InStr(objAdapter.IPAddress(i),":") > "0" Then objWorksheet.Cells(x+1, y+3).Value = objAdapter.IPAddress(i) End If Next End If ' Subnet Logic If Not IsNull(objAdapter.IPSubnet) Then For i = LBound(objAdapter.IPSubnet) To UBound(objAdapter.IPSubnet) If objAdapter.IPSubnet(i)<> "64" Then objWorksheet.Cells(x+1, y+4).Value = objAdapter.IPSubnet(i) End If Next End If objWorksheet.Cells(x+1, y+5).Value = objAdapter.MACAddress ' Gateway Logic If IsNull(objAdapter.DefaultIPGateway) Then objWorksheet.Cells(x+1, y+6).Value = "Gateway Not Set" Else For i = LBound(objAdapter.DefaultIPGateway) To UBound(objAdapter.DefaultIPGateway) objWorksheet.Cells(x+1, y+6).Value = objAdapter.DefaultIPGateway(i) Next End If ' DNS Logic If IsNull(objAdapter.DNSServerSearchOrder) Then objworksheet.Cells(x+1, y+7).Value = "DNS Not Set" Else For i = LBound(objAdapter.DNSServerSearchOrder) To UBound(objAdapter.DNSServerSearchOrder) objWorksheet.Cells(x+1, y+7).Value = objAdapter.DNSServerSearchOrder(i) y = y + 1 Next End If y = 1 objWorksheet.Cells(x+1, y+12).Value = objAdapter.WINSPrimaryServer objWorksheet.Cells(x+1, y+13).Value = objAdapter.WINSSecondaryServer objWorksheet.Cells(x+1, y+14).Value = objAdapter.DNSDomain ' Suffix Logic If IsNull(objAdapter.DNSDomainSuffixSearchOrder) Then objworksheet.Cells(x+1, y+14).Value = "Suffix Order NA" Else For i = LBound(objAdapter.DNSDomainSuffixSearchOrder) To UBound(objAdapter.DNSDomainSuffixSearchOrder) objWorksheet.Cells(x+1, y+15).Value = objAdapter.DNSDomainSuffixSearchOrder(i) x = x + 1 Next x = x - 1 End If x = x + 1 WScript.Echo strServer(k) &": Completed" Next Else ' Error Handling for Offline Servers objWorksheet.Cells(x+1, y+16).Value = Err.Number & "_" & Err.Description WScript.Echo strServer(k) &": "& Err.Description Err.Clear x = x + 1 End If s = s + 1Loop'--- Formatting and Saving ---Set objRange = objWorksheet.UsedRangeobjRange.EntireColumn.Autofit()objExcel.ActiveWorkbook.Saveas strOutput & "IP_Addresses.xlsx"MsgBox "Operation Completed Successfully " ,,"IP Address"
Key Features of the Script
- Automatic Excel Formatting: It uses
UsedRange.Autofit()to ensure the data is readable as soon as the file opens. - WMI Integration: It queries the
Win32_NetworkAdapterConfigurationclass directly from the remote machine. - Multi-Adapter Support: If a server has multiple enabled NICs, the script loops through each to capture all configurations.
- Remark Logging: If a machine is unreachable, the error code and description are written directly into the Excel “Remarks” column so you know which servers to check manually.

