#
# Script: VM Service Report v1.0
# Joseph Kyle Weir
# jkw117@gmail.com
# 8/21/08
# This Script is to determine what services are running on what vm's in a VI organization
# This is very handy when you have many vm's running all types of services - and can point out a rogue service you may not want to have in your VM's
#
# This script will require:
# An administrator account to remote servers that are in the VI as WMI is used to obtain information. - This is described further below.
#
# Will get a list of services - output these along with the VM, IP information and vmnetwork for NICS.
# There is a list of services that are excluded by default, this can be disabled if needbe by changing the stdservices variable below.
# I use WMI to obtain information from the servers - for this to work correctly you need to have administrator access to all of the servers and they need to have WMI/RPC working.
# So some webservers etc. may not show any services as the app can't talk to them (in some ways if it can it may be a security problem)
# In my environment I run this script under an account that is the Enterprise Admin in the root domain for the Active Directory. Or any account that has administrator access on all of the servers.
# The description is obtained as well as the status of each service to further assist the user to determine what a service is.
#
# Replace account information below
$viserver = "vicenter" # Virtual Center DNS name or IP
$viuser = "Administrator" # Virtual Center Username
$vipassword = "password" # Virtual Center Password
$runningservices = 1 # 0 - for services regardless of status, 1 - for only running services,
$stdservices = 1 # 0 - to show all services, 1 - to exclude services that are listed in the $excludedservices variable below.
$servicerowstart = 10 # Row on the excel spreadsheet where the services are displayed - This can be changed to allow more IP information to be displayed if you have multiple IP's/ NICS (I've given enough space to have 4 ip's/network cards)

# Dealing with errors
#$warningPreference = "SilentlyContinue"
#$errorActionPreference = "SilentlyContinue"
$error=$null

# List of services to be excluded - These are the standard/base services installed on an XP machine - most of these pass on to 2000 & 2003 servers.
# This list can be extended or reduced depending on the users needs.
if ($stdservices -eq 1) {
$excludedservices = "Alerter","ALG","appmgt","wuaUserv","BITS","Clipsrv","Event System","Browser","CryptSvc","DcomLaunch","Dhcp","TrkWks","msdtc","Dnscache","Replicator","Ersvc","EventLog","FastUserSwitching Compatibility","Fax","helpsvc","HidServ","HTTPFilter","ImapiService","cisvc","PolicyAgent","LicenseService","Dmserver","Dmadmin","swprv","Messenger","Netman","Netlogon","Nmnsrvc","NetDDE","NetDDEdsdm","nla","xmlprov","NtLmSsp","sysmonLog","PlugPlay","UPNPhost","WmdmPmSN","Spooler","ProtectedStorage","rsvp","Rasauto","Rasman","RDSessMgr","RpcSs","RpcLocator","RemoteRegistry","Ntmssvc","RemoteAccess","secLogon","SamSs","wscsvc","LanmanServer","ShellHWDetection","ScardSrv","ScardDrv","Snmp","SSDPSRV","SENS","srservice","Schedule","lmHosts","TapiSrv","TlntSvr","TermService","Themes","UPS","UPNPhost","uploadmgr","VSS","WebClient","AudioSrv","SharedAccess","stisvc","MSIServer","WinMgmt","Wmi","W32time","WZCSVC","WmiApSrv","lanmanworkstation"
}else {$excludedservices =""}

Connect-VIServer -Server $viserver -User $viuser -Password $vipassword

# Setup Excel Sheet

$Excel = New-Object -Com Excel.Application
$Excel.visible = $True
$Excel = $Excel.Workbooks.Add()
$Addsheet = $Excel.sheets.Add()
$Sheet = $Excel.WorkSheets.Item(1)
$Sheet.Cells.Item(1,1)="VM Name"
for ($vmnetlabel = 2;$vmnetlabel -lt ($servicerowstart-1);$vmnetlabel++)
{$Sheet.Cells.Item($vmnetlabel,1)="VM Network/IP"}
$Sheet.Cells.Item($servicerowstart,1)="services"

