├── Collect-ServerInfo.ps1
├── LICENSE
└── README.md
/Collect-ServerInfo.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Collect-ServerInfo.ps1 - PowerShell script to collect information about Windows servers
4 |
5 | .DESCRIPTION
6 | This PowerShell script runs a series of WMI and other queries to collect information
7 | about Windows servers.
8 |
9 | .OUTPUTS
10 | Each server's results are output to HTML.
11 |
12 | .PARAMETER -Verbose
13 | See more detailed progress as the script is running.
14 |
15 | .EXAMPLE
16 | .\Collect-ServerInfo.ps1 SERVER1
17 | Collect information about a single server.
18 |
19 | .EXAMPLE
20 | "SERVER1","SERVER2","SERVER3" | .\Collect-ServerInfo.ps1
21 | Collect information about multiple servers.
22 |
23 | .EXAMPLE
24 | Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*"} | %{.\Collect-ServerInfo.ps1 $_.DNSHostName}
25 | Collects information about all servers in Active Directory.
26 |
27 |
28 | .NOTES
29 | Written by: Paul Cunningham
30 |
31 | Find me on:
32 |
33 | * My Blog: https://paulcunningham.me
34 | * Twitter: https://twitter.com/paulcunningham
35 | * LinkedIn: https://au.linkedin.com/in/cunninghamp/
36 | * Github: https://github.com/cunninghamp
37 |
38 | License:
39 |
40 | The MIT License (MIT)
41 |
42 | Copyright (c) 2016 Paul Cunningham
43 |
44 | Permission is hereby granted, free of charge, to any person obtaining a copy
45 | of this software and associated documentation files (the "Software"), to deal
46 | in the Software without restriction, including without limitation the rights
47 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
48 | copies of the Software, and to permit persons to whom the Software is
49 | furnished to do so, subject to the following conditions:
50 |
51 | The above copyright notice and this permission notice shall be included in all
52 | copies or substantial portions of the Software.
53 |
54 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
59 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
60 | SOFTWARE.
61 |
62 | Change Log:
63 | V1.00, 20/04/2015 - First release
64 | V1.01, 01/05/2015 - Updated with better error handling
65 | #>
66 |
67 |
68 | [CmdletBinding()]
69 |
70 | Param (
71 |
72 | [parameter(ValueFromPipeline=$True)]
73 | [string[]]$ComputerName
74 |
75 | )
76 |
77 | Begin
78 | {
79 | #Initialize
80 | Write-Verbose "Initializing"
81 |
82 | }
83 |
84 | Process
85 | {
86 |
87 | #---------------------------------------------------------------------
88 | # Process each ComputerName
89 | #---------------------------------------------------------------------
90 |
91 | if (!($PSCmdlet.MyInvocation.BoundParameters[“Verbose”].IsPresent))
92 | {
93 | Write-Host "Processing $ComputerName"
94 | }
95 |
96 | Write-Verbose "=====> Processing $ComputerName <====="
97 |
98 | $htmlreport = @()
99 | $htmlbody = @()
100 | $htmlfile = "$($ComputerName).html"
101 | $spacer = "
"
102 |
103 | #---------------------------------------------------------------------
104 | # Do 10 pings and calculate the fastest response time
105 | # Not using the response time in the report yet so it might be
106 | # removed later.
107 | #---------------------------------------------------------------------
108 |
109 | try
110 | {
111 | $bestping = (Test-Connection -ComputerName $ComputerName -Count 10 -ErrorAction STOP | Sort ResponseTime)[0].ResponseTime
112 | }
113 | catch
114 | {
115 | Write-Warning $_.Exception.Message
116 | $bestping = "Unable to connect"
117 | }
118 |
119 | if ($bestping -eq "Unable to connect")
120 | {
121 | if (!($PSCmdlet.MyInvocation.BoundParameters[“Verbose”].IsPresent))
122 | {
123 | Write-Host "Unable to connect to $ComputerName"
124 | }
125 |
126 | "Unable to connect to $ComputerName"
127 | }
128 | else
129 | {
130 |
131 | #---------------------------------------------------------------------
132 | # Collect computer system information and convert to HTML fragment
133 | #---------------------------------------------------------------------
134 |
135 | Write-Verbose "Collecting computer system information"
136 |
137 | $subhead = "
Computer System Information
"
138 | $htmlbody += $subhead
139 |
140 | try
141 | {
142 | $csinfo = Get-WmiObject Win32_ComputerSystem -ComputerName $ComputerName -ErrorAction STOP |
143 | Select-Object Name,Manufacturer,Model,
144 | @{Name='Physical Processors';Expression={$_.NumberOfProcessors}},
145 | @{Name='Logical Processors';Expression={$_.NumberOfLogicalProcessors}},
146 | @{Name='Total Physical Memory (Gb)';Expression={
147 | $tpm = $_.TotalPhysicalMemory/1GB;
148 | "{0:F0}" -f $tpm
149 | }},
150 | DnsHostName,Domain
151 |
152 | $htmlbody += $csinfo | ConvertTo-Html -Fragment
153 | $htmlbody += $spacer
154 |
155 | }
156 | catch
157 | {
158 | Write-Warning $_.Exception.Message
159 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
160 | $htmlbody += $spacer
161 | }
162 |
163 |
164 |
165 | #---------------------------------------------------------------------
166 | # Collect operating system information and convert to HTML fragment
167 | #---------------------------------------------------------------------
168 |
169 | Write-Verbose "Collecting operating system information"
170 |
171 | $subhead = "Operating System Information
"
172 | $htmlbody += $subhead
173 |
174 | try
175 | {
176 | $osinfo = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName -ErrorAction STOP |
177 | Select-Object @{Name='Operating System';Expression={$_.Caption}},
178 | @{Name='Architecture';Expression={$_.OSArchitecture}},
179 | Version,Organization,
180 | @{Name='Install Date';Expression={
181 | $installdate = [datetime]::ParseExact($_.InstallDate.SubString(0,8),"yyyyMMdd",$null);
182 | $installdate.ToShortDateString()
183 | }},
184 | WindowsDirectory
185 |
186 | $htmlbody += $osinfo | ConvertTo-Html -Fragment
187 | $htmlbody += $spacer
188 | }
189 | catch
190 | {
191 | Write-Warning $_.Exception.Message
192 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
193 | $htmlbody += $spacer
194 | }
195 |
196 |
197 | #---------------------------------------------------------------------
198 | # Collect physical memory information and convert to HTML fragment
199 | #---------------------------------------------------------------------
200 |
201 | Write-Verbose "Collecting physical memory information"
202 |
203 | $subhead = "Physical Memory Information
"
204 | $htmlbody += $subhead
205 |
206 | try
207 | {
208 | $memorybanks = @()
209 | $physicalmemoryinfo = @(Get-WmiObject Win32_PhysicalMemory -ComputerName $ComputerName -ErrorAction STOP |
210 | Select-Object DeviceLocator,Manufacturer,Speed,Capacity)
211 |
212 | foreach ($bank in $physicalmemoryinfo)
213 | {
214 | $memObject = New-Object PSObject
215 | $memObject | Add-Member NoteProperty -Name "Device Locator" -Value $bank.DeviceLocator
216 | $memObject | Add-Member NoteProperty -Name "Manufacturer" -Value $bank.Manufacturer
217 | $memObject | Add-Member NoteProperty -Name "Speed" -Value $bank.Speed
218 | $memObject | Add-Member NoteProperty -Name "Capacity (GB)" -Value ("{0:F0}" -f $bank.Capacity/1GB)
219 |
220 | $memorybanks += $memObject
221 | }
222 |
223 | $htmlbody += $memorybanks | ConvertTo-Html -Fragment
224 | $htmlbody += $spacer
225 | }
226 | catch
227 | {
228 | Write-Warning $_.Exception.Message
229 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
230 | $htmlbody += $spacer
231 | }
232 |
233 |
234 | #---------------------------------------------------------------------
235 | # Collect pagefile information and convert to HTML fragment
236 | #---------------------------------------------------------------------
237 |
238 | $subhead = "PageFile Information
"
239 | $htmlbody += $subhead
240 |
241 | Write-Verbose "Collecting pagefile information"
242 |
243 | try
244 | {
245 | $pagefileinfo = Get-WmiObject Win32_PageFileUsage -ComputerName $ComputerName -ErrorAction STOP |
246 | Select-Object @{Name='Pagefile Name';Expression={$_.Name}},
247 | @{Name='Allocated Size (Mb)';Expression={$_.AllocatedBaseSize}}
248 |
249 | $htmlbody += $pagefileinfo | ConvertTo-Html -Fragment
250 | $htmlbody += $spacer
251 | }
252 | catch
253 | {
254 | Write-Warning $_.Exception.Message
255 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
256 | $htmlbody += $spacer
257 | }
258 |
259 |
260 | #---------------------------------------------------------------------
261 | # Collect BIOS information and convert to HTML fragment
262 | #---------------------------------------------------------------------
263 |
264 | $subhead = "BIOS Information
"
265 | $htmlbody += $subhead
266 |
267 | Write-Verbose "Collecting BIOS information"
268 |
269 | try
270 | {
271 | $biosinfo = Get-WmiObject Win32_Bios -ComputerName $ComputerName -ErrorAction STOP |
272 | Select-Object Status,Version,Manufacturer,
273 | @{Name='Release Date';Expression={
274 | $releasedate = [datetime]::ParseExact($_.ReleaseDate.SubString(0,8),"yyyyMMdd",$null);
275 | $releasedate.ToShortDateString()
276 | }},
277 | @{Name='Serial Number';Expression={$_.SerialNumber}}
278 |
279 | $htmlbody += $biosinfo | ConvertTo-Html -Fragment
280 | $htmlbody += $spacer
281 | }
282 | catch
283 | {
284 | Write-Warning $_.Exception.Message
285 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
286 | $htmlbody += $spacer
287 | }
288 |
289 |
290 | #---------------------------------------------------------------------
291 | # Collect logical disk information and convert to HTML fragment
292 | #---------------------------------------------------------------------
293 |
294 | $subhead = "Logical Disk Information
"
295 | $htmlbody += $subhead
296 |
297 | Write-Verbose "Collecting logical disk information"
298 |
299 | try
300 | {
301 | $diskinfo = Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName -ErrorAction STOP |
302 | Select-Object DeviceID,FileSystem,VolumeName,
303 | @{Expression={$_.Size /1Gb -as [int]};Label="Total Size (GB)"},
304 | @{Expression={$_.Freespace / 1Gb -as [int]};Label="Free Space (GB)"}
305 |
306 | $htmlbody += $diskinfo | ConvertTo-Html -Fragment
307 | $htmlbody += $spacer
308 | }
309 | catch
310 | {
311 | Write-Warning $_.Exception.Message
312 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
313 | $htmlbody += $spacer
314 | }
315 |
316 |
317 | #---------------------------------------------------------------------
318 | # Collect volume information and convert to HTML fragment
319 | #---------------------------------------------------------------------
320 |
321 | $subhead = "Volume Information
"
322 | $htmlbody += $subhead
323 |
324 | Write-Verbose "Collecting volume information"
325 |
326 | try
327 | {
328 | $volinfo = Get-WmiObject Win32_Volume -ComputerName $ComputerName -ErrorAction STOP |
329 | Select-Object Label,Name,DeviceID,SystemVolume,
330 | @{Expression={$_.Capacity /1Gb -as [int]};Label="Total Size (GB)"},
331 | @{Expression={$_.Freespace / 1Gb -as [int]};Label="Free Space (GB)"}
332 |
333 | $htmlbody += $volinfo | ConvertTo-Html -Fragment
334 | $htmlbody += $spacer
335 | }
336 | catch
337 | {
338 | Write-Warning $_.Exception.Message
339 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
340 | $htmlbody += $spacer
341 | }
342 |
343 |
344 | #---------------------------------------------------------------------
345 | # Collect network interface information and convert to HTML fragment
346 | #---------------------------------------------------------------------
347 |
348 | $subhead = "Network Interface Information
"
349 | $htmlbody += $subhead
350 |
351 | Write-Verbose "Collecting network interface information"
352 |
353 | try
354 | {
355 | $nics = @()
356 | $nicinfo = @(Get-WmiObject Win32_NetworkAdapter -ComputerName $ComputerName -ErrorAction STOP | Where {$_.PhysicalAdapter} |
357 | Select-Object Name,AdapterType,MACAddress,
358 | @{Name='ConnectionName';Expression={$_.NetConnectionID}},
359 | @{Name='Enabled';Expression={$_.NetEnabled}},
360 | @{Name='Speed';Expression={$_.Speed/1000000}})
361 |
362 | $nwinfo = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -ErrorAction STOP |
363 | Select-Object Description, DHCPServer,
364 | @{Name='IpAddress';Expression={$_.IpAddress -join '; '}},
365 | @{Name='IpSubnet';Expression={$_.IpSubnet -join '; '}},
366 | @{Name='DefaultIPgateway';Expression={$_.DefaultIPgateway -join '; '}},
367 | @{Name='DNSServerSearchOrder';Expression={$_.DNSServerSearchOrder -join '; '}}
368 |
369 | foreach ($nic in $nicinfo)
370 | {
371 | $nicObject = New-Object PSObject
372 | $nicObject | Add-Member NoteProperty -Name "Connection Name" -Value $nic.connectionname
373 | $nicObject | Add-Member NoteProperty -Name "Adapter Name" -Value $nic.Name
374 | $nicObject | Add-Member NoteProperty -Name "Type" -Value $nic.AdapterType
375 | $nicObject | Add-Member NoteProperty -Name "MAC" -Value $nic.MACAddress
376 | $nicObject | Add-Member NoteProperty -Name "Enabled" -Value $nic.Enabled
377 | $nicObject | Add-Member NoteProperty -Name "Speed (Mbps)" -Value $nic.Speed
378 |
379 | $ipaddress = ($nwinfo | Where {$_.Description -eq $nic.Name}).IpAddress
380 | $nicObject | Add-Member NoteProperty -Name "IPAddress" -Value $ipaddress
381 |
382 | $nics += $nicObject
383 | }
384 |
385 | $htmlbody += $nics | ConvertTo-Html -Fragment
386 | $htmlbody += $spacer
387 | }
388 | catch
389 | {
390 | Write-Warning $_.Exception.Message
391 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
392 | $htmlbody += $spacer
393 | }
394 |
395 |
396 | #---------------------------------------------------------------------
397 | # Collect software information and convert to HTML fragment
398 | #---------------------------------------------------------------------
399 |
400 | $subhead = "Software Information
"
401 | $htmlbody += $subhead
402 |
403 | Write-Verbose "Collecting software information"
404 |
405 | try
406 | {
407 | $software = Get-WmiObject Win32_Product -ComputerName $ComputerName -ErrorAction STOP | Select-Object Vendor,Name,Version | Sort-Object Vendor,Name
408 |
409 | $htmlbody += $software | ConvertTo-Html -Fragment
410 | $htmlbody += $spacer
411 |
412 | }
413 | catch
414 | {
415 | Write-Warning $_.Exception.Message
416 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
417 | $htmlbody += $spacer
418 | }
419 |
420 | #---------------------------------------------------------------------
421 | # Collect services information and covert to HTML fragment
422 | # Added by Nicolas Nowinski (nicknow@nicknow.net): Mar 28 2019
423 | #---------------------------------------------------------------------
424 |
425 | $subhead = "Computer Services Information
"
426 | $htmlbody += $subhead
427 |
428 | Write-Verbose "Collecting services information"
429 |
430 | try
431 | {
432 | $services = Get-WmiObject Win32_Service -ComputerName $ComputerName -ErrorAction STOP | Select-Object Name,StartName,State,StartMode | Sort-Object Name
433 |
434 | $htmlbody += $services | ConvertTo-Html -Fragment
435 | $htmlbody += $spacer
436 |
437 | }
438 | catch
439 | {
440 | Write-Warning $_.Exception.Message
441 | $htmlbody += "An error was encountered. $($_.Exception.Message)
"
442 | $htmlbody += $spacer
443 | }
444 |
445 | #---------------------------------------------------------------------
446 | # Generate the HTML report and output to file
447 | #---------------------------------------------------------------------
448 |
449 | Write-Verbose "Producing HTML report"
450 |
451 | $reportime = Get-Date
452 |
453 | #Common HTML head and styles
454 | $htmlhead="
455 |
468 |
469 | Server Info: $ComputerName
470 | Generated: $reportime
"
471 |
472 | $htmltail = "
473 | "
474 |
475 | $htmlreport = $htmlhead + $htmlbody + $htmltail
476 |
477 | $htmlreport | Out-File $htmlfile -Encoding Utf8
478 | }
479 |
480 | }
481 |
482 | End
483 | {
484 | #Wrap it up
485 | Write-Verbose "=====> Finished <====="
486 | }
487 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Paul Cunningham
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Collect-ServerInfo
2 | This PowerShell script runs a series of WMI and other queries to collect information about Windows servers.
3 |
4 | Each server's results are output to a HTML file.
5 |
6 | ## Parameters
7 | - **-Verbose**, See more detailed progress as the script is running.
8 |
9 | ## Examples
10 |
11 | Collect information about a single server named SERVER1.
12 | ```
13 | .\Collect-ServerInfo.ps1 SERVER1
14 | ```
15 |
16 | Collect information about multiple servers.
17 | ```
18 | "SERVER1","SERVER2","SERVER3" | .\Collect-ServerInfo.ps1
19 | ```
20 |
21 | Collect information about all servers in Active Directory.
22 | ```
23 | Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*"} | %{.\Collect-ServerInfo.ps1 $_.DNSHostName}
24 | ```
25 |
26 | ## Download
27 |
28 | Download the latest release from [Github](https://github.com/cunninghamp/Collect-ServerInfo/releases/latest) or from the [TechNet Script Gallery](https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Collect-Server-089f1da3).
29 |
30 | ## Credits
31 | Written by: Paul Cunningham
32 |
33 | Find me on:
34 |
35 | * My Blog: https://paulcunningham.me
36 | * Twitter: https://twitter.com/paulcunningham
37 | * LinkedIn: https://au.linkedin.com/in/cunninghamp/
38 | * Github: https://github.com/cunninghamp
39 |
40 | Additional contributions by:
41 | * [Nicolas Nowinski](https://github.com/nicknow)
42 |
--------------------------------------------------------------------------------