mirror of
https://github.com/winapps-org/winapps.git
synced 2025-05-31 20:37:18 +02:00
336 lines
13 KiB
PowerShell
336 lines
13 KiB
PowerShell
### FUNCTIONS ###
|
|
# Name: 'GetApplicationIcon'
|
|
# Role: Extract the icon from a given executable file as a base-64 string.
|
|
# Args:
|
|
# - 'exePath': Provides the path to the executable file.
|
|
Function GetApplicationIcon {
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$exePath
|
|
)
|
|
|
|
try {
|
|
# Load the 'System.Drawing' assembly to access 'ExtractAssociatedIcon'.
|
|
Add-Type -AssemblyName System.Drawing
|
|
|
|
# Extract the icon from the executable.
|
|
$exeIcon = [System.Drawing.Icon]::ExtractAssociatedIcon($exePath)
|
|
|
|
# Create a bitmap from the icon.
|
|
$exeIconBitmap = New-Object System.Drawing.Bitmap $exeIcon.Width, $exeIcon.Height
|
|
$graphics = [System.Drawing.Graphics]::FromImage($exeIconBitmap)
|
|
$graphics.DrawIcon($exeIcon, 0, 0)
|
|
|
|
# Save the bitmap to a 'MemoryStream' as a '.PNG' to preserve the icon colour depth.
|
|
$memoryStream = New-Object System.IO.MemoryStream
|
|
$exeIconBitmap.Save($memoryStream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
|
|
# Convert the PNG 'MemoryStream' to a base-64 string.
|
|
$bytes = $memoryStream.ToArray()
|
|
$base64String = [Convert]::ToBase64String($bytes)
|
|
|
|
# Clean up.
|
|
$memoryStream.Flush()
|
|
$memoryStream.Dispose()
|
|
$graphics.Dispose()
|
|
$exeIconBitmap.Dispose()
|
|
$exeIcon.Dispose()
|
|
} catch {
|
|
# Use a generic 32x32 PNG.
|
|
$base64String = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAASZQTFRFAAAA+vr65ubm4uLkhYmLvL7A7u7w+/r729vb4eHjFYPbFoTa5eXnGIbcG4jc+fn7Gofc7+/x7OzuF4Xb+fn54uLiC37Z5OTmEIHaIIjcEYHbDoDZFIPcJ43fHYjd9fX28PDy3d3fI4rd3d3dHojc19fXttTsJIve2dnZDX/YCn3Y09PTjL/p5+fnh7zo2traJYzfIYjdE4Pb6urrW6Tf9PT1Ioneir7otNPsCX3Zhbvn+Pj5YKfhJYfWMo7a39/gKIzeKo7eMI3ZNJDcXqbg4eHhuNTsB3zYIoncBXvZLIrXIYjbLJDgt7m6ubu+YqjiKYvYvr6+tba3rs/sz8/P1+byJonXv7/DiImLxsbGjo6Ra6reurq6io6QkJKVw8PD0tLSycnJq1DGywAAAGJ0Uk5TAP////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+BVJDaAAABY0lEQVR4nM2RaVOCUBSGr1CBgFZimppgoGnKopZSaYGmRpravq///0904IqOM9j00WeGT+9ztgtCS8Dzyh98fL6i2+HqQoaj0RPSzQNgzZc4F4wgvUuoqkr1er094MjlIeBCwRdFua9CqURQ51cty7Lykj0YCIIibnlEkS4TgCuky3nbTmSFsCKSHuso96N/Ox1aacjrlYQQ3gjNCYV7UlUJ6szCeRZyXmlkNjEZEPSuLIMAuYTreVYROQ8Y8SLTNAhlCdfzLMsaIhfHgEAT7pLtvFTH9QxTNWrmLsaEDu8558y2ZOP5LLNTNUQyiCFnHaRZnjTmzryhnR36FSdnIU9up7RGxAOuKJjOFX2vHvKU5jPiepbvxzR3BIffwROc++AAJy9qjQxQwz9rIjyGeN6tj8VACEyZCqfQn3H7F48vTvwEdlIP+aWvMNkPcl8h8DYeN5vNTqdzCNz5CIv4h7AE/AKcwUFbShJywQAAAABJRU5ErkJggg=="
|
|
}
|
|
|
|
# Return the base-64 string.
|
|
return $base64String
|
|
}
|
|
|
|
# Name: 'PrintArrayData'
|
|
# Role: Print application names, executable paths and base-64 encoded icons in a format suitable for importing into bash arrays.
|
|
# Args:
|
|
# - 'Names': An array of application names.
|
|
# - 'Paths': An array of executable paths.
|
|
# - 'Source': The source of the applications (e.g. Windows Registry, Package manangers, Universal Windows Platform (UWP), etc.)
|
|
function PrintArrayData {
|
|
param (
|
|
[string[]]$Names,
|
|
[string[]]$Paths,
|
|
[string]$Source
|
|
)
|
|
|
|
# Combine the arrays into an array of objects
|
|
$NamesandPaths = @()
|
|
for ($i = 0; $i -lt $Names.Length; $i++) {
|
|
$NamesandPaths += [PSCustomObject]@{
|
|
Name = $Names[$i]
|
|
Path = $Paths[$i]
|
|
}
|
|
}
|
|
|
|
# Sort the combined array based on the application names.
|
|
$NamesandPaths = $NamesandPaths | Sort-Object {$_.Name}
|
|
|
|
# Loop through the extracted executable file paths.
|
|
foreach ($Application in $NamesandPaths) {
|
|
|
|
# Remove undesirable suffix for chocolatey shims.
|
|
if ($Source -eq "choco") {
|
|
if ($Application.Name.EndsWith(" - Chocolatey Shim")) {
|
|
$Application.Name = $Application.Name.Substring(0, $Application.Name.Length - " - Chocolatey Shim".Length)
|
|
}
|
|
}
|
|
|
|
# Add the appropriate tag to the application name.
|
|
if ($Source -ne "winreg") {
|
|
$Application.Name = $Application.Name + " [" + $Source.ToUpper() + "]"
|
|
}
|
|
|
|
# Store the application icon as a base-64 string.
|
|
$Icon = GetApplicationIcon -exePath $Application.Path
|
|
|
|
# Output the results as bash commands that append the results to several bash arrays.
|
|
Write-Output ('NAMES+=("' + $Application.Name + '")')
|
|
Write-Output ('EXES+=("' + $Application.Path + '")')
|
|
Write-Output ('ICONS+=("' + $Icon + '")')
|
|
}
|
|
}
|
|
|
|
# Name: 'GetApplicationName'
|
|
# Role: Determine the application name for a given executable file.
|
|
# Args:
|
|
# - 'exePath': The path to a given executable file.
|
|
function GetApplicationName {
|
|
param (
|
|
[string]$exePath
|
|
)
|
|
|
|
if ((Get-Item $exePath).VersionInfo.FileDescription) {
|
|
# Remove leading/trailing whitespace and replace multiple spaces with a single space.
|
|
$productName = (Get-Item $exePath).VersionInfo.FileDescription.Trim() -replace '\s+', ' '
|
|
} else {
|
|
# Get the executable file name without the file extension.
|
|
$productName = [System.IO.Path]::GetFileNameWithoutExtension($exePath)
|
|
}
|
|
|
|
return $productName
|
|
}
|
|
|
|
# Name: 'GetUWPApplicationName'
|
|
# Role: Determine the application name for a given UWP application.
|
|
# Args:
|
|
# - 'exePath': The path to a given executable file.
|
|
function GetUWPApplicationName {
|
|
param (
|
|
[string]$exePath
|
|
)
|
|
|
|
# Query the application executable for the application name.
|
|
if (Test-Path $exePath) {
|
|
if ((Get-Item $exePath).VersionInfo.FileDescription) {
|
|
# Remove leading/trailing whitespace and replace multiple spaces with a single space.
|
|
$productName = (Get-Item $exePath).VersionInfo.FileDescription.Trim() -replace '\s+', ' '
|
|
}
|
|
}
|
|
|
|
# Use the 'DisplayName' (if available) if the previous method failed.
|
|
if (-not $productName -and $app.DisplayName) {
|
|
$productName = $app.DisplayName
|
|
}
|
|
|
|
# Use the 'Name' (if available) as a final fallback.
|
|
if (-not $productName -and $app.Name) {
|
|
$productName = $app.Name
|
|
}
|
|
|
|
return $productName
|
|
}
|
|
|
|
# Name: 'GetUWPExecutablePath'
|
|
# Role: Obtain the UWP application executable path from 'AppxManifest.xml'.
|
|
# Args:
|
|
# - 'instLoc': UWP application folder path (C:\Program Files\WindowsApps\*).
|
|
function GetUWPExecutablePath {
|
|
param (
|
|
[string]$instLoc
|
|
)
|
|
|
|
# Determine the path to 'AppxManifest.xml' for the selected application.
|
|
$manifestPath = Join-Path -Path $instLoc -ChildPath "AppxManifest.xml"
|
|
|
|
if (Test-Path $manifestPath) {
|
|
# Parse the XML file.
|
|
[xml]$manifest = Get-Content $manifestPath
|
|
$applications = $manifest.Package.Applications.Application
|
|
|
|
# Return the path to the first executable specified within the XML.
|
|
foreach ($application in $applications) {
|
|
$executable = $application.Executable
|
|
if ($executable) {
|
|
return Join-Path -Path $instLoc -ChildPath $executable
|
|
}
|
|
}
|
|
}
|
|
|
|
# Return 'null' if nothing was found.
|
|
return $null
|
|
}
|
|
|
|
# Name: 'AppSearchWinReg'
|
|
# Role: Search the Windows Registry for installed applications.
|
|
function AppSearchWinReg {
|
|
# Initialise empty arrays.
|
|
$exeNames = @()
|
|
$exePaths = @()
|
|
|
|
# Query windows registry for unique installed executable files.
|
|
$exePaths = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\*" |
|
|
ForEach-Object { $_."(default)" } | # Extract the value of the (default) property
|
|
Where-Object { $_ -ne $null } | # Filter out null values
|
|
Sort-Object -Unique # Ensure uniqueness
|
|
|
|
# Remove leading and trailing double quotes from all paths.
|
|
$exePaths = $exePaths -replace '^"*|"*$'
|
|
|
|
# Get corresponding application names for unique installed executable files.
|
|
foreach ($exePath in $exePaths) {
|
|
$exeNames += GetApplicationName -exePath $exePath
|
|
}
|
|
|
|
# Process extracted executable file paths.
|
|
PrintArrayData -Names $exeNames -Paths $exePaths -Source "winreg"
|
|
}
|
|
|
|
# Name: 'AppSearchUWP'
|
|
# Role: Search for 'non-system' UWP applications.
|
|
function AppSearchUWP {
|
|
# Initialise empty arrays.
|
|
$exeNames = @()
|
|
$exePaths = @()
|
|
|
|
# Obtain all 'non-system' UWP applications using 'Get-AppxPackage'.
|
|
$uwpApps = Get-AppxPackage | Where-Object {
|
|
$_.IsFramework -eq $false -and
|
|
$_.IsResourcePackage -eq $false -and
|
|
$_.SignatureKind -ne 'System'
|
|
}
|
|
|
|
# Create an array to store UWP application details.
|
|
$uwpAppDetails = @()
|
|
|
|
# Loop through each UWP application.
|
|
foreach ($app in $uwpApps) {
|
|
# Initialise the variable responsible for storing the UWP application name.
|
|
$productName = $null
|
|
|
|
# Obtain the path to the UWP application executable.
|
|
$exePath = GetUWPExecutablePath -instLoc $app.InstallLocation
|
|
|
|
# Proceed only if an executable path was identified.
|
|
if ($exePath) {
|
|
$productName = GetUWPApplicationName -exePath $exePath
|
|
|
|
# Ignore UWP applications with no name, or those named 'Microsoft® Windows® Operating System'.
|
|
if ($productName -ne "Microsoft® Windows® Operating System" -and [string]::IsNullOrEmpty($productName) -eq $false) {
|
|
# Store the UWP application name and executable path.
|
|
$exeNames += $productName
|
|
$exePaths += $exePath
|
|
}
|
|
}
|
|
}
|
|
|
|
# Process extracted executable file paths.
|
|
PrintArrayData -Names $exeNames -Paths $exePaths -Source "uwp"
|
|
}
|
|
|
|
# Name: 'AppSearchWinReg'
|
|
# Role: Search for chocolatey shims.
|
|
function AppSearchChocolatey {
|
|
# Initialise empty arrays.
|
|
$exeNames = @()
|
|
$exePaths = @()
|
|
|
|
# Specify the 'chocolatey' shims directory.
|
|
$chocoDir = "C:\ProgramData\chocolatey\bin"
|
|
|
|
# Check if the 'chocolatey' shims directory exists.
|
|
if (Test-Path -Path $chocoDir -PathType Container) {
|
|
# Get all shim '.exe' files.
|
|
$shimExeFiles = Get-ChildItem -Path $chocoDir -Filter *.exe
|
|
|
|
# Loop through each '.shim' file to extract the executable path.
|
|
foreach ($shimExeFile in $shimExeFiles) {
|
|
# Resolve the shim to the actual executable path.
|
|
$exePath = (Get-Command $shimExeFile).Source
|
|
|
|
# Proceed only if an executable path was identified.
|
|
if ($exePath) {
|
|
$exeNames += GetApplicationName -exePath $exePath
|
|
$exePaths += $exePath
|
|
}
|
|
}
|
|
|
|
# Process extracted executable file paths.
|
|
PrintArrayData -Names $exeNames -Paths $exePaths -Source "choco"
|
|
}
|
|
}
|
|
|
|
# Name: 'AppSearchWinReg'
|
|
# Role: Search for scoop shims.
|
|
function AppSearchScoop {
|
|
# Initialise empty arrays.
|
|
$exeNames = @()
|
|
$exePaths = @()
|
|
|
|
# Specify the 'scoop' shims directory.
|
|
$scoopDir = "$HOME\scoop\shims"
|
|
|
|
# Check if the 'scoop' shims directory exists.
|
|
if (Test-Path -Path $scoopDir -PathType Container) {
|
|
# Get all '.shim' files.
|
|
$shimFiles = Get-ChildItem -Path $scoopDir -Filter *.shim
|
|
|
|
# Loop through each '.shim' file to extract the executable path.
|
|
foreach ($shimFile in $shimFiles) {
|
|
# Read the content of the '.shim' file.
|
|
$shimFileContent = Get-Content -Path $shimFile.FullName
|
|
|
|
# Extract the path using regex, exiting the loop after the first match is found.
|
|
$exePath = ""
|
|
|
|
foreach ($line in $shimFileContent) {
|
|
# '^\s*path\s*=\s*"([^"]+)"'
|
|
# ^ --> Asserts the start of the line.
|
|
# \s* --> Matches any whitespace characters (zero or more times).
|
|
# path --> Matches the literal string "path".
|
|
# \s*=\s* --> Matches an equal sign = surrounded by optional whitespace characters.
|
|
# " --> Matches an initial double quote.
|
|
# ([^"]+) --> Captures one or more characters that are not ", representing the path inside the double quotes.
|
|
# " --> Matches a final double quote.
|
|
if ($line -match '^\s*path\s*=\s*"([^"]+)"') {
|
|
$exePath = $matches[1]
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($exePath -ne "") {
|
|
$exeNames += GetApplicationName -exePath $exePath
|
|
$exePaths += $exePath
|
|
}
|
|
}
|
|
|
|
# Process extracted executable file paths.
|
|
PrintArrayData -Names $exeNames -Paths $exePaths -Source "scoop"
|
|
}
|
|
}
|
|
|
|
### SEQUENTIAL LOGIC ###
|
|
# Print bash commands to define three new arrays.
|
|
Write-Output 'NAMES=()'
|
|
Write-Output 'EXES=()'
|
|
Write-Output 'ICONS=()'
|
|
|
|
# Search for installed applications.
|
|
AppSearchWinReg # Windows Registry
|
|
AppSearchUWP # Universal Windows Platform
|
|
AppSearchChocolatey # Chocolatey Package Manager
|
|
AppSearchScoop # Scoop Package Manager
|