Thursday, August 15, 2013

First Script - Computer Hardware Inventory Script that helps with SQL Licensing

Here is my first Script!
It is based on PowerShell.

It queries each computer from a text file (one computer line by line) and gathers some hardware information like number of CPUs, physical memory, model etc and logs it to a file. The script will also search for SQL instances and will gather the details on each SQL instance setup on the system as well.

This might come in handy during a licensing true-up...

<#
Title: GetHardwareInfo-forLicensing.ps1
Description: Gathers OS, CPU, Memory and SQL Information from remote systems
Comments: None
Author: Daniel Sarfati
Original Date: August 15, 2013
Modified Date: 
Version: 1.4
#>
Add-type -AssemblyName "System.Windows.Forms"
$HKLM = [UInt32] "0x80000002"
#Custom Ping function which returns 0 if ping fails, 1 if ping passes
Function Ping($computername)
{
 $query = "select * from win32_pingstatus where address = '"   $computername   "'"
 $wmi = get-wmiobject -query $query
 if ($($wmi.statuscode) -eq $null)
  {
  $rtnvalue = $($wmi.PrimaryAddressResolutionStatus)
  }
 else {$rtnvalue = $($wmi.statuscode)}
 if ( $rtnvalue -eq 0 ) {$true}
 else {$false}
 
}
#Custom WMI Test function, just in case ping is working but WMI is down, PS shouldn't throw an error
Function WMIConnectionTest($computername)
{
 $wmiClass = "Win32_OperatingSystem"
 if ((Get-WmiObject -ComputerName $computerName win32_operatingsystem -ErrorAction silentlycontinue)) 
  { return $true } 
 else { return $false } 
}

#Main Code of the program
Function Get-HardwareDetails($ComputerName)
{
 #Create a WMI Connection to the destination computer's Win32_OperatingSystem namespace
 $OSWMI = Get-WmiObject -ComputerName $ComputerName win32_operatingsystem
 #Get some OS Information
 $OperatingSystem = $OSWMI.Caption
 $ServicePack = $OSWMI.ServicePackMajorVersion
 #Close WMI Win32_OperatingSystem connection
 $OSWMI = $null
 #Create a WMI connection to the destination computer's Win32_Processor namespace
 $ProcWMI = Get-WmiObject -ComputerName $ComputerName Win32_Processor
 #Get some Processor information, including CPU architecture x86/x64, number of cores, number of procs, etc
 $Architecture = @($ProcWMI.AddressWidth)[0]
 $CPUDescription = @($ProcWMI.Name)[0]
 $Cores = @($ProcWMI.NumberOfCores)[0]
 $ProcessorCount = @($ProcWMI.NumberOfLogicalProcessors).count
 #Close WMI Win32_OperatingSystem connection
 $ProcWMI = $null
 #Create a WMI Connection to the destination computer's Win32_OperatingSystem namespace
 $ComputerWMI = Get-WmiObject -ComputerName $ComputerName Win32_ComputerSystem
 #Get some memory and computer model information
 $TotalMemory = $ComputerWMI.TotalPhysicalMemory
 $Manufacturer = $ComputerWMI.Manufacturer
 $Model = $ComputerWMI.Model
 $ComputerWMI = $null
 #$ComputerIPs = @(([System.Net.Dns]::GetHostAddresses($ComputerName)))
 #This only works with Windows 2003 and higher
 #$SQLInstances = @(Get-WmiObject -ComputerName $computername -query "select * from win32_service where Name LIKE 'MSSQL%' and Description LIKE '%transaction%'").Count
 #Get a list of all services, for Windows 2000 Compatibility, WQL doesn't have the like operand
 $AllServices = Get-WmiObject -ComputerName $computername -query "select * from win32_service"
 #Filter for SQL Transaction service instances
 $SQLInstances = @($AllServices | where-object {$_.name -like "*MSSQL*" -and $_.description -like "*transaction*"}).count 
 #if any SQL Transaction services exists
 if ($SQLInstances -gt 0)
 {
  #Create an array of SQL service instances to investigate
  $SQLRoot = @($AllServices | where-object {$_.name -like "*MSSQL*" -and $_.description -like "*transaction*"}) | Select-Object pathname
  foreach ($SQL in $SQLRoot)
  {
   $binPath=$SQL.pathname.ToString()
   #Get the path of the binn folder from the service path, replace the : with $ and remove the quotes from the path string
   $LocalSqlInstPath=$binPath.Substring(0,$binPath.IndexOf("Binn")) -replace ":", "$" -replace "`"","" #"
   #Build the folder path, as we will connect to the remote server through UNC
   $sqlInstPath = '\\'   $ComputerName  '\'   $LocalSqlInstPath
   #Get the information and save it to the array
   $thisInstance = GetSQLInformation $sqlInstPath
   $Script:AllSQLInstances =@($thisInstance)
  }
 }
 #Close the services query
 $AllServices = $null
 #Build the object we will send back for easier CSV exports and return it
 $CompOSObj = New-Object PSObject
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name ComputerName -Value $ComputerName
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name Connection -Value $true
 #Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name ComputerIP -Value $ComputerIP
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name OperatingSystem -Value $OperatingSystem
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name ServicePack -Value $ServicePack
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name Architecture -Value $Architecture
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name CPUDescription -Value $CPUDescription
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name NumberOfCores -Value $Cores
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name NumberOfProcessors -Value $ProcessorCount
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name TotalMemory -Value $TotalMemory
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name ComputerManufacturer -Value $Manufacturer
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name ComputerModel -Value $Model
 Add-Member -InputObject $CompOSObj -MemberType NoteProperty -Name SQLInstances -Value $SQLInstances
 Return $CompOSObj
}

