PSMacToolkit.psm1
|
<# PSMacToolkit Copyright (C) 2025 Vincent Anso This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #> #Requires -Version 7.2 using module ".\StandardAdditions.psm1" using module ".\SystemInformation.psm1" using module ".\LoginWindow.psm1" using module ".\Network.psm1" using module ".\PSMacToolkitLib.psm1" if ( -Not $IsMacOS ) { Write-Warning "This module only runs on macOS." exit 0 } else { if (Test-Path -LiteralPath "$PSScriptRoot/More System Events.zip") { Write-Verbose "Need to unzip More System Events.app" /usr/bin/unzip -qo "$PSScriptRoot/More System Events.zip" -d "$PSScriptRoot/" /bin/rm "$PSScriptRoot/More System Events.zip" /bin/rm -R $PSScriptRoot/__MACOSX /usr/bin/open "$PSScriptRoot/More System Events.app" } if (Test-Path -LiteralPath "$PSScriptRoot/Notifications Scripting.zip") { Write-Verbose "Need to unzip Notifications Scripting.app" /usr/bin/unzip -qo "$PSScriptRoot/Notifications Scripting.zip" -d "$PSScriptRoot/" /bin/rm "$PSScriptRoot/Notifications Scripting.zip" /bin/rm -R $PSScriptRoot/__MACOSX } if (Test-Path -LiteralPath "$PSScriptRoot/Scripting Examples.zip") { Write-Verbose "Need to unzip Scripting Examples.app" /usr/bin/unzip -qo "$PSScriptRoot/Scripting Examples.zip" -d "$PSScriptRoot/" /bin/rm "$PSScriptRoot/Scripting Examples.zip" /bin/rm -R $PSScriptRoot/__MACOSX } [SPLocalization]::new() | Out-Null } if (Get-Module -ListAvailable | Where-Object Name -eq PowerShellOSA) { Import-Module PowerShellOSA } else { Write-Warning "The PowerShellOSA module must be installed to use PSMacToolkit." exit 0 } function Lock-Screen { <# .SYNOPSIS Lock the screen. #> param( [switch]$WithScreenSaver ) if ($WithScreenSaver) { $command = "launch application `"ScreenSaverEngine`"" } else { $command = "tell application `"System Events`" to keystroke `"q`" using {control down, command down}" } /usr/bin/osascript -e $command } function Get-UserCredential { <# .SYNOPSIS Prompt the user to enter their credentials. #> param ( [string]$WithTitle = "PowerShell credential request", [string]$WithPrompt = "Enter your credentials.", [string]$AsUserName, [switch]$UsingKeychainItem, [uri]$WithIconFile ) if (-Not $PSBoundParameters['WithTitle']) { $PSBoundParameters.Add("WithTitle", $WithTitle) } if (-Not $PSBoundParameters['WithPrompt']) { $PSBoundParameters.Add("WithPrompt", $WithPrompt) } $askCredentialsArguments = New-AppleScriptCommand "" $PSBoundParameters $script = "tell application `"`"PowerShellOSAUI`"`" set credentials to ask credentials $askCredentialsArguments { UserName: user name of credentials, ¬ |Password|: encrypt secure text (password of credentials), ¬ |KeychainItem|: keychain item of credentials, ¬ |VerifiedPassword|:verified password of credentials } end tell" $result = Invoke-OSA $script if ($result.OSAScriptErrorNumberKey) { $result ; break } [PSCustomObject]@{ UserName = $result.UserName Password = $result.Password ? $(ConvertTo-SecureString -String $result.Password) : $null KeychainItem = $result.KeychainItem VerifiedPassword = $result.VerifiedPassword } } enum DataDetectionType { AllTypes Link PhoneNumber Address Date TransitInformation } function Invoke-DataDetection { <# .SYNOPSIS Find dates, addresses, links, phone numbers, and transit information in natural language text. #> param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$InputObject, [DataDetectionType]$DataType = "AllTypes" ) if ($DataType -ne "AllTypes") { $Type = "Type$DataType" } else { $Type = "AllSystemTypes" } $script = " use framework `"`"Foundation`"`" use scripting additions property NSString : a reference to current application's NSString property NSDataDetector : a reference to current application's NSDataDetector property NSTextCheckingTypeLink : a reference to current application's NSTextCheckingTypeLink property NSTextCheckingTypePhoneNumber : a reference to current application's NSTextCheckingTypePhoneNumber property NSTextCheckingTypeAddress : a reference to current application's NSTextCheckingTypeAddress property NSTextCheckingTypeDate : a reference to current application's NSTextCheckingTypeDate property NSTextCheckingTypeTransitInformation : a reference to current application's NSTextCheckingTypeTransitInformation property NSTextCheckingAllSystemTypes : a reference to current application's NSTextCheckingAllSystemTypes set stringToCheck to `"`"$InputObject`"`" set theString to NSString's stringWithString:stringToCheck set {theDetector, theError} to NSDataDetector's dataDetectorWithTypes:NSTextChecking$Type |error|:(reference) set searchRange to {location:0, |length|:theString's |length|()} set matches to theDetector's matchesInString:theString options:0 range:searchRange if (count of matches) = 0 then return end if set resultList to {} repeat with match in matches set resultType to match's resultType as integer set range to match's range as record as list if resultType = NSTextCheckingTypeLink as integer then set end of resultList to {DataDetectionType:`"`"Link`"`", |Range|:range, |Result|:match's |URL|'s |absoluteString| as text} else if resultType = NSTextCheckingTypeDate as integer then set end of resultList to {DataDetectionType:`"`"Date`"`", |Range|:range, |Result|:match's |date| as date} else if resultType = NSTextCheckingTypePhoneNumber as integer then set end of resultList to {DataDetectionType:`"`"PhoneNumber`"`", |Range|:range, |Result|:match's |phoneNumber| as text} else if resultType = NSTextCheckingTypeAddress as integer then set end of resultList to {DataDetectionType:`"`"Address`"`", |Range|:range, |Result|:match's addressComponents as record} else if resultType = NSTextCheckingTypeTransitInformation as integer then set end of resultList to {DataDetectionType:`"`"TransitInformation`"`", |Range|:range, |Result|:match's components as record} end if end repeat return resultList " Invoke-OSA $script } function Get-HardwareInfo { <# .SYNOPSIS Get information about the hardware. #> Invoke-OSA "tell application `"`"More System Events`"`" to get hardware info" } Set-Alias -Name Choose-Application -Value Select-Application Set-Alias -Name Choose-Color -Value Select-Color Set-Alias -Name Choose-File -Value Select-File Set-Alias -Name Choose-FileName -Value Select-FileName Set-Alias -Name Choose-Folder -Value Select-Folder Set-Alias -Name Choose-FromList -Value Select-FromList Set-Alias -Name Choose-RemoteApplication -Value Select-RemoteApplication Set-Alias -Name Choose-URL -Value Select-URL Set-Alias -Name Display-Alert -Value Show-Alert Set-Alias -Name Display-Dialog -Value Show-Dialog Set-Alias -Name Display-Notification -Value Show-Notification Set-Alias -Name Log-Out -Value Disconnect-UserSession Set-Alias -Name Sleep-MacComputer -Value Suspend-MacComputer Set-Alias -Name Connect-EnterpriseWiFiNetwork -Value Connect-8021XWiFiNetwork Set-Alias -Name Get-EnterpriseNetworkConfigurationProfile -Value Get-8021XConfigurationProfile Set-Alias -Name Get-EnterpriseNetworkInfo -Value Get-8021XNetworkInfo Set-Alias -Name Get-EnterpriseNetworkPreferences -Value Get-8021XPreferences Set-Alias -Name Start-EnterpriseNetworkClient -Value Start-8021XClient Set-Alias -Name Stop-EnterpriseNetworkClient -Value Stop-8021XClient Export-ModuleMember -Alias @( 'Choose-Application', 'Choose-Color', 'Choose-File', 'Choose-FileName', 'Choose-Folder', 'Choose-FromList', 'Choose-RemoteApplication', 'Choose-URL', 'Display-Alert', 'Display-Dialog', 'Display-Notification', 'Log-Out', 'Sleep-MacComputer', 'Connect-EnterpriseWiFiNetwork', 'Get-EnterpriseNetworkConfigurationProfile', 'Get-EnterpriseNetworkInfo', 'Get-EnterprisePreferences', 'Start-EnterpriseNetworkClient', 'Stop-EnterpriseNetworkClient' ) Export-ModuleMember -Function @( 'Select-Application', 'Select-Color', 'Select-File', 'Select-FileName', 'Select-Folder', 'Select-FromList', 'Select-RemoteApplication', 'Select-URL', 'Get-ClipboardInfo', 'Get-InfoFor', 'Get-ListDisks', 'Get-ListFolder', 'Get-LocalizedString', 'Get-LocalizedStrings', 'Get-MacClipboard', 'Get-PathTo', 'Get-PathToResource', 'Get-ScriptingComponents', 'Get-SPAvailableDataTypes', 'Get-SPAvailableLocalizations', 'Get-SPLocalizedString' 'Get-SystemAttribute', 'Get-SystemInfo', 'Get-SystemInformation', 'Get-UserCredential', 'Get-VolumeSettings', 'Invoke-Beep', 'Invoke-DataDetection', 'Invoke-Delay', 'Invoke-Say', 'Lock-Screen', 'Disconnect-UserSession', 'Mount-Volume', 'Restart-MacComputer', 'Set-MacClipboard', 'Set-Volume', 'Show-Alert', 'Show-Dialog', 'Show-Notification', 'Stop-MacComputer', 'Suspend-MacComputer', 'Get-HardwareInfo', 'Connect-WiFiNetwork', 'Disconnect-WiFiNetwork', 'Find-WiFiNetwork', 'Get-WiFiNetworkInfo', 'Get-WiFiPreferences', 'Get-WiFiPreferredNetwork', 'Get-WiFiState', 'Set-WiFiState', 'Connect-8021XWiFiNetwork', 'Get-8021XConfigurationProfile', 'Get-8021XNetworkInfo', 'Get-8021XPreferences', 'Start-8021XClient', 'Stop-8021XClient', 'Get-CurrentNetworkLocation', 'Get-NetworkEthernetInterface', 'Get-NetworkInfo', 'Get-NetworkInterface', 'Get-NetworkLocation', 'Get-NetworkService', 'Get-PrimaryNetworkInterface' ) |