PSWinOps.psm1
|
#Requires -Version 5.1 <# .SYNOPSIS PSWinOps module loader .DESCRIPTION Loads all public and private functions for the PSWinOps module. Public functions are automatically exported. #> # Guard: this module is Windows-only (Win32/CIM/registry/netsh/w32tm/mstsc/logoff) if ($PSEdition -eq 'Core' -and -not $IsWindows) { throw 'PSWinOps requires Windows. Linux and macOS are not supported.' } # Get module root path $script:ModuleRoot = $PSScriptRoot # Module-scoped list of names that identify the local machine $script:LocalComputerNames = @($env:COMPUTERNAME, 'localhost', '.') Write-Verbose "[$($MyInvocation.MyCommand)] Loading PSWinOps module from: $script:ModuleRoot" # Legacy alias gate — opt-in for one minor release cycle, then remove entirely. # Set $env:PSWINOPS_LEGACY_ALIASES = '1' BEFORE Import-Module to re-create the # pre-rename aliases. Each gated alias emits a deprecation warning. if ($env:PSWINOPS_LEGACY_ALIASES -eq '1') { Set-Alias -Name 'Download-WindowsUpdate' -Value 'Save-WindowsUpdate' -Scope Global Write-Warning "PSWinOps: 'Download-WindowsUpdate' alias is deprecated. Use 'Save-WindowsUpdate' (Download is not an approved verb). This alias will be removed in a future minor release." } # Import Private functions $privatePath = Join-Path -Path $script:ModuleRoot -ChildPath 'Private' if (Test-Path -Path $privatePath) { Write-Verbose "[$($MyInvocation.MyCommand)] Loading Private functions from: $privatePath" Get-ChildItem -Path $privatePath -Filter '*.ps1' -Recurse | ForEach-Object { Write-Verbose "[$($MyInvocation.MyCommand)] Importing private function: $($_.Name)" . $_.FullName } } # Import Public functions $publicPath = Join-Path -Path $script:ModuleRoot -ChildPath 'Public' if (Test-Path -Path $publicPath) { Write-Verbose "[$($MyInvocation.MyCommand)] Loading Public functions from: $publicPath" Get-ChildItem -Path $publicPath -Filter '*.ps1' -Recurse | ForEach-Object { Write-Verbose "[$($MyInvocation.MyCommand)] Importing public function: $($_.Name)" . $_.FullName } } # ============================================================ # Short aliases for every public function # ============================================================ $script:AliasMap = @{ 'cfms' = 'ConvertFrom-MisencodedString' 'cla' = 'Clear-Arp' 'cldc' = 'Clear-DiskCleanup' 'clwuc' = 'Clear-WindowsUpdateCache' 'conrs' = 'Connect-RdpSession' 'ctm' = 'ConvertTo-Markdown' 'dconrs' = 'Disconnect-RdpSession' 'disaua' = 'Disable-ADUserAccount' 'ehf' = 'Edit-HostsFile' 'enaua' = 'Enable-ADUserAccount' 'expnc' = 'Export-NetworkConfig' 'gacd' = 'Get-ADComputerDetail' 'gaci' = 'Get-ADComputerInventory' 'gadch' = 'Get-AdDomainControllerHealth' 'gadi' = 'Get-ADDomainInfo' 'gagi' = 'Get-ADGroupInventory' 'gagm' = 'Get-ADGroupMembership' 'gah' = 'Get-ADFSHealth' 'gala' = 'Get-ADLockedAccount' 'gals' = 'Get-ADLockoutSource' 'gangm' = 'Get-ADNestedGroupMembership' 'gap' = 'Get-AuditPolicy' 'gapa' = 'Get-ADPrivilegedAccount' 'gaps' = 'Get-ADPasswordStatus' 'gars' = 'Get-ADReplicationStatus' 'gasa' = 'Get-ADStaleAccount' 'gasc' = 'Get-ADStaleComputer' 'gast' = 'Get-ADSiteTopology' 'gat' = 'Get-ARPTable' 'gaud' = 'Get-ADUserDetail' 'gaugi' = 'Get-ADUserGroupInventory' 'gaui' = 'Get-ADUserInventory' 'gcah' = 'Get-CertificateAuthorityHealth' 'gcd' = 'Get-CrashDump' 'gch' = 'Get-ClusterHealth' 'gcu' = 'Get-ComputerUptime' 'gdci' = 'Get-DiskCleanupInfo' 'gdee' = 'Get-DiskErrorEvent' 'gdi' = 'Get-DriverInventory' 'gdnh' = 'Get-DfsNamespaceHealth' 'gdrh' = 'Get-DfsReplicationHealth' 'gds' = 'Get-DiskSpace' 'gdsh' = 'Get-DhcpServerHealth' 'gdshe' = 'Get-DnsServerHealth' 'gec' = 'Get-ExpiringCertificate' 'gesh' = 'Get-ExchangeServerHealth' 'gev' = 'Get-EnvironmentVariable' 'gfsh' = 'Get-FileServerHealth' 'ghvhh' = 'Get-HyperVHostHealth' 'giaph' = 'Get-IISAppPoolHistory' 'gicb' = 'Get-IISCertificateBinding' 'gicr' = 'Get-IISCurrentRequest' 'gifrt' = 'Get-IISFailedRequestTrace' 'gih' = 'Get-IISHealth' 'gipl' = 'Get-IISParsedLog' 'gis' = 'Get-InstalledSoftware' 'giwp' = 'Get-IISWorkerProcess' 'glf' = 'Get-LogonFailure' 'glp' = 'Get-ListeningPort' 'gna' = 'Get-NetworkAdapter' 'gnc' = 'Get-NTPConfiguration' 'gnci' = 'Get-NetworkCIDR' 'gnco' = 'Get-NetworkConnection' 'gnp' = 'Get-NTPPeer' 'gnr' = 'Get-NetworkRoute' 'gns' = 'Get-NetworkStatistic' 'gnss' = 'Get-NTPSyncStatus' 'gpbp' = 'Get-ProcessByPort' 'gpc' = 'Get-ProxyConfiguration' 'gpce' = 'Get-ProcessCrashEvent' 'gpfc' = 'Get-PageFileConfiguration' 'gpia' = 'Get-PublicIPAddress' 'gpr' = 'Get-PendingReboot' 'gpsh' = 'Get-PrintServerHealth' 'grh' = 'Get-RDSHealth' 'grhi' = 'Get-RebootHistory' 'grs' = 'Get-RdpSession' 'grsh' = 'Get-RdpSessionHistory' 'grsl' = 'Get-RdpSessionLock' 'gsa' = 'Get-ServiceAccount' 'gsc' = 'Get-SSLCertificate' 'gsce' = 'Get-ServiceCrashEvent' 'gsco' = 'Get-ShadowCopy' 'gscs' = 'Get-ShadowCopyStorage' 'gse' = 'Get-SchannelError' 'gsh' = 'Get-ServiceHealth' 'gsi' = 'Get-SubnetInfo' 'gsp' = 'Get-StartupProgram' 'gss' = 'Get-SystemSummary' 'gstd' = 'Get-ScheduledTaskDetail' 'gstf' = 'Get-ScheduledTaskFailure' 'gus' = 'Get-UnexpectedShutdown' 'gwh' = 'Get-WSUSHealth' 'gwu' = 'Get-WindowsUpdate' 'gwuc' = 'Get-WindowsUpdateConfiguration' 'gwuf' = 'Get-WindowsUpdateFailure' 'gwuh' = 'Get-WindowsUpdateHistory' 'hwu' = 'Hide-WindowsUpdate' 'iasa' = 'Invoke-ADSecurityAudit' 'inswu' = 'Install-WindowsUpdate' 'mnl' = 'Measure-NetworkLatency' 'nnr' = 'New-NetworkRoute' 'nrp' = 'New-RandomPassword' 'nsc' = 'New-ShadowCopy' 'restscf' = 'Restore-ShadowCopyFile' 'rnr' = 'Remove-NetworkRoute' 'rpc' = 'Remove-ProxyConfiguration' 'rrs' = 'Remove-RdpSession' 'rsc' = 'Remove-ShadowCopy' 'rsd' = 'Remove-StringDiacritic' 'rslvmv' = 'Resolve-MACVendor' 'rstaup' = 'Reset-ADUserPassword' 'rstns' = 'Reset-NetworkStack' 'rstwuc' = 'Reset-WindowsUpdateComponent' 'rup' = 'Remove-UserProfile' 'seao' = 'Search-ADObject' 'sev' = 'Set-EnvironmentVariable' 'shnsm' = 'Show-NetworkStatisticMonitor' 'shpm' = 'Show-PingMonitor' 'shsm' = 'Show-SystemMonitor' 'shwu' = 'Show-WindowsUpdate' 'sibc' = 'Set-IISBindingCertificate' 'snc' = 'Set-NTPClient' 'snr' = 'Set-NetworkRoute' 'spc' = 'Set-ProxyConfiguration' 'spf' = 'Set-PageFile' 'sscs' = 'Set-ShadowCopyStorage' 'stppt' = 'Stop-ProcessTree' 'svwu' = 'Save-WindowsUpdate' 'synt' = 'Sync-NTPTime' 'tdr' = 'Test-DNSResolution' 'tibc' = 'Test-IISBindingCertificate' 'tpc' = 'Test-PortConnectivity' 'tpco' = 'Test-ProxyConnection' 'trnr' = 'Trace-NetworkRoute' 'twr' = 'Test-WinRM' 'ulaua' = 'Unlock-ADUserAccount' 'unswu' = 'Uninstall-WindowsUpdate' 'wil' = 'Watch-IISLog' } foreach ($aliasName in $script:AliasMap.Keys) { Set-Alias -Name $aliasName -Value $script:AliasMap[$aliasName] -Scope Global } # ============================================================ # Argument completers for Active Directory Identity parameters # ============================================================ # Each completer queries AD live, respects Server/Credential already # typed on the command line, limits to 20 results, and silently # returns nothing when the AD module is unavailable. $script:ADUserCompleter = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $null = $commandName, $parameterName, $commandAst try { # Sanitize user-typed text to prevent LDAP filter injection / wildcard explosion. $safe = ($wordToComplete -as [string]) -replace '[\\\(\)\*\x00'']', '' if ([string]::IsNullOrWhiteSpace($safe)) { return } $splat = @{ Filter = "SamAccountName -like '$safe*'" Properties = @('DisplayName') ResultSetSize = 20 ErrorAction = 'Stop' } if ($fakeBoundParameters.ContainsKey('Server')) { $splat['Server'] = $fakeBoundParameters['Server'] } if ($fakeBoundParameters.ContainsKey('Credential')) { $splat['Credential'] = $fakeBoundParameters['Credential'] } Get-ADUser @splat | Sort-Object -Property 'SamAccountName' | ForEach-Object { $toolTip = if ($_.DisplayName) { "$($_.SamAccountName) ($($_.DisplayName))" } else { $_.SamAccountName } [System.Management.Automation.CompletionResult]::new( $_.SamAccountName, $_.SamAccountName, [System.Management.Automation.CompletionResultType]::ParameterValue, $toolTip ) } } catch { Write-Verbose -Message "AD user completer unavailable: $_" } } $script:ADComputerCompleter = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $null = $commandName, $parameterName, $commandAst try { # Sanitize user-typed text to prevent LDAP filter injection / wildcard explosion. $safe = ($wordToComplete -as [string]) -replace '[\\\(\)\*\x00'']', '' if ([string]::IsNullOrWhiteSpace($safe)) { return } $splat = @{ Filter = "Name -like '$safe*'" ResultSetSize = 20 ErrorAction = 'Stop' } if ($fakeBoundParameters.ContainsKey('Server')) { $splat['Server'] = $fakeBoundParameters['Server'] } if ($fakeBoundParameters.ContainsKey('Credential')) { $splat['Credential'] = $fakeBoundParameters['Credential'] } Get-ADComputer @splat | Sort-Object -Property 'Name' | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, "$($_.Name) ($($_.DistinguishedName))" ) } } catch { Write-Verbose -Message "AD computer completer unavailable: $_" } } $script:ADGroupCompleter = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $null = $commandName, $parameterName, $commandAst try { # Sanitize user-typed text to prevent LDAP filter injection / wildcard explosion. $safe = ($wordToComplete -as [string]) -replace '[\\\(\)\*\x00'']', '' if ([string]::IsNullOrWhiteSpace($safe)) { return } $splat = @{ Filter = "Name -like '$safe*'" ResultSetSize = 20 ErrorAction = 'Stop' } if ($fakeBoundParameters.ContainsKey('Server')) { $splat['Server'] = $fakeBoundParameters['Server'] } if ($fakeBoundParameters.ContainsKey('Credential')) { $splat['Credential'] = $fakeBoundParameters['Credential'] } Get-ADGroup @splat | Sort-Object -Property 'Name' | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, "$($_.Name) ($($_.GroupScope)/$($_.GroupCategory))" ) } } catch { Write-Verbose -Message "AD group completer unavailable: $_" } } # Register user completers $userFunctions = @( 'Disable-ADUserAccount' 'Enable-ADUserAccount' 'Get-ADNestedGroupMembership' 'Get-ADUserDetail' 'Get-ADUserGroupInventory' 'Reset-ADUserPassword' 'Unlock-ADUserAccount' ) foreach ($fn in $userFunctions) { Register-ArgumentCompleter -CommandName $fn -ParameterName 'Identity' -ScriptBlock $script:ADUserCompleter } # Register computer completer Register-ArgumentCompleter -CommandName 'Get-ADComputerDetail' -ParameterName 'Identity' -ScriptBlock $script:ADComputerCompleter # Register group completer Register-ArgumentCompleter -CommandName 'Get-ADGroupMembership' -ParameterName 'Identity' -ScriptBlock $script:ADGroupCompleter Write-Verbose "[$($MyInvocation.MyCommand)] PSWinOps module loaded successfully" |