Function GetSQLInformation($sqlInstPath)
{
 #Build the sql log path
 $SqlLog=  $sqlInstPath   'Log\Errorlog'
 #Open the Errorlog file, and find the Edition string
 $SqlLogFile = get-content $sqllog
 $Edition = ($SqlLogFile | select-string Edition).ToString()
 $Edition = $Edition.Trim()
 $Version = $SqlLogFile[0].ToString()
 #With the Errorlog file open, and find Microsoft string, this will tell us what SQL version it is
 $SQLVersion = $Version.Substring($Version.IndexOF("Microsoft"))
 #Build the object we will send back for easier CSV exports and return it
 $SQLInstanceObj = New-Object PSObject
 Add-Member -InputObject $SQLInstanceObj -MemberType NoteProperty -Name ComputerName -Value $ComputerName
 Add-Member -InputObject $SQLInstanceObj -MemberType NoteProperty -Name SQLEdition -Value $Edition
 Add-Member -InputObject $SQLInstanceObj -MemberType NoteProperty -Name SQLVersion -Value $SQLVersion
 $SqlLogFile=$null
 Return $SQLInstanceObj
}

#Open a file dialog box
$fd = new-object System.Windows.Forms.OpenFileDialog
$fd.title = %u201CSelect Input File%u201D
$fd.Filter = %u201CText Files (*.txt) | *.txt%u201D
$fd.ShowHelp = $true
$fd.ShowDialog()

#$InputFile = Read-Host -Prompt "Please enter the name of the file you'd like to scan for" -
$ComputerList = Get-Content -Path $fd.FileName
forEach ($ComputerName in $ComputerList)
{
 #If the system is pingable and passes WMI tests, connect to it run the main function in the program, save that output to array a
 if (Ping($ComputerName) -eq $true -and if (WMIConnectionTest($ComputerName) -eq $true))
 {
  $a =@(Get-HardwareDetails $ComputerName)
 }
 #if the system can't connect, build an object and save it to array a
 Else
 {
  $CantConnectObj = New-Object PSObject 
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name ComputerName -Value $ComputerName
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name Connection -Value $false
  #Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name ComputerIP -Value $ComputerIP
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name OperatingSystem -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name ServicePack -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name Architecture -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name CPUDescription -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name NumberOfCores -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name NumberOfProcessors -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name TotalMemory -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name ComputerManufacturer -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name ComputerModel -Value $false
  Add-Member -InputObject $CantConnectObj -MemberType NoteProperty -Name SQLInstances -Value $false
  $a =@($CantConnectObj)
 }
}

$a | Export-Csv -Path ".\Export-List-HardwareDetails.csv" -notypeinformation
$Script:AllSQLInstances | Export-Csv -Path ".\Export-List-SQLInstanceDeatils.csv" -notypeinformation

No comments:

Post a Comment