# Setup array for Cell Columns
# This method was used as formula's were having problems after the first 26 columns
$col1=1
$col2=1
[System.Array]$alphabet = $null
for ($col=0 ; $col -le 675; $col++)
{

if ($col1 -gt 26) {
$col1=1
$col2++
}
if ($col2 -gt 26) {
$col1=1
$col2=1
}
if ($col -lt 26) {
$alphabet += [char]($col1+64)
}else
{
$alphabet += ([char]($col2+63) + [char]($col1+64))
}
$col1++
}


# Get List of VM's and IP's

# This section will one day get a list of Hosts and seperate the VM's of each ESX server onto seperate worksheets

# This Section will ping all ports on the esx server itself and then the vm's and find all open ports and display them in the worksheet

# Get guest VM data
$guestvms = Get-VMGuest -VM (Get-VM) |Select-Object VmName,IPAddress,Nics,State,HostName

$col = 2 # Variable use to set the initial column in the excel sheet to start
for ($vmloop=0;$vmloop -le ($guestvms.count);$vmloop++){ #replace 2 with $guestvms.count
if ($guestvms[$vmloop].State -eq "Running"){
# Gather information for networks for VM - In case their are multiple nics
$nic = $guestvms[$vmloop].Nics|Select-Object NetworkName,IPAddress
# Display VM name and the DNS hostname on the spreadsheet
$Sheet.Cells.Item(1,$col) = $guestvms[$vmloop].VmName
$Sheet.Cells.Item(2,$col) = $guestvms[$vmloop].hostname

# Display single nic and multiple IP's on a VM
if ($guestvms[$vmloop].nics.count -eq 1) {
for ($iploop=0;$iploop -lt ($nic.ipaddress.count);$iploop++)
{
$Sheet.Cells.Item($iploop + 3,$col) = $nic.networkname
$Sheet.Cells.Item($iploop + 3,$col+1) = $nic.IPaddress[$iploop]
}
}else # This section deals with multiple nics
{
for ($nicloop=0;$nicloop -lt $guestvms[$vmloop].Nics.count;$nicloop++)
{
$Sheet.Cells.Item($nicloop + $iploop + 1,$col) = $nic[$nicloop].networkname
$Sheet.Cells.Item($nicloop + $iploop + 1,$col+1) = $nic[$nicloop].IPaddress
}
}

# Gather WMI service list from machine - and only capture those not in the service list

if ($runningservices -eq 1){
$errorcount=$error.count
$guestwmi= Get-WmiObject win32_service -ComputerName $guestvms[$vmloop].ipaddress -Filter "state='Running'" |where {$excludedservices -notcontains $_.Name } |select-object name,state,description
if ($error.Count -ne $errorcount) {
$guestwmi= Get-WmiObject win32_service -Credential -ComputerName $guestvms[$vmloop].ipaddress -Filter "state='Running'" |where {$excludedservices -notcontains $_.Name } |select-object name,state,description
}
}
else
{
$errorcount=$error.count
$guestwmi= Get-WmiObject win32_service -ComputerName $guestvms[$vmloop].ipaddress |where {$excludedservices -notcontains $_.Name } |select-object name,state,description
if ($error.Count -ne $errorcount) {
$guestwmi= Get-WmiObject win32_service -ComputerName $guestvms[$vmloop].ipaddress |where {$excludedservices -notcontains $_.Name } |select-object name,state,description
}
}
}

# Display WMI services that are running
for ($x=0;$x -le $guestwmi.length;$x++){
$Sheet.Cells.Item($x+$servicerowstart,$col) = $guestwmi[$x].name # Service Name
$Sheet.Cells.Item($x+$servicerowstart,$col + 1) = $guestwmi[$x].state #Service State
# converts the column number into the excel column letter - for all those trying to figure it out
if($guestwmi[$x].description -ne $null)
{ #check if description is null and if so do not add description
$colletter=$alphabet[$col-1]+($x+$servicerowstart)
$Sheet.range($colletter).addcomment($guestwmi[$x].description) # add description to the comment field for the service in each cell.
}
}
$col = $col + 3
clear-Variable guestwmi
}

$WorkBook = $Sheet.UsedRange
$WorkBook.EntireRow.AutoFit()
$WorkBook.EntireColumn.AutoFit()