├── GenerateDatabase.sql ├── logging └── Logging_Functions.ps1 ├── .gitattributes ├── .gitignore └── Get-ServerInventorySQL.ps1 /GenerateDatabase.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giMini/Get-ServerInventorySQL/HEAD/GenerateDatabase.sql -------------------------------------------------------------------------------- /logging/Logging_Functions.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giMini/Get-ServerInventorySQL/HEAD/logging/Logging_Functions.ps1 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Get-ServerInventorySQL.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | #requires -version 4 3 | 4 | .SYNOPSIS 5 | Name : Server Inventory (Get-ServerInventorySQL.ps1) 6 | Description : Get informations from remote servers with WMI and ouput in an SQL Database 7 | 8 | Author : Pierre-Alexandre Braeken 9 | 10 | * Select list of servers from a CSV file with an OpenFileDialog 11 | * Get remotely Servers informations with WMI and Powershell : 12 | * General (Domain, role in the domain, hardware manufacturer, type and model, cpu number, memory capacity, operating system and sp level) 13 | * System (BIOS name, BIOS version, hardware serial number, time zone, WMI version, virtual memory file location, virtual memory current usage, virtual memory peak usage and virtual memory allocated) 14 | * Processor (Processor(s), processor type, family, speed in Mhz, cache size in GB and socket number) 15 | * Memory (Bank number, label, capacity in GB, form and type) 16 | * Disk (Disk type, letter, capacity in GB, free space in GB + display a chart Excel) 17 | * Network (Network card, DHCP enable or not, Ip address, subnet mask, default gateway, Dns servers, Dns registered or not, primary and secondary wins and wins lookup or not) 18 | * Installed Programs (Display name, version, install location and publisher) 19 | * Share swith NTFS rights (Share name, user account, rights, ace flags and ace type) 20 | * Services (Display name, name, start by, start mode and path name) 21 | * Scheduled Tasks (Name, last run time, next run time and run as) 22 | * Printers (Locationm, name, printer state and status, share name and system name) 23 | * Process (Name, Path and sessionID) 24 | * Local Users (Groups, users) 25 | * ODBC Configured (dsn, Server, Port, DatabaseFile, DatabaseName, UID, PWD, Start, LastUser, Database, DefaultLibraries, DefaultPackage, DefaultPkgLibrary, System, Driver, Description) 26 | * ODBC Drivers Installed (Driver, DriverODBCVer, FileExtns, Setup) 27 | * Operating System Privileges (Strategy, SecurityParameters) 28 | * MB to GB conversion 29 | * Display of the progress of the script 30 | 31 | .INPUT 32 | .csv file with servers to activate 33 | 34 | .OUTPUTS 35 | Console outputs : server ok or not ok 36 | Log file 37 | 38 | .NOTES 39 | Version: 1.1 40 | Author: Pierre-Alexandre Braeken 41 | 42 | .EXAMPLE 43 | .\Get-ServerInventorySQL.ps1 44 | #> 45 | 46 | #---------------------------------------------------------[Initialisations]-------------------------------------------------------- 47 | 48 | #Set Error Action to Silently Continue 49 | $ErrorActionPreference = "SilentlyContinue" 50 | 51 | $scriptPath = split-path -parent $myInvocation.MyCommand.Definition 52 | $loggingFunctions = "$scriptPath\logging\Logging_Functions.ps1" 53 | . $loggingFunctions 54 | 55 | $tc = [System.Management.ManagementDateTimeconverter] 56 | 57 | $start =$tc::ToDmtfDateTime((Get-Date).AddDays(-1).Date) 58 | 59 | #----------------------------------------------------------[Declarations]---------------------------------------------------------- 60 | 61 | #Script version will be write in the log file 62 | $sScriptName = "Get-ServerInventorySQL" 63 | $sScriptVersion = "1.0" 64 | 65 | #Log File Info 66 | $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 67 | 68 | $launchDate = get-date -f "yyyyMMdd" 69 | $sLogPath = $scriptPath + "\" + $launchDate 70 | $logDate = get-date -f "yyyyMMddHHmm" 71 | 72 | if(!(Test-Path $sLogPath)) { 73 | New-Item $sLogPath -type directory 74 | } 75 | 76 | $sLogName = $sScriptName + $logDate + ".log" 77 | $sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName 78 | 79 | $returnValue = "" 80 | 81 | #-----------------------------------------------------------[Functions]------------------------------------------------------------ 82 | 83 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 84 | # Function Name 'Connect-Database' - connect to a SQL database 85 | # ________________________________________________________________________ 86 | Function Connect-Database($connString){ 87 | $sqlConnection = new-object System.Data.SqlClient.SqlConnection 88 | $sqlConnection.ConnectionString = $connString 89 | return $sqlConnection 90 | } 91 | 92 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 93 | # Function Name 'Count-Record' - count number of record about a query 94 | # ________________________________________________________________________ 95 | Function Count-Record($query) { 96 | $queryText = $query 97 | $sqlCommand = $sqlConnection.CreateCommand() 98 | $sqlCommand.CommandText = $QueryText 99 | $dataAdapter = new-object System.Data.SqlClient.SqlDataAdapter $sqlCommand 100 | $dataset = new-object System.Data.Dataset 101 | $dataAdapter.Fill($dataset) | Out-Null 102 | $nbRecord = ($dataset.Tables[0].recordCount) 103 | return $nbRecord 104 | } 105 | 106 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 107 | # Function Name 'Count-Record' - count number of record about a query 108 | # ________________________________________________________________________ 109 | Function Select-FromDatabase($query) { 110 | $queryText = $query 111 | $sqlCommand = $sqlConnection.CreateCommand() 112 | $sqlCommand.CommandText = $QueryText 113 | $dataAdapter = new-object System.Data.SqlClient.SqlDataAdapter $sqlCommand 114 | $dataset = new-object System.Data.Dataset 115 | $dataAdapter.Fill($dataset) | Out-Null 116 | $record = ($dataset.Tables[0]) 117 | return $record 118 | } 119 | 120 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 121 | # Function Name 'Insert-IntoDatabase' - insert record in a SQL table 122 | # ________________________________________________________________________ 123 | Function Insert-IntoDatabase($sqlCommand, $query){ 124 | $sqlCommand.CommandText = $query 125 | try{ 126 | $sqlCommand.executenonquery() | Out-Null 127 | } 128 | catch { 129 | $_.Exception 130 | } 131 | } 132 | 133 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 134 | # Function Name 'Clean-CharacterChain' remove spaces, quotes and accents 135 | # from a string 136 | # ________________________________________________________________________ 137 | Function Clean-CharacterChain { 138 | param ([String]$src = [String]::Empty) 139 | $normalized = $src.Normalize( [Text.NormalizationForm]::FormD ) 140 | $normalized = $normalized.replace(" ","") 141 | $normalized = $normalized.replace("'","") 142 | $sb = new-object Text.StringBuilder 143 | $normalized.ToCharArray() | % { 144 | if( [Globalization.CharUnicodeInfo]::GetUnicodeCategory($_) -ne [Globalization.UnicodeCategory]::NonSpacingMark) { 145 | [void]$sb.Append($_) 146 | } 147 | } 148 | 149 | return $sb.ToString() 150 | } 151 | 152 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 153 | # Function Name 'Read-OpenFileDialog' - Open an open File Dialog box 154 | # ________________________________________________________________________ 155 | Function Read-OpenFileDialog([string]$InitialDirectory, [switch]$AllowMultiSelect) { 156 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 157 | $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog 158 | $openFileDialog.ShowHelp = $True # http://www.sapien.com/blog/2009/02/26/primalforms-file-dialog-hangs-on-windows-vista-sp1-with-net-30-35/ 159 | $openFileDialog.initialDirectory = $initialDirectory 160 | $openFileDialog.filter = "csv files (*.csv)|*.csv|All files (*.*)| *.*" 161 | $openFileDialog.FilterIndex = 1 162 | $openFileDialog.ShowDialog() | Out-Null 163 | return $openFileDialog.filename 164 | } 165 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 166 | # Function Name 'Translate-AccessMask' - Translate integer value in string 167 | # ________________________________________________________________________ 168 | Function Translate-AccessMask($val) { 169 | Switch ($val) 170 | { 171 | 2032127 {"FullControl"; break} 172 | 1179785 {"Read"; break} 173 | 1180063 {"Read, Write"; break} 174 | 1179817 {"ReadAndExecute"; break} 175 | -1610612736 {"ReadAndExecuteExtended"; break} 176 | 1245631 {"ReadAndExecute, Modify, Write"; break} 177 | 1180095 {"ReadAndExecute, Write"; break} 178 | 268435456 {"FullControl (Sub Only)"; break} 179 | default {$AccessMask = $val; break} 180 | } 181 | } 182 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 183 | # Function Name 'Translate-AceType' - Translate integer value in string 184 | # ________________________________________________________________________ 185 | Function Translate-AceType($val) { 186 | Switch ($val) 187 | { 188 | 0 {"Allow"; break} 189 | 1 {"Deny"; break} 190 | 2 {"Audit"; break} 191 | } 192 | } 193 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 194 | # Function Name 'Translate-AceFlagse' - Translate integer value in string 195 | # ________________________________________________________________________ 196 | <# OBJECT_INHERIT_ACE 197 | 1 (0x1) 198 | Noncontainer child objects inherit the ACE as an effective ACE. 199 | For child objects that are containers, the ACE is inherited as an inherit-only ACE unless the NO_PROPAGATE_INHERIT_ACE bit flag is also set. 200 | CONTAINER_INHERIT_ACE 201 | 2 (0x2) 202 | Child objects that are containers, such as directories, inherit the ACE as an effective ACE. The inherited ACE is inheritable unless the NO_PROPAGATE_INHERIT_ACE bit flag is also set. 203 | NO_PROPAGATE_INHERIT_ACE 204 | 4 (0x4) 205 | If the ACE is inherited by a child object, the system clears the OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags in the inherited ACE. This prevents the ACE from being inherited by subsequent generations of objects. 206 | INHERIT_ONLY_ACE 207 | 8 (0x8) 208 | Indicates an inherit-only ACE which does not control access to the object to which it is attached. If this flag is not set, the ACE is an effective ACE which controls access to the object to which it is attached. 209 | Both effective and inherit-only ACEs can be inherited depending on the state of the other inheritance flags. 210 | INHERITED_ACE 211 | 16 (0x10) 212 | The system sets this bit when it propagates an inherited ACE to a child object. 213 | Access these the same way. You can break them out using the bitwise AND operator or just test for the totals #> 214 | Function Translate-AceFlags($val) { 215 | Switch ($val) 216 | { 217 | 0 {"0"} 218 | 1 {"Noncontainer child objects inherit"; break} 219 | 2 {"Containers will inherit and pass on"; break} 220 | 3 {"Containers AND Non-containers will inherit and pass on"; break} 221 | } 222 | } 223 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 224 | # Function Name 'Get-NtfsRights' - Enumerates NTFS rights of a folder 225 | # ________________________________________________________________________ 226 | Function Get-NtfsRights($name,$path,$comp) { 227 | $path = [regex]::Escape($path) 228 | $share = "\\$comp\\$name" 229 | $wmi = gwmi Win32_LogicalFileSecuritySetting -filter "path='$path'" -ComputerName $comp 230 | $wmi.GetSecurityDescriptor().Descriptor.DACL | where {$_.AccessMask -as [Security.AccessControl.FileSystemRights]} |select ` 231 | @{name="ShareName";Expression={$share}}, 232 | @{name="Principal";Expression={"{0}\{1}" -f $_.Trustee.Domain,$_.Trustee.name}}, 233 | @{name="Rights";Expression={Translate-AccessMask $_.AccessMask }}, 234 | @{name="AceFlags";Expression={Translate-AceFlags $_.AceFlags }}, 235 | @{name="AceType";Expression={Translate-AceType $_.AceType }} 236 | 237 | } 238 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 239 | # Function Name 'listProgramsInstalled' - get info in registry 240 | # ________________________________________________________________________ 241 | Function listProgramsInstalled { 242 | Param( 243 | [string]$UninstallKey, 244 | [string]$ComputerName 245 | ) 246 | $array = @() 247 | 248 | $remoteBaseKeyObject = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername) 249 | if($remoteBaseKeyObject) { 250 | $remoteBaseKey = $remoteBaseKeyObject.OpenSubKey($uninstallKey) 251 | if($remoteBaseKey) { 252 | $subKeys = $remoteBaseKey.GetSubKeyNames() 253 | foreach($key in $subKeys){ 254 | $thisKey=$UninstallKey+"\\"+$key 255 | $thisSubKey=$remoteBaseKeyObject.OpenSubKey($thisKey) 256 | $psObject = New-Object PSObject 257 | $psObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($thisSubKey.GetValue("DisplayName")) 258 | $psObject | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion")) 259 | $psObject | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value $($thisSubKey.GetValue("InstallLocation")) 260 | $psObject | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($thisSubKey.GetValue("Publisher")) 261 | $array += $psObject 262 | } 263 | } 264 | } 265 | $array 266 | } 267 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 268 | # Function Name 'List-ProgramsInstalled' - get info by WMI request 269 | # ________________________________________________________________________ 270 | Function List-ProgramsInstalled { 271 | Param( 272 | [string]$UninstallKey, 273 | [string]$ComputerName, 274 | $Credential 275 | ) 276 | $array = @() 277 | 278 | $wmi = Get-WmiObject -List "StdRegProv" -Namespace root\default -ComputerName $ComputerName -Credential $Credential 279 | 280 | $subkeys = $wmi.EnumKey(2147483650,$UninstallKey) 281 | if($subkeys) { 282 | $remoteSubkeysNames = $subkeys.sNames 283 | foreach($key in $remoteSubkeysNames){ 284 | $thisSubKey=$UninstallKey+"\"+$key 285 | $psObject = New-Object PSObject 286 | $psObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $(($wmi.GetStringValue(2147483650,$thisSubKey,"DisplayName")).sValue) 287 | $psObject | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $(($wmi.GetStringValue(2147483650,$thisSubKey,"DisplayVersion")).sValue) 288 | $psObject | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value $(($wmi.GetStringValue(2147483650,$thisSubKey,"InstallLocation")).sValue) 289 | $psObject | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $(($wmi.GetStringValue(2147483650,$thisSubKey,"Publisher")).sValue) 290 | $psObject | Add-Member -MemberType NoteProperty -Name "DisplayIcon" -Value $(($wmi.GetStringValue(2147483650,$thisSubKey,"DisplayIcon")).sValue) 291 | $array += $psObject 292 | } 293 | } 294 | 295 | $array 296 | } 297 | 298 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 299 | # Function Name 'getTasks' - get scheduled tasks on remote server 300 | # ________________________________________________________________________ 301 | Function getTasks($path) { 302 | $out = @() 303 | # Get root tasks 304 | $schedule.GetFolder($path).GetTasks(0) | % { 305 | $xml = [xml]$_.xml 306 | $out += New-Object psobject -Property @{ 307 | "Name" = $_.Name 308 | "Path" = $_.Path 309 | "LastRunTime" = $_.LastRunTime 310 | "NextRunTime" = $_.NextRunTime 311 | "Actions" = ($xml.Task.Actions.Exec | % { "$($_.Command) $($_.Arguments)" }) -join "`n" 312 | "RunAs" = ($xml.Task.Principals.principal.userID) 313 | } 314 | } 315 | # Get tasks from subfolders 316 | $schedule.GetFolder($path).GetFolders(0) | % { 317 | $out += getTasks($_.Path) 318 | } 319 | $out 320 | } 321 | <# 322 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 323 | # Function Name 'getLocalUsersInGroup' - get local users in groups 324 | # ________________________________________________________________________ 325 | function getLocalUsersInGroup { 326 | if($saveIntDomainRole -le 3) { 327 | $serverADSIObject = [ADSI]"WinNT://$strComputer,computer" 328 | $localUserinGroups=@() 329 | $serverADSIObject.psbase.children | Where { $_.psbase.schemaClassName -eq 'group' } |` 330 | foreach { 331 | $group =[ADSI]$_.psbase.Path 332 | $group.psbase.Invoke("Members") | ` 333 | foreach {$localUserinGroups += New-Object psobject -property @{Group = $group.Name;User=(($_.GetType().InvokeMember("Adspath", 'GetProperty', $null, $_, $null)) -replace "WinNT://","")}} 334 | } 335 | } 336 | else { 337 | $localUserinGroups = @() 338 | } 339 | $localUserinGroups 340 | } 341 | #> 342 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 343 | # Function Name 'getLocalUsersInGroup' - get local users in groups 344 | # ________________________________________________________________________ 345 | function getLocalUsersInGroup { 346 | Param( 347 | [string]$ComputerName, 348 | $Credential 349 | ) 350 | if($saveIntDomainRole -le 3) { 351 | $user = $Credential.UserName 352 | $pass = $($Credential.GetNetworkCredential().password) 353 | 354 | # Create an ADSI Search 355 | $serverADSIObject = New-Object System.DirectoryServices.DirectoryEntry("WinNT://$ComputerName",$user,$pass) 356 | # Limit the output to 50 objects 357 | $serverADSIObject.SizeLimit = '50' 358 | 359 | # Add the Domain to the search 360 | # $serverADSIObject.SearchRoot = $DomainEntry 361 | 362 | # Execute the Search 363 | $serverADSIObject.FindAll() 364 | 365 | $serverADSIObject = [ADSI]"WinNT://$ComputerName,computer" 366 | $localUserinGroups=@() 367 | $serverADSIObject.psbase.children | Where { $_.psbase.schemaClassName -eq 'group' } |` 368 | foreach { 369 | $group =[ADSI]$_.psbase.Path 370 | $group.psbase.Invoke("Members") | ` 371 | foreach {$localUserinGroups += New-Object psobject -property @{Group = $group.Name;User=(($_.GetType().InvokeMember("Adspath", 'GetProperty', $null, $_, $null)) -replace "WinNT://","")}} 372 | } 373 | } 374 | else { 375 | $localUserinGroups = @() 376 | } 377 | $localUserinGroups 378 | } 379 | 380 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 381 | # Function Name 'listODBCConfigured' - get ODBC connections configured 382 | # ________________________________________________________________________ 383 | Function listODBCConfigured ($odbcConfigured) { 384 | $computername = $strComputer 385 | $arrayConfigured = @() 386 | $remoteBaseKeyObject = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername) 387 | $remoteBaseKey = $remoteBaseKeyObject.OpenSubKey($odbcConfigured) 388 | $subKeys = $remoteBaseKey.GetSubKeyNames() 389 | foreach($key in $subKeys){ 390 | $thisKey=$odbcConfigured+"\\"+$key 391 | $thisSubKey=$remoteBaseKeyObject.OpenSubKey($thisKey) 392 | $psObjectConfigured = New-Object PSObject 393 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername 394 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DSN" -Value $($thisSubKey.GetValue("dsn")) 395 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Server" -Value $($thisSubKey.GetValue("Server")) 396 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Port" -Value $($thisSubKey.GetValue("Port")) 397 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DatabaseFile" -Value $($thisSubKey.GetValue("DatabaseFile")) 398 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DatabaseName" -Value $($thisSubKey.GetValue("DatabaseName")) 399 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "UID" -Value $($thisSubKey.GetValue("UID")) 400 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "PWD" -Value $($thisSubKey.GetValue("PWD")) 401 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Start" -Value $($thisSubKey.GetValue("Start")) 402 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "LastUser" -Value $($thisSubKey.GetValue("LastUser")) 403 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Database" -Value $($thisSubKey.GetValue("Database")) 404 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DefaultLibraries" -Value $($thisSubKey.GetValue("DefaultLibraries")) 405 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DefaultPackage" -Value $($thisSubKey.GetValue("DefaultPackage")) 406 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "DefaultPkgLibrary" -Value $($thisSubKey.GetValue("DefaultPkgLibrary")) 407 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "System" -Value $($thisSubKey.GetValue("System")) 408 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Driver" -Value $($thisSubKey.GetValue("Driver")) 409 | $psObjectConfigured | Add-Member -MemberType NoteProperty -Name "Description" -Value $($thisSubKey.GetValue("Description")) 410 | $arrayConfigured += $psObjectConfigured 411 | } 412 | $arrayConfigured 413 | } 414 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 415 | # Function Name 'listODBCInstalled' - get ODBC connections installed 416 | # ________________________________________________________________________ 417 | Function listODBCInstalled ($odbcDriversInstalled) { 418 | $computername = $strComputer 419 | $arrayInstalled = @() 420 | $remoteBaseKeyObject = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername) 421 | $remoteBaseKey = $remoteBaseKeyObject.OpenSubKey($odbcDriversInstalled) 422 | $subKeys = $remoteBaseKey.GetSubKeyNames() 423 | foreach($key in $subKeys){ 424 | $thisKey=$odbcDriversInstalled+"\\"+$key 425 | $thisSubKey=$remoteBaseKeyObject.OpenSubKey($thisKey) 426 | $psObjectInstalled = New-Object PSObject 427 | $psObjectInstalled | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername 428 | $psObjectInstalled | Add-Member -MemberType NoteProperty -Name "Driver" -Value $($thisSubKey.GetValue("Driver")) 429 | $psObjectInstalled | Add-Member -MemberType NoteProperty -Name "DriverODBCVer" -Value $($thisSubKey.GetValue("DriverODBCVer")) 430 | $psObjectInstalled | Add-Member -MemberType NoteProperty -Name "FileExtns" -Value $($thisSubKey.GetValue("FileExtns")) 431 | $psObjectInstalled | Add-Member -MemberType NoteProperty -Name "Setup" -Value $($thisSubKey.GetValue("Setup")) 432 | $arrayInstalled += $psObjectInstalled 433 | } 434 | $arrayInstalled 435 | } 436 | 437 | # ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 438 | # Function Name 'ListFile' - get server based on a CSV file 439 | # ________________________________________________________________________ 440 | Function ListFile { 441 | $fileOpen = Read-OpenFileDialog 442 | if($fileOpen -ne '') { 443 | $colComputers = Import-Csv $fileOpen 444 | } 445 | $colComputers 446 | } 447 | # Run-WmiRemoteProcess 448 | Function Run-WmiRemoteProcess 449 | { 450 | Param( 451 | [string]$ComputerName=$env:COMPUTERNAME, 452 | [string]$Cmd=$(Throw "You must enter the full path to the command which will create the process."), 453 | [int]$TimeOut = 0 454 | ) 455 | 456 | Write-Host "Process to create on $computername is $cmd" 457 | [wmiclass]$wmi="\\$computername\root\cimv2:win32_process" 458 | # Exit if the object didn't get created 459 | if (!$wmi) {return} 460 | 461 | try{ 462 | $remote=$wmi.Create($cmd) 463 | } 464 | catch{ 465 | $_.Exception 466 | } 467 | $test =$remote.returnvalue 468 | if ($remote.returnvalue -eq 0) { 469 | Write-Host ("Successfully launched $cmd on $computername with a process id of " + $remote.processid) 470 | } else { 471 | Write-Host ("Failed to launch $cmd on $computername. ReturnValue is " + $remote.ReturnValue) 472 | } 473 | 474 | # Wait for the process to complete or to reach timeout 475 | $processId = $remote.processid 476 | $processActive = 1 477 | while ( $processActive -ge 1) { 478 | $process = Get-Wmiobject -class win32_process ` 479 | -namespace "rootcimv2" -computerName $computername -Filter "ProcessId = $processId" 480 | if ($process -ne $null) { 481 | if ($processActive -ge $timeout -and $timeout -ne 0){ 482 | Write-Host "Remote process execution is taking too long and timed out" 483 | return 484 | } 485 | $processActive++ 486 | Start-Sleep -Seconds 1 487 | } else { 488 | Write-Host "Remote process finished" 489 | $processActive = 0 490 | } 491 | } 492 | } 493 | 494 | function Get-NameFromSid 495 | { 496 | Param ( 497 | [String]$currentSid 498 | ) 499 | 500 | $objSID = $null 501 | $objUser = $null 502 | 503 | try { 504 | $sid = $currentSid.Replace("`*","") 505 | $objSID = New-Object System.Security.Principal.SecurityIdentifier ($sid) 506 | $objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) 507 | Write-Host "SID $sid translated to $objUser.Value" 508 | return $objUser.Value 509 | } catch { 510 | Write-Host "SID $sid could not be translated" 511 | return $currentSid 512 | } 513 | } 514 | 515 | # to find the index of an element in an array 516 | function Get-IndexOf { 517 | Param ( 518 | [object[]]$array, $element 519 | ) 520 | 521 | $line = 0..($array.length - 1) | where {$array[$_] -eq $element} 522 | return $line 523 | } 524 | 525 | # Parse the text file from the secdump and outputs an array of policies 526 | function Parse-SecdumpFileToObject { 527 | Param ( 528 | [String]$file 529 | ) 530 | 531 | # The array that will be returned 532 | $policies = @() 533 | 534 | # put the text file to an array 535 | $fileContent = Get-Content $file 536 | 537 | # Find the delimitations of the security policies 538 | $start = IndexOf $fileContent "[Privilege Rights]" 539 | $end = IndexOf $fileContent "[Version]" 540 | 541 | # Extract the security policies between those delimitations 542 | For ($i = $start+1; $i -lt $end; $i++) { 543 | $policy = New-Object Object 544 | $line = $fileContent[$i].split(" =") 545 | 546 | # Add policy name to the policy 547 | Add-Member -memberType NoteProperty -name name -value $line[0] -inputObject $policy 548 | # Extract array of members, translate the SIDs, and add the members array to the policy 549 | $members = $line[3].split(",") 550 | For ($j = 0; $j -lt $members.Count; $j++) { 551 | if ($members[$j] -like "``**") { 552 | $members[$j] = Get-NameFromSid $members[$j] 553 | } 554 | } 555 | Add-Member -memberType NoteProperty -name members -value $members -inputObject $policy 556 | 557 | # Add the policy to the "policies" array 558 | $policies += $policy 559 | } 560 | return $policies 561 | } 562 | #-----------------------------------------------------------[Execution]------------------------------------------------------------ 563 | 564 | Log-Start -LogPath $sLogPath -LogName $sLogName -ScriptName $sScriptName -ScriptVersion $sScriptVersion 565 | 566 | $ServerName = '' 567 | $UserName = 'domain\user' 568 | $Credential = Get-Credential -Credential $UserName 569 | 570 | # open database connection 571 | 572 | $connString = "Data Source=DC01\SQLEXPRESS; Initial Catalog=PowerShellServerInventory; Integrated Security=True" 573 | $sqlConnection = Connect-Database $connString 574 | Log-Write -LogPath $sLogFile -LineValue "Database connection to $connString" 575 | $sqlConnection.Open() 576 | $sqlCommand = $sqlConnection.CreateCommand() 577 | Log-Write -LogPath $sLogFile -LineValue "SqlCommand objec created" 578 | $colComputers = ListFile 579 | $computerCount = $colComputers.Count 580 | Log-Write -LogPath $sLogFile -LineValue "List of $computerCount computers to query collected" #`n" 581 | 582 | $serversNotResponding = "" 583 | $nbError = 0 584 | $nbSuccess = 0 585 | $nbTot = $computerCount 586 | 587 | foreach ($strComputer in $colComputers){ 588 | $items = "" 589 | $queryText = "Select count(*) as recordCount FROM ServerAudited" 590 | $nbServer = Count-Record($queryText) 591 | $strComputer = $strComputer.ServerName 592 | $serverName = $strComputer 593 | Write-Progress -Activity "Getting general information ($strComputer)" -status "Running..." -id 1 594 | $items = gwmi Win32_ComputerSystem -Comp $strComputer -Credential $Credential | Select-Object Domain, DomainRole, Manufacturer, Model, SystemType, NumberOfProcessors, TotalPhysicalMemory 595 | if($items) { 596 | $domain = $items.Domain 597 | $domainRole = $items.DomainRole 598 | $manufacturer = $items.Manufacturer 599 | $model = $items.Model 600 | $systemType = $items.SystemType 601 | $numberOfProcessors = $items.NumberOfProcessors 602 | $totalPhysicalMemory = [math]::round(($items.TotalPhysicalMemory)/1024/1024/1024, 0) 603 | Write-Progress -Activity "Getting systems information ($strComputer)" -status "Running..." -id 1 604 | $items = "" 605 | $items = gwmi Win32_OperatingSystem -Comp $strComputer -Credential $Credential | Select-Object Caption, csdversion 606 | $operatingSystem = $items.Caption 607 | $servicePackLevel = $items.csdversion 608 | $items = "" 609 | $items = gwmi Win32_BIOS -Comp $strComputer -Credential $Credential | Select-Object Name, SMBIOSbiosVersion, SerialNumber 610 | $biosName = $items.Name 611 | $biosVersion = $items.SMBIOSbiosVersion 612 | $hardwareSerial = $items.SerialNumber 613 | $items = "" 614 | $items = gwmi Win32_TimeZone -Comp $strComputer -Credential $Credential | Select-Object Caption 615 | $timeZone = $items.Caption 616 | $items = "" 617 | $items = gwmi Win32_WmiSetting -Comp $strComputer -Credential $Credential | Select-Object BuildVersion 618 | $wmiVersion = $items.BuildVersion 619 | $items = "" 620 | $items = gwmi Win32_PageFileUsage -Comp $strComputer -Credential $Credential | Select-Object Name, CurrentUsage, PeakUsage, AllocatedBaseSize 621 | $virtualMemoryName = $items.Name 622 | $virtualMemoryCurrentUsage = $items.CurrentUsage 623 | $virtualMermoryPeakUsage = $items.PeakUsage 624 | $virtualMemoryAllocatedBaseSize = $items.AllocatedBaseSize 625 | 626 | $saveIntDomainRole = $domainRole 627 | 628 | Switch($domainRole) { 629 | 0{$domainRole = "Stand Alone Workstation"} 630 | 1{$domainRole = "Member Workstation"} 631 | 2{$domainRole = "Stand Alone Server"} 632 | 3{$domainRole = "Member Server"} 633 | 4{$domainRole = "Back-up Domain Controller"} 634 | 5{$domainRole = "Primary Domain Controller"} 635 | default{"Undetermined"} 636 | } 637 | 638 | $serverQueryInsert = "INSERT INTO ServerAudited (serverID,serverName,domain,role,HW_Make,HW_Model,HW_Type,cpuCount,memoryGB,operatingSystem,servicePackLevel, 639 | biosName,biosVersion,hardwareSerial,timeZone,wmiVersion,virtualMemoryName,virtualMemoryCurrentUsage,virtualMermoryPeakUsage, 640 | virtualMemoryAllocatedBaseSize) VALUES('$nbServer','$serverName','$domain','$domainRole','$manufacturer','$model','$systemType','$numberOfProcessors', 641 | '$totalPhysicalMemory','$operatingSystem','$servicePackLevel','$biosName','$biosVersion','$hardwareSerial','$timeZone','$wmiVersion','$virtualMemoryName', 642 | '$virtualMemoryCurrentUsage','$virtualMermoryPeakUsage','$virtualMemoryAllocatedBaseSize')" 643 | Write-Progress -Activity "Inserting server information ($strComputer)" -status "Running..." -id 1 644 | Insert-IntoDatabase $sqlCommand $serverQueryInsert 645 | Log-Write -LogPath $sLogFile -LineValue "$serverQueryInsert" 646 | 647 | Write-Progress -Activity "Getting processor information ($strComputer)" -status "Running..." -id 1 648 | $items = "" 649 | $items = gwmi Win32_Processor -Comp $strComputer -Credential $Credential | Select-Object DeviceID, Name, Description, family, currentClockSpeed, l2cacheSize, UpgradeMethod, SocketDesignation 650 | Write-Progress -Activity "Inserting processor information ($strComputer)" -status "Running..." -id 1 651 | foreach($item in $items) { 652 | $deviceLocator = $item.DeviceID 653 | $processorName = $item.Name 654 | $processorDescription = $item.Description 655 | $processorFamily = $item.family 656 | $currentClockSpeed = $item.currentClockSpeed 657 | $l2cacheSize = $item.l2cacheSize 658 | $upgradeMethod = $item.UpgradeMethod 659 | $socketDesignation = $item.SocketDesignation 660 | $processorQueryInsert = "INSERT INTO ProcessorAudited (serverID,Name,TypeP,Family,Speed,CacheSize,Interface,SocketNumber) VALUES 661 | ('$nbServer','$deviceLocator','$processorName','$processorFamily','$currentClockSpeed','$l2cacheSize','$upgradeMethod','$socketDesignation')" 662 | Insert-IntoDatabase $sqlCommand $processorQueryInsert 663 | Log-Write -LogPath $sLogFile -LineValue "$processorQueryInsert" 664 | } 665 | 666 | 667 | Write-Progress -Activity "Getting memory information ($strComputer)" -status "Running..." -id 1 668 | $items = "" 669 | $items = gwmi Win32_PhysicalMemory -Comp $strComputer -Credential $Credential | Select-Object DeviceLocator, Capacity, FormFactor, TypeDetail 670 | Write-Progress -Activity "Inserting memory information ($strComputer)" -status "Running..." -id 1 671 | foreach($item in $items) { 672 | $deviceLocator = $item.DeviceLocator 673 | $capacity = [math]::round(($item.Capacity)/1024/1024/1024, 0) 674 | $formFactor = $item.FormFactor 675 | $typeDetail = $item.TypeDetail 676 | $memoryQueryInsert = "INSERT INTO MemoryAudited (serverID,Label,Capacity,Form,TypeM) VALUES ('$nbServer','$deviceLocator','$capacity','$formFactor','$typeDetail')" 677 | Insert-IntoDatabase $sqlCommand $memoryQueryInsert 678 | Log-Write -LogPath $sLogFile -LineValue "$memoryQueryInsert" 679 | } 680 | 681 | Write-Progress -Activity "Getting disks information ($strComputer)" -status "Running..." -id 1 682 | $items = "" 683 | $items = gwmi Win32_LogicalDisk -Comp $strComputer -Credential $Credential | Select-Object DriveType, DeviceID, Size, FreeSpace 684 | Write-Progress -Activity "Inserting disk information ($strComputer)" -status "Running..." -id 1 685 | foreach($item in $items) { 686 | $driveType = $item.DriveType 687 | $deviceID = $item.DeviceID 688 | $size = [math]::round(($item.Size)/1024/1024/1024, 0) 689 | $freeSpace = [math]::round(($item.FreeSpace)/1024/1024/1024, 0) 690 | 691 | Switch($driveType) { 692 | 2{$driveType = "Floppy"} 693 | 3{$driveType = "Fixed Disk"} 694 | 5{$driveType = "Removable Media"} 695 | default{"Undetermined"} 696 | } 697 | 698 | $diskQueryInsert = "INSERT INTO DriveAudited (serverID,diskType,driveLetter,capacity,freeSpace) VALUES ('$nbServer','$driveType','$deviceID','$size','$freeSpace')" 699 | Insert-IntoDatabase $sqlCommand $diskQueryInsert 700 | Log-Write -LogPath $sLogFile -LineValue "$diskQueryInsert" 701 | } 702 | 703 | Write-Progress -Activity "Getting network information ($strComputer)" -status "Running..." -id 1 704 | $items = "" 705 | $items = gwmi Win32_NetworkAdapterConfiguration -Comp $strComputer -Credential $Credential | Where{$_.IPEnabled -eq "True"} | Select-Object Caption, DHCPEnabled, IPAddress, IPSubnet, DefaultIPGateway, DNSServerSearchOrder, FullDNSRegistrationEnabled, WINSPrimaryServer, WINSSecondaryServer, WINSEnableLMHostsLookup 706 | Write-Progress -Activity "Inserting network information ($strComputer)" -status "Running..." -id 1 707 | foreach($item in $items) { 708 | $caption = $item.Caption 709 | $dhcpEnabled = $item.DHCPEnabled 710 | $ipAddress = $item.IPAddress 711 | $ipSubnet = $item.IPSubnet 712 | $defaultIPGateway = $item.DefaultIPGateway 713 | $dnsServerSearchOrder = $item.DNSServerSearchOrder 714 | $fullDNSRegistrationEnabled = $item.FullDNSRegistrationEnabled 715 | $winsPrimaryServer = $item.WINSPrimaryServer 716 | $winsSecondaryServer = $item.WINSSecondaryServer 717 | $winsEnableLMHostsLookup = $item.WINSEnableLMHostsLookup 718 | $networkQueryInsert = "INSERT INTO NetworkAudited (serverID,networkCard,dhcpEnabled,ipAddress,subnetMask,defaultGateway,dnsServers,dnsReg,primaryWins,secondaryWins,winsLookup) 719 | VALUES ('$nbServer','$caption','$dhcpEnabled','$ipAddress','$ipSubnet','$defaultIPGateway','$dnsServerSearchOrder','$fullDNSRegistrationEnabled', 720 | '$winsPrimaryServer','$winsSecondaryServer','$winsEnableLMHostsLookup')" 721 | Insert-IntoDatabase $sqlCommand $networkQueryInsert 722 | Log-Write -LogPath $sLogFile -LineValue "$networkQueryInsert" 723 | } 724 | 725 | Write-Progress -Activity "Getting programs installed information ($strComputer)" -status "Running..." -id 1 726 | # Populate Installed Programs 727 | #$arrayprogramsInstalled = listProgramsInstalled -UninstallKey "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" -ComputerName $strComputer 728 | #$arrayprogramsInstalled2 = listProgramsInstalled -Key "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" -ComputerName $strComputer 729 | 730 | $arrayprogramsInstalled = List-ProgramsInstalled -UninstallKey "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" -ComputerName $strComputer -Credential $Credential 731 | $arrayprogramsInstalled2 = List-ProgramsInstalled -UninstallKey "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" -ComputerName $strComputer -Credential $Credential 732 | 733 | $items = "" 734 | $items = $arrayprogramsInstalled + $arrayprogramsInstalled2 735 | Write-Progress -Activity "Inserting installed programs information ($strComputer)" -status "Running..." -id 1 736 | foreach($item in $items) { 737 | $displayName = $item.DisplayName 738 | $displayVersion = $item.DisplayVersion 739 | $installLocation = $item.InstallLocation 740 | $publisher = $item.Publisher 741 | $displayicon = $item.displayicon 742 | if(!([string]::IsNullOrEmpty($displayName))) { 743 | $installedProgramQueryInsert = "INSERT INTO InstalledProgramAudited (serverID,displayName,displayVersion,installLocation,publisher,displayicon) VALUES ('$nbServer','$displayName','$displayVersion','$installLocation','$publisher','$displayicon')" 744 | Insert-IntoDatabase $sqlCommand $installedProgramQueryInsert 745 | Log-Write -LogPath $sLogFile -LineValue "$installedProgramQueryInsert" 746 | } 747 | } 748 | 749 | # Populate Shares 750 | Write-Progress -Activity "Getting shares information ($strComputer)" -status "Running..." -id 1 751 | if ($shares = Get-WmiObject Win32_Share -ComputerName $strComputer -Credential $Credential) { 752 | $items = @() 753 | $shares | Foreach {$items += Get-NtfsRights $_.Name $_.Path $_.__Server} 754 | } 755 | else {$shares = "Failed to get share information from {0}." -f $($_.ToUpper())} 756 | Write-Progress -Activity "Inserting shares information ($strComputer)" -status "Running..." -id 1 757 | $shareName = "" 758 | $shareNameSave = "" 759 | foreach ($item in $items) { 760 | $shareName = $item.ShareName 761 | if($shareName -ne $shareNameSave) { 762 | $sharesQueryInsert = "INSERT INTO ShareAudited (serverID,shareName) VALUES ('$nbServer','$shareName')" 763 | Insert-IntoDatabase $sqlCommand $sharesQueryInsert 764 | $shareNameSave = $shareName 765 | Log-Write -LogPath $sLogFile -LineValue "$sharesQueryInsert" 766 | } 767 | $principal = $item.Principal 768 | $rights = $item.Rights 769 | $aceFlags = $item.AceFlags 770 | $aceType = $item.AceType 771 | 772 | $queryText = "Select shareAuditedID as shareAuditedID FROM ShareAudited WHERE shareName LIKE '$shareName'" 773 | $recordReturned = Select-FromDatabase($queryText) 774 | $shareAuditedID = $recordReturned.shareAuditedID 775 | $sharesRightsQueryInsert = "INSERT INTO ShareRightsAudited (shareAuditedID,account,rights,aceFlags,aceType) VALUES ('$shareAuditedID','$principal','$rights','$aceFlags','$aceType')" 776 | Insert-IntoDatabase $sqlCommand $sharesRightsQueryInsert 777 | Log-Write -LogPath $sLogFile -LineValue "$sharesRightsQueryInsert" 778 | } 779 | 780 | # Populate Services 781 | Write-Progress -Activity "Getting services information ($strComputer)" -status "Running..." -id 1 782 | $items = "" 783 | $items = Get-WmiObject win32_service -Comp $strComputer -Credential $Credential | Select-Object DisplayName, Name, StartName, StartMode, PathName, Description 784 | Write-Progress -Activity "Inserting services information ($strComputer)" -status "Running..." -id 1 785 | foreach ($item in $items) { 786 | $displayName = $item.DisplayName 787 | $name = $item.Name 788 | $startName = $item.StartName 789 | $startMode = $item.StartMode 790 | $pathName = $item.PathName 791 | $description = $item.Description 792 | $description = $description.replace("'","") 793 | 794 | $servicesQueryInsert = "INSERT INTO ServiceAudited (serverID,displayName,name,startName,startMode,servicePathName,serviceDescription) VALUES ('$nbServer','$displayName','$name','$startName','$startMode','$pathName','$description')" 795 | Insert-IntoDatabase $sqlCommand $servicesQueryInsert 796 | Log-Write -LogPath $sLogFile -LineValue "$servicesQueryInsert" 797 | } 798 | 799 | # Populate Scheduled Tasks 800 | Write-Progress -Activity "Getting tasks information ($strComputer)" -status "Running..." -id 1 801 | $items = @() 802 | try { $schedule = new-object -comobject "Schedule.Service" ; $schedule.Connect($strComputer) } 803 | catch [System.Management.Automation.PSArgumentException] { throw $_ } 804 | $items += getTasks("\") 805 | # Close com 806 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null 807 | Remove-Variable schedule 808 | Write-Progress -Activity "Inserting Scheduled Tasks information ($strComputer)" -status "Running..." -id 1 809 | foreach ($item in $items) { 810 | $name = $item.Name 811 | $name = $name.replace("'","") 812 | $path = $item.Path 813 | $path = $path.replace("'","") 814 | $lastRunTime = $item.LastRunTime 815 | $nextRunTime = $item.NextRunTime 816 | $actions = $item.Actions 817 | $runAs = $item.RunAs 818 | 819 | $scheduledTasksQueryInsert = "INSERT INTO ScheduledTaskAudited (serverID,name,pathName,lastRunTime,nextRunTime,scheduledAction,runAs) VALUES ('$nbServer','$name','$path','$lastRunTime','$nextRunTime','$actions','$runAs')" 820 | Insert-IntoDatabase $sqlCommand $scheduledTasksQueryInsert 821 | Log-Write -LogPath $sLogFile -LineValue "$scheduledTasksQueryInsert" 822 | } 823 | 824 | # Populate Printers 825 | Write-Progress -Activity "Getting printers information ($strComputer)" -status "Running..." -id 1 826 | $items = "" 827 | $items = gwmi Win32_Printer -Comp $strComputer -Credential $Credential | Select-Object Location, Name, PrinterState, PrinterStatus, ShareName, SystemName 828 | Write-Progress -Activity "Inserting Printers information ($strComputer)" -status "Running..." -id 1 829 | foreach ($item in $items) { 830 | $name = $item.Name 831 | $location = $item.Location 832 | $printerState = $item.PrinterState 833 | $printerStatus = $item.PrinterStatus 834 | $shareName = $item.ShareName 835 | $systemName = $item.SystemName 836 | 837 | $printerQueryInsert = "INSERT INTO PrinterAudited (serverID,name,location,printerState,printerStatus,shareName,systemName) VALUES ('$nbServer','$name','$location','$printerState','$printerStatus','$shareName','$systemName')" 838 | Insert-IntoDatabase $sqlCommand $printerQueryInsert 839 | Log-Write -LogPath $sLogFile -LineValue "$printerQueryInsert" 840 | } 841 | # Populate Process worksheet 842 | Write-Progress -Activity "Getting process information ($strComputer)" -status "Running..." -id 1 843 | $items = "" 844 | $items = gwmi win32_process -ComputerName $strComputer -Credential $Credential | select-object Name, Path, SessionId 845 | Write-Progress -Activity "Inserting Process information ($strComputer)" -status "Running..." -id 1 846 | foreach ($item in $items) { 847 | $name = $item.Name 848 | $location = $item.Location 849 | $sessionID = $item.sessionID 850 | 851 | $processQueryInsert = "INSERT INTO ProcessAudited (serverID,name,location,sessionID) VALUES ('$nbServer','$name','$location','$sessionID')" 852 | Insert-IntoDatabase $sqlCommand $processQueryInsert 853 | Log-Write -LogPath $sLogFile -LineValue "$processQueryInsert" 854 | } 855 | 856 | # Populate ODBC Configured 857 | Write-Progress -Activity "Getting ODBC connections Configured ($strComputer)" -status "Running..." -id 1 858 | if($systemType -eq "x86-based PC") { 859 | $odbcConfigured = "SOFTWARE\\odbc\\odbc.ini" 860 | $odbcDriversInstalled = "SOFTWARE\\odbc\\odbcinst.ini" 861 | } 862 | else { 863 | $odbcConfigured = "SOFTWARE\\wow6432Node\\odbc\\odbc.ini" 864 | $odbcDriversInstalled = "SOFTWARE\\wow6432Node\\odbc\\odbcinst.ini" 865 | } 866 | Write-Progress -Activity "Formating the output - ODBC connections Configured ($strComputer)" -status "Running..." -id 1 867 | $items = "" 868 | $items = listODBCConfigured $odbcConfigured 869 | foreach ($item in $items) { 870 | $dsn = $item.dsn 871 | $serverName = $item.serverName 872 | $port = $item.port 873 | $dataBaseFile = $item.dataBaseFile 874 | $dataBaseName = $item.dataBaseName 875 | $odbcUID = $item.odbcUID 876 | $odbcPWD = $item.odbcPWD 877 | $start = $item.start 878 | $lastUser = $item.lastUser 879 | $odbcDatabase = $item.odbcDatabase 880 | $defaultLibraries = $item.defaultLibraries 881 | $defaultPackage = $item.defaultPackage 882 | $defaultPkgLibrary = $item.defaultPkgLibrary 883 | $odbcSystem = $item.odbcSystem 884 | $driver = $item.driver 885 | $odbcDescription = $item.odbcDescription 886 | 887 | $odbcConfiguredQueryInsert = "INSERT INTO ODBCConfiguredAudited (serverID,dsn,serverName,port,dataBaseFile,dataBaseName,odbcUID,odbcPWD,start,lastUser,odbcDatabase,defaultLibraries,defaultPackage,defaultPkgLibrary,odbcSystem,driver,odbcDescription) 888 | VALUES ('$nbServer','$dsn','$serverName','$port','$dataBaseFile','$dataBaseName','$odbcUID','$odbcPWD','$start','$lastUser','$odbcDatabase','$defaultLibraries','$defaultPackage','$defaultPkgLibrary','$odbcSystem','$driver','$odbcDescription')" 889 | Insert-IntoDatabase $sqlCommand $odbcConfiguredQueryInsert 890 | Log-Write -LogPath $sLogFile -LineValue "$odbcConfiguredQueryInsert" 891 | } 892 | # Populate ODBC Drivers Installed 893 | Write-Progress -Activity "Getting ODBC Drivers Installed ($strComputer)" -status "Running..." -id 1 894 | $items = "" 895 | $items = listODBCInstalled $odbcDriversInstalled 896 | Write-Progress -Activity "Formating the output - ODBC Drivers Installed ($strComputer)" -status "Running..." -id 1 897 | foreach ($item in $items) { 898 | $driver = $item.Driver 899 | $driverODBCVer = $item.DriverODBCVer 900 | $fileExtns = $item.FileExtns 901 | $setup = $item.Setup 902 | 903 | $odbcInstalledQueryInsert = "INSERT INTO ODBCInstalledAudited (serverID,driver,driverODBCVer,fileExtns,setup) VALUES ('$nbServer','$driver','$driverODBCVer','$fileExtns','$setup')" 904 | Insert-IntoDatabase $sqlCommand $odbcInstalledQueryInsert 905 | Log-Write -LogPath $sLogFile -LineValue "$odbcInstalledQueryInsert" 906 | } 907 | 908 | Write-Progress -Activity "Getting local users information ($strComputer)" -status "Running..." -id 1 909 | $items = "" 910 | $items = getLocalUsersInGroup -ComputerName $strComputer -Credential $Credential 911 | Write-Progress -Activity "Inserting local users information ($strComputer)" -status "Running..." -id 1 912 | foreach($item in $items) { 913 | $group = $item.Group 914 | $user = $item.User 915 | $localUsersQueryInsert = "INSERT INTO LocalGroupAudited (serverID,localGroup,userNested) VALUES ('$nbServer','$group','$user')" 916 | Insert-IntoDatabase $sqlCommand $localUsersQueryInsert 917 | Log-Write -LogPath $sLogFile -LineValue "$localUsersQueryInsert" 918 | } 919 | 920 | Write-Progress -Activity "Getting OS Privileges information ($strComputer)" -status "Running..." -id 1 921 | Run-WmiRemoteProcess -ComputerName $strComputer -Cmd 'secedit.exe /export /cfg c:\secdump.txt' | Wait-Process 922 | Start-Sleep -Seconds 3 # wait for file to be created 923 | 924 | [string]$strScriptPath = Split-Path $MyInvocation.MyCommand.Pathwhoami 925 | $file = ($strScriptPath + "secdump.txt") 926 | try { 927 | 928 | $fileTocopy = "\\$strComputer\c$\secdump.txt" 929 | 930 | Copy-Item $fileTocopy $file 931 | } 932 | catch{ 933 | $_.Exception 934 | } 935 | 936 | $dumpResult = Parse-SecdumpFileToObject $file 937 | Start-Sleep -Seconds 1 938 | 939 | Remove-Item \\$strComputer\c$\secdump.txt 940 | Remove-Item $file 941 | 942 | # convert the dump to XML to a test file 943 | $XMLDump = $dumpResult | ConvertTo-XML -NoTypeInformation 944 | # Save Dump Data in the Output File 945 | $XMLDump.Save("secdump.xml") 946 | 947 | $xmlPath = "$scriptPath\secdump.xml" 948 | $nodes = "" 949 | $nodes = Select-Xml -Path $xmlPath -XPath "//Property" | Select-Object -ExpandProperty Node 950 | 951 | $arrayPrivilege = @{} 952 | 953 | $nbNode = 0 954 | $nodes | ForEach-Object { 955 | $name = "" 956 | $name = $_.Name 957 | if($name -eq "name") { 958 | $privilegeName = $_ | Select '#text' 959 | $privilegeName = $privilegeName.'#text' 960 | } 961 | if($name -eq "members") { 962 | $members = $_ | Select 'Property' 963 | $members = $members.property 964 | $arrayPrivilege.Add($privilegeName, $members) 965 | } 966 | 967 | $nbNode++ 968 | } 969 | 970 | foreach($privilege in $arrayPrivilege.keys) { 971 | $strategy = $privilege 972 | $securityParameters = $arrayPrivilege.item($privilege) 973 | $OSPrivilegeQueryInsert = "INSERT INTO OSPrivilegeAudited (serverID,strategy,securityParameter) VALUES ('$nbServer','$strategy','$securityParameters')" 974 | Insert-IntoDatabase $sqlCommand $OSPrivilegeQueryInsert 975 | Log-Write -LogPath $sLogFile -LineValue "$localUsersQueryInsert" 976 | } 977 | 978 | $nbSuccess++ 979 | } 980 | else { 981 | 982 | Log-Write -LogPath $sLogFile -LineValue "WMI connection to $strComputer failed`n" 983 | 984 | 985 | $serversNotResponding += "$strComputer `r`n" 986 | $nbError++ 987 | } 988 | } 989 | $sqlConnection.Close() 990 | 991 | $printErrorEncountered = "" 992 | 993 | if($nbError -gt 0) { 994 | $printErrorEncountered = "`r`n The script encountered $nbError error `r`n $serversNotResponding" 995 | } 996 | 997 | Log-Write -LogPath $sLogFile -LineValue "`r`n****************************************************** $printErrorEncountered `r`n $nbSuccess / $nbTot server(s) answer WMI requests `r`n $nbError / $nbTot server(s) NOT answer WMI requests `r`n ****************************************************** `n " 998 | 999 | Log-Write -LogPath $sLogFile -LineValue "Database connection closed" 1000 | 1001 | 1002 | 1003 | Log-Finish -LogPath $sLogFile 1004 | --------------------------------------------------------------------------------