Sunday, April 24, 2011

The 2011 Scripting Games Advanced Event 1: Finding Process Module Versions by Using PowerShell

The 2011 Scripting Games Advanced Event 1: Finding Process Module Versions by Using PowerShell

My personal script:
http://2011sg.poshcode.org/597
with a "wow..nice script" comment by Ed Wilson which is a real gift for me
Average Rating: 3.50 by 2 users.
(Download it)


#
#
# 2011 Scripting Games Advanced Event 1: Finding Process Module Versions by Using PowerShell
#
# by F.Richard 2011-04
#
#

#Requires -Version 2.0

# Main Program
Param(
[parameter(Position=0)]
[String[]]
$action="Localhost",
[parameter(Position=1)]
[String[]]
$inputfile
)




# ***********************************************

Function isComputerInADomain {
<#
.SYNOPSIS
Is computer in a domain
.DESCRIPTION
Is computer in a domain. Return $True or $False
.PARAMETER strComputer
Computer name. Default to localhost.
.EXAMPLE
isComputerInADomain
is local machine in a domain ?
.EXAMPLE
isComputerInADomain mycomputer
is mycomputer in a domain ?
#>
Param ([string] $strComputer)
$strComputer = $(if ($strComputer) {$strComputer} else {Get-Content ENV:COMPUTERNAME})
if ((Get-WmiObject -ComputerName $strComputer Win32_ComputerSystem).PartOfDomain -eq $true) {
return $true
} else {
return $false
}
}

# ***********************************************

Function GetUserDomainDNS {
<#
.SYNOPSIS
return user domain name in DNS format ex: domain.net
.DESCRIPTION
return user domain name in DNS format ex: domain.net
.EXAMPLE
GetUserDomainDNS
return user domain name ex: domain.net
#>
[string] $strDomainDNS = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
Return $strDomainDNS
}

# ***********************************************

Function GetComputerDomainDNS {
<#
.SYNOPSIS
return local computer domain name in DNS format ex: domain.net
.DESCRIPTION
return local computer domain name in DNS format ex: domain.net
.EXAMPLE
GetComputerDomainDNS
return local computer domain name ex: domain.net
#>
[string] $strDomainDNS = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().Name
Return $strDomainDNS
}

# ***********************************************

# GetDomainDN
# get Domain name in DNS format ex: domain.net
#
Function GetDomainDN {
<#
.SYNOPSIS
return domain name in Distinguished Name format ex: DC=DOMAIN,DC=NET
.DESCRIPTION
from domain name DNS format domain.net to
return domain name in Distinguished Name format ex: DC=DOMAIN,DC=NET
.PARAMETER strDomainDNS
Domain name in DNS format. Ex: domain.net
.EXAMPLE
GetDomainDN domain.net
return DC=DOMAIN,DC=NET
.EXAMPLE
GetDomainDN -strDomainDNS domain.net
return DC=DOMAIN,DC=NET
#>
Param ([string] $strDomainDNS)
$strDomainDN = "DC=" + $strDomainDNS -replace "\.",",DC="
Return $strDomainDN
}

# ***********************************************

Function SearchAD {
<#
.SYNOPSIS
return AD query
.DESCRIPTION
return AD query
.PARAMETER options
Hashtable
.EXAMPLE
$hashSearchAD = @{ }
$hashSearchAD["strFilter"] = "(objectCategory=computer)"
$hashSearchAD["strSearchScope"] = "Subtree"
$hashSearchAD["colAttributes"] = "name"
$hashSearchAD["strBaseDN"] = "DC=DOMAIN,DC=NET"
searchAD $hashSearchAD
#>
Param ([hashtable] $options)
$strFilter = $(if ($options.ContainsKey("strFilter")) {$options["strFilter"]} else {""}) # ex: '(objectCategory=computer)'
$strSearchScope = $(if ($options.ContainsKey("strSearchScope")) {$options["strSearchScope"]} else {"Subtree"}) # Base, OneLevel or Subtree
$colAttributes = $(if ($options.ContainsKey("colAttributes")) {$options["colAttributes"]} else {""}) # ex: '"name", "jobTitle", "telephoneNumber"
$strBaseDN = $(if ($options.ContainsKey("strBaseDN")) {$options["strBaseDN"]} else {""}) # ex: DC=Domain,DC=NET

$strBase = New-Object System.DirectoryServices.DirectoryEntry ("LDAP://" + $strBaseDN)
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $strBase
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = $strSearchScope
Foreach ($attribute in $colAttributes){$objSearcher.PropertiesToLoad.Add($attribute)}

$dtResult = New-Object "System.Data.DataTable"
$dtResult = $objSearcher.FindAll() # .FindOne() .FindAll()
#Write-host "count:" $dtResult.count
return $dtResult
}

# ***********************************************

Function TestFile {
<#
.SYNOPSIS
Test if file exist
.DESCRIPTION
Test if file strFilename exist
Then test if file exist in strCurDir\strFilename path
Return filename path
.PARAMETER strFilename
filename to test
.PARAMETER strCurDir
directory to test filename if not in current directory
.EXAMPLE
TestFile -strFilename abcdefghijkl.txt
return
ERROR: file abcdefghijkl.txt NOT exist
ERROR: file D:\Datas\Dev\abcdefghijkl.txt NOT exist
.EXAMPLE
TestFile -strFilename regedit.exe -strCurDir C:\WINDOWS
return C:\WINDOWS\regedit.exe
#>
Param(
[String] $strFilename,
[String] $strCurDir
)
if ($strFilename) {
$strCurDir = $(if ($strCurDir) {$strCurDir} else {if ($MyInvocation.MyCommand.CommandType -eq "Function") {(Get-Location).Path} else {Split-Path -parent $MyInvocation.MyCommand.Path} })
If ((Test-Path("$strFilename")) -eq $False){
If ($strFilename.ToUpper().Contains($strCurDir.ToUpper()) ) {
Write-Host "ERROR: file $strFilename NOT exist"
return
} Else {
If ((Test-Path("$strCurDir\$strFilename")) -eq $False){
Write-Host "ERROR: file $strFilename NOT exist"
Write-Host "ERROR: file $strCurDir\$strFilename NOT exist"
return
} Else {
$strFilename = "$strCurDir\$strFilename"
}
}
}
return $strFilename
}
}


# ***********************************************

Function GetFileIntoArr {
<#
.SYNOPSIS
Import File into an array
.DESCRIPTION
Import File into an array
.PARAMETER strFilename
filename to import
.PARAMETER strCurDir
directory to test filename if not in current directory
.PARAMETER arrFile
array where file is imported
.PARAMETER strComment
1st line character for comment line (default: #)
.EXAMPLE
[Array] $arrContent = @( )
GetFileIntoArr -strFilename .\content.txt -arrFile ([Ref]$arrContent)
return
#>
Param(
[String] $strFilename,
[String] $strCurDir,
[Ref]$arrFile,
[String] $strComment
)
$strComment = $(if ($strComment) {$strComment} else {"#"})
$strCurDir = $(if ($strCurDir) {$strCurDir} else {if ($MyInvocation.MyCommand.CommandType -eq "Function") {(Get-Location).Path} else {Split-Path -parent $MyInvocation.MyCommand.Path} })

$retFilename = TestFile -strFilename $strFilename -strCurDir $strCurDir
if ($retFilename) {
$Content = Get-Content "$retFilename"
Foreach ($line in $Content) {
$comment = $False
If ($line.length -gt 0) { # take only line with data and without # at begininng of the line
# if we do not want to use comment
If ($strComment -eq "#") {
If ($line.substring(0,1) -eq "#") {
$comment = $True
}
}
If ($comment -eq $False) {
# Get Search & Replace
$arrFile.Value += $line.Trim()
}
}
}
return $True
} else {
return $False
}
}

# ***********************************************


Function GetADComputerToArray {
<#
.SYNOPSIS
return AD Computer query to array
.DESCRIPTION
return AD Computer query to array
.PARAMETER strDomainDN
Domain name in DN format. Default: Computer Domain Name ex: DC=DOMAIN,DC=NET
.PARAMETER strFilter
Computer AD filter. Default: (objectCategory=computer)
.PARAMETER strSearchScope
Domain name in DNS format. Default: Subtree
.PARAMETER colAttributes
Attributes to get. Default: name
.EXAMPLE
[Array] $arrComputers = @( )
GetADComputerToArray -array ([Ref]$arrComputers)
#>
Param(
[Ref]$array,
[String] $strDomainDN,
[String] $strFilter,
[String] $strSearchScope,
[String] $colAttributes
)
$strDomainDN = $(if ($strDomainDN) {$strDomainDN} else {GetDomainDN -strDomainDNS (GetComputerDomainDNS)})
$strFilter = $(if ($strFilter) {$strFilter} else {'(objectCategory=computer)'})
$strSearchScope = $(if ($strSearchScope) {$strSearchScope} else {"Subtree"})
$colAttributes = $(if ($colAttributes) {$colAttributes} else {"name"})
$hashSearchAD = @{ }
$hashSearchAD["strFilter"] = $strFilter
$hashSearchAD["strSearchScope"] = $strSearchScope # Base, OneLevel or Subtree
$hashSearchAD["colAttributes"] = $colAttributes # ex: '"name", "jobTitle", "telephoneNumber"
$hashSearchAD["strBaseDN"] = $strDomainDN
$dtResult = SearchAD($hashSearchAD)
If ($dtResult -ne $Null) {
Foreach ($row in $dtResult){
If ($row.GetType().Name -eq "Int32") {
} else {
$result = $row.GetDirectoryEntry()
$array.Value += $result.Name
Write-Host $result.Name
}
}
}
}

# ***********************************************



Function Get-AdvEvent1 {
<#
.SYNOPSIS
2011 Scripting Games Advanced Event 1
.DESCRIPTION
2011 Scripting Games Advanced Event 1
Finding Process Module Versions by Using PowerShell
.PARAMETER action
action : ad / file / localhost
.PARAMETER inputfile
inputfile filename for file option
.EXAMPLE
Get-AdvEvent1
"Localhost only"
Get process module version for Localhost
.EXAMPLE
Get-AdvEvent1 ad
Get process module version for AD query computers
.EXAMPLE
Get-AdvEvent1 file filename.txt
Get process module version for all computers in filename.txt
#>
Param(
[String] $action,
[String] $inputfile
)
# local computername
$computername = (Get-Content ENV:COMPUTERNAME)
[Array] $arrComputers = @( )

# Default action = localhost
switch($action) {
"localhost" {
$arrComputers += $computername
}

# AD Query
"ad" {
Write-Host "AD"
if(isComputerInADomain) {
GetADComputerToArray -array ([Ref]$arrComputers)
} else {
Write-Host "ERROR: $computername is NOT in a domain. You cound not use switch $action"
return
}
}

# File content
"file" {
if ($inputfile) {
if (!(GetFileIntoArr -strFilename $inputfile -arrFile ([Ref]$arrComputers))) {
return
}
} else {
Write-Host "ERROR: With action $action switch you need a filename.txt as second parameter inputfile"
return
}
}

# Others actions = Help
Default {
get-help Get-AdvEvent1 -full
return
}
}


# Check "Windows Spooler Driver" module in Notepad process
$processName="notepad"
[Array] $arrObj = @( )
Foreach ($computer in $arrComputers) {
# Create process
$process = ([WMICLASS]"\\$computer\ROOT\CIMV2:win32_process").Create($processName)
if ($process.ReturnValue -eq 0) {
Start-Sleep -m 100 # Else too fast on my machine
# Get Process Id
$proc = invoke-command -computername $computer -scriptblock {param($id) get-process -id $id -module} -ArgumentList $process.ProcessId
# Get informations in custom object
$obj = New-Object PSObject
# Multilanguage below: Description -eq "Windows Spooler Driver" only for english
$obj = $proc | where-object {$_.ModuleName -eq "winspool.drv"} | select @{Name="computer"; Expression = {$computer}},ModuleName,Size,Filename,FileVersion
# Kill process
[System.Diagnostics.Process]::GetProcessByID($process.ProcessId,$computer).kill()
if ($obj) { $arrObj += $obj }
} else {
# Write-Host "Failed to create process!"
}
}

# Display information
$arrObj | ConvertTo-Csv -NoTypeInformation

}


# ***********************************************

# Main program

Get-AdvEvent1 -action $action -inputfile $inputfile


No comments: