Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions scripts_wip/Win_Software_AddRemovelog.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<#
.Synopsis
Software Install and Removal Detection - Reports new installs and removals without considering version numbers.
.DESCRIPTION
This script compares the current installed software list from the registry with a previous state.
.VERSION
v1.0 11/23/2024
#>

Function Foldercreate {
param (
[Parameter(Mandatory = $false)]
[String[]]$Paths
)

foreach ($Path in $Paths) {
if (!(Test-Path $Path)) {
New-Item -ItemType Directory -Force -Path $Path
}
}
}
Foldercreate -Paths "$env:ProgramData\TacticalRMM\temp", "$env:ProgramData\TacticalRMM\logs"

# Define file paths
$previousStateFile = "$env:ProgramData\TacticalRMM\installed_software.json"
$logFile = "$env:ProgramData\TacticalRMM\logs\software_changes.log"

# Function to get installed software from the registry
function Get-InstalledSoftware {
$installedSoftware = @()

# Get software from 64-bit and 32-bit registry paths
$installedSoftware += Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Select-Object DisplayName, DisplayVersion
$installedSoftware += Get-ItemProperty 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Select-Object DisplayName, DisplayVersion

# Filter out entries without a valid DisplayName
$installedSoftware = $installedSoftware | Where-Object { $_.DisplayName -ne $null -and $_.DisplayName -ne '' }

# Strip version number patterns from DisplayName and remove duplicates
$installedSoftware = $installedSoftware | ForEach-Object {
if ($_.DisplayVersion -and $_.DisplayName -like "*$($_.DisplayVersion)*") {
$_.DisplayName = $_.DisplayName -replace [regex]::Escape($_.DisplayVersion), '' # Strip DisplayVersion
$_.DisplayName = $_.DisplayName.Trim() # Remove trailing spaces
}
$_
} | Sort-Object DisplayName -Unique

return $installedSoftware
}

# Function to log changes to a file, ensuring proper logging
function LogChange {
param([string]$message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp - $message"

# Write the log entry to the file
Add-Content -Path $logFile -Value $logEntry
}

# Get current installed software
$currentSoftware = Get-InstalledSoftware

# Check if the previous state file exists
if (Test-Path $previousStateFile) {
# Load the previous state
$previousSoftware = Get-Content $previousStateFile | ConvertFrom-Json

# Compare current and previous software lists
$newSoftware = Compare-Object -ReferenceObject $previousSoftware -DifferenceObject $currentSoftware -Property DisplayName -PassThru |
Where-Object { $_.SideIndicator -eq '=>' }

$removedSoftware = Compare-Object -ReferenceObject $previousSoftware -DifferenceObject $currentSoftware -Property DisplayName -PassThru |
Where-Object { $_.SideIndicator -eq '<=' }

# Report new installs
if ($newSoftware) {
Write-Output "New software installed:"
$newSoftware | ForEach-Object {
Write-Output " - $($_.DisplayName)"
LogChange "Installed: $($_.DisplayName)"
}
}

# Report removals
if ($removedSoftware) {
Write-Output "The following software(s) were removed:"
$removedSoftware | ForEach-Object {
Write-Output " - $($_.DisplayName)"
LogChange "Removed: $($_.DisplayName)"
}
}

# Save the current state (overwrite the existing file)
$currentSoftware | ConvertTo-Json | Out-File -FilePath $previousStateFile -Encoding UTF8

# Exit with status code based on changes
if ($newSoftware -or $removedSoftware) {
exit 1
}
else {
Write-Output "No new software installations or removals detected."
exit 0
}
}
else {
# Save the current state if no previous state exists (overwrite if needed)
$currentSoftware | ConvertTo-Json | Out-File -FilePath $previousStateFile -Encoding UTF8
LogChange "Initial software inventory saved."
Write-Output "Initial software inventory saved."
exit 0
}
72 changes: 72 additions & 0 deletions scripts_wip/Win_User_Admin_check_if_admin.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<#
.SYNOPSIS
Reports if the currently logged-in interactive user has local administrator rights.
This script is designed to be run from the SYSTEM account.

.DESCRIPTION
When run as SYSTEM, the script first identifies the user who is actively
logged into the console session. It then uses the reliable ADSI provider to
query the local 'Administrators' group and checks if the detected user is a member.

This revised version avoids potential name resolution errors encountered with the
[System.Security.Principal.WindowsIdentity] .NET class when run as SYSTEM.

.NOTES
v1 2025-7-22 silversword411 initial release
#>
[CmdletBinding()]
param()

# Suppress errors for the initial check in case no one is logged in
$ErrorActionPreference = 'SilentlyContinue'

# --- Step 1: Find the currently logged-in user from the SYSTEM context ---
Write-Verbose "Querying Win32_ComputerSystem to find the interactive user..."
$loggedInUser = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
$ErrorActionPreference = 'Continue' # Reset error preference

# --- Step 2: Check if a user was found ---
if ([string]::IsNullOrWhiteSpace($loggedInUser)) {
Write-Output "Status: No interactive user is currently logged in to the console."
exit 0
}

# The user is typically returned as "DOMAIN\user" or "COMPUTERNAME\user".
# We only need the username part for the group check.
$usernameOnly = $loggedInUser.Split('\')[-1]
Write-Output "Detected logged-in user: $loggedInUser (Checking for account: $usernameOnly)"


# --- Step 3 (Revised): Check group membership using ADSI ---
try {
# Define the well-known name for the local Administrators group
$adminGroupName = "Administrators"

# Use the ADSI provider to connect to the local Administrators group.
# The "WinNT://" provider is used for local machine resources.
# The "." represents the local computer.
$group = [ADSI]"WinNT://./$adminGroupName,group"

# Get all members of the group.
$members = $group.psbase.Invoke("Members") | ForEach-Object {
# For each member object, get its 'Name' property
$_.GetType().InvokeMember("Name", "GetProperty", $null, $_, $null)
}

# Now, check if the username is in the list of administrator members.
# We use the username part we extracted earlier ($usernameOnly).
if ($members -contains $usernameOnly) {
Write-Output "Result: The user '$loggedInUser' IS an Administrator."
$host.SetShouldExit(1)
}
else {
Write-Output "Result: The user '$loggedInUser' is NOT an Administrator."
# You could exit with a specific code, e.g., exit 0 for "Not Admin"
}
}
catch {
Write-Error "An error occurred while checking Administrators group membership."
Write-Error "Error details: $($_.Exception.Message)"
# Exit with an error code
exit 99
}