148 lines
6.3 KiB
PowerShell
148 lines
6.3 KiB
PowerShell
# Specify the working directory for this script to place files
|
|
$WORK_DIR = "${Env:ProgramData}\Atera"
|
|
|
|
# Specify the name of the previous generation file to compare with the current generation file
|
|
$P_FILE = "${WORK_DIR}\InstalledSoftware_Previous.csv"
|
|
|
|
# Specify the name of the current generation file to compare with the previous generation file
|
|
$C_FILE = "${WORK_DIR}\InstalledSoftware_Current.csv"
|
|
|
|
# Function to append a line to a file
|
|
Function Write-LineToFile {
|
|
param([Parameter(Mandatory=$true)][string]$Path,[Parameter(Mandatory=$true)][string]$Line)
|
|
If ( -not (Test-Path $Path) ) {
|
|
#Write-Output "Creating file ""${Path}"""
|
|
Try { New-Item -Path $Path -ItemType File -Force | Out-Null }
|
|
Catch { Write-Error $_.Exception.Message }
|
|
}
|
|
Try { Add-Content -Path $Path -Value $Line }
|
|
Catch { Write-Error $_.Exception.Message }
|
|
}
|
|
|
|
# Function to test whether or not an item has a specified property
|
|
Function Test-ItemProperty {
|
|
param([Parameter(Mandatory=$true)][string]$Path,[Parameter(Mandatory=$true)][string]$Name)
|
|
Try {
|
|
$test = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
|
|
If (($null -eq $test) -or ($test.Length -eq 0)) { Return $false } Else { Return $true }
|
|
}
|
|
Catch { Return $false }
|
|
}
|
|
|
|
# Function to retrieve an item property
|
|
Function Get-ItemPropertyInfo {
|
|
param([Parameter(Mandatory=$true)][string]$Path,[Parameter(Mandatory=$true)][string]$Name)
|
|
If ( Test-ItemProperty -Path $Path -Name $Name ) {
|
|
$retval = Get-ItemPropertyValue -Path $Path -Name $Name
|
|
$retval = $retval -replace ",", " "
|
|
|
|
# Additional processing for specific properties
|
|
Switch ( $Name ) {
|
|
|
|
# Convert the estimated size into MB
|
|
"EstimatedSize" {
|
|
$size = [int]$retval
|
|
$size = [Math]::Ceiling($size / 1024)
|
|
$retval = [string]$size
|
|
}
|
|
|
|
# Convert the date format into YYYY-MM-DD
|
|
"InstallDate" {
|
|
|
|
$origRetval = $retval
|
|
|
|
# Try to find each type of date string so we can convert it
|
|
Switch -Regex ( $retval ) {
|
|
'^\d{8}$' { $formatstring = 'yyyyMMdd' }
|
|
'^\d{1,2}\\\d{1,2}\\\d{4}$' { $formatstring = 'MM\dd\yyyy' }
|
|
'^\d{4}\\\d{1,2}\\\d{1,2}$' { $formatstring = 'yyyy\MM\dd' }
|
|
Default { $formatstring = $null }
|
|
}
|
|
|
|
# Make sure $formatstring has a value, if not just try to cast directly to a datetime
|
|
Try {
|
|
If ( $null -eq $formatstring ) {
|
|
$date = [datetime]$retval
|
|
} Else {
|
|
$date = [datetime]::ParseExact($retval,$formatstring,$null)
|
|
}
|
|
|
|
# Set $retval to a standard datetime format
|
|
$retval = $date.ToString('yyyy-MM-dd')
|
|
}
|
|
Catch { Write-Error $_.Exception.Message; $retval = $origRetval }
|
|
}
|
|
Default {}
|
|
}
|
|
}
|
|
Else { $retval = "" }
|
|
|
|
Return $retval
|
|
}
|
|
|
|
# Create $WORK_DIR if it doesn't exist
|
|
If ( -not (Test-Path $WORK_DIR) ) { New-Item -Path $WORK_DIR -ItemType Directory -Force | Out-Null }
|
|
|
|
# Create $C_FILE if it doesn't exist
|
|
If ( -not (Test-Path $C_FILE) ) {
|
|
# Write the headers to the output file
|
|
Write-LineToFile -Path $C_FILE -Line "Name,Publisher,Version,InstallDate,EstimatedSize(MB),UninstallString,ModifyPath"
|
|
|
|
# Iterate through all Registry Uninstall keys and build the CSV file of all installed software
|
|
ForEach ( $item in $(Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall','HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') ) {
|
|
$DisplayName = Get-ItemPropertyInfo -Path $item.PSPath -Name DisplayName
|
|
$DisplayVersion = Get-ItemPropertyInfo -Path $item.PSPath -Name DisplayVersion
|
|
$EstimatedSize = Get-ItemPropertyInfo -Path $item.PSPath -Name EstimatedSize
|
|
$InstallDate = Get-ItemPropertyInfo -Path $item.PSPath -Name InstallDate
|
|
$Publisher = Get-ItemPropertyInfo -Path $item.PSPath -Name Publisher
|
|
$UninstallString = Get-ItemPropertyInfo -Path $item.PSPath -Name UninstallString
|
|
$ModifyPath = Get-ItemPropertyInfo -Path $item.PSPath -Name ModifyPath
|
|
|
|
# Write installed software to output file only if it has a name and uninstall/modify path, otherwise discard
|
|
If ( -not (($DisplayName -eq "") -and ($UninstallString -eq "") -and ($ModifyPath -eq "")) ) {
|
|
$content = "${DisplayName},${Publisher},${DisplayVersion},${InstallDate},${EstimatedSize},${UninstallString},${ModifyPath}"
|
|
Write-LineToFile -Path $C_FILE -Line $content
|
|
}
|
|
}
|
|
}
|
|
|
|
# Compare $C_FILE and $P_FILE
|
|
If ( (Test-Path $C_FILE) -and (Test-Path $P_FILE) ) {
|
|
$current = Import-Csv -Path $C_FILE
|
|
$previous = Import-Csv -Path $P_FILE
|
|
|
|
# Items that exist in $C_FILE but not $P_FILE have been installed
|
|
$installed = Compare-Object -ReferenceObject $current -DifferenceObject $previous -Property Name,Version -PassThru | Where-Object { (![string]::IsNullOrEmpty($_.Name)) -and ($_.SideIndicator -eq '<=') }
|
|
|
|
# Items that exist in $P_FILE but not $C_FILE have been uninstalled
|
|
$uninstalled = Compare-Object -ReferenceObject $current -DifferenceObject $previous -Property Name,Version -PassThru | Where-Object { (![string]::IsNullOrEmpty($_.Name)) -and ($_.SideIndicator -eq '=>') }
|
|
|
|
# Alert trigger for Atera
|
|
If ( $installed -or $uninstalled ) { Write-Output "Application change detected" }
|
|
|
|
# Display installed apps
|
|
If ( $installed ) {
|
|
Write-Output "`nAPPLICATIONS RECENTLY INSTALLED:"
|
|
$installed | Select-Object * -ExcludeProperty SideIndicator
|
|
}
|
|
|
|
# Display uninstalled apps
|
|
If ( $uninstalled ) {
|
|
Write-Output "`nAPPLICATIONS RECENTLY UNINSTALLED:"
|
|
$uninstalled | Select-Object * -ExcludeProperty UninstallString,ModifyPath,SideIndicator
|
|
}
|
|
}
|
|
|
|
# Delete $P_FILE
|
|
If ( Test-Path $P_FILE ) {
|
|
#Write-Output "Deleting ""${P_FILE}"""
|
|
Remove-Item -Path $P_FILE -Force
|
|
}
|
|
|
|
# Rename $C_FILE to $P_FILE
|
|
If ( Test-Path $C_FILE ) {
|
|
#Write-Output "Renaming ""${C_FILE}"" to ""${P_FILE}"""
|
|
Move-Item -Path $C_FILE -Destination $P_FILE -Force
|
|
}
|
|
|