UsefulArgumentCompleters.psm1
using namespace System using namespace System.Collections.Generic using namespace System.Management.Automation using namespace System.Management.Automation.Language class CompletionHelper { # Chars that PowerShell treats as quote chars hidden static [char[]] $QuoteChars = [char[]]@( [char]"'" [char]'"' [char]0x2018 # left single quotation mark [char]0x2019 # right single quotation mark [char]0x201a # single low-9 quotation mark [char]0x201b # single high-reversed-9 quotation mark [char]0x201c # left double quotation mark [char]0x201d # right double quotation mark [char]0x201E # low double left quote used in german. ) # Chars that cannot be used at the start of a barequote string hidden static [char[]] $BadStartChars = [char[]]@( [char]'<' [char]'>' [char]'#' [char]'&' [char]'-' [char]0x2013 # EnDash [char]0x2014 # EmDash [char]0x2015 # HorizontalBar ) # Chars that cause issues when used anywhere in a barequote string hidden static [char[]] $BadChars = [char[]]@( [char]'$' [char]'`' # Backtick [char]' ' # Space [char]'"' [char]',' [char]';' [char]'(' [char]')' [char]'{' [char]'}' [CompletionHelper]::QuoteChars ) # Cache for saving expensive or static object collections used for completions hidden static [Dictionary[string,Object[]]] $ObjectCache = ([Dictionary[string,Object[]]]::new([System.StringComparer]::OrdinalIgnoreCase)) static [string] AddQuotesIfNeeded([string] $CompletionText) { $Result = if ($CompletionText.Contains("'")) { "'$($CompletionText.Replace("'","''"))'" } elseif ($CompletionText.IndexOfAny([CompletionHelper]::BadStartChars) -eq 0 -or $CompletionText.IndexOfAny([CompletionHelper]::BadChars) -ne -1) { "'$CompletionText'" } else { $CompletionText } return $Result } static [string] TrimQuotes([string] $Text) { return $Text.Trim([CompletionHelper]::QuoteChars) } static [CompletionResult] NewParamCompletionResult([string] $Text) { return [CompletionResult]::new( [CompletionHelper]::AddQuotesIfNeeded($Text), $Text, [CompletionResultType]::ParameterValue, $Text ) } static [CompletionResult] NewParamCompletionResult([string] $Text, [string]$ToolTip) { return [CompletionResult]::new( [CompletionHelper]::AddQuotesIfNeeded($Text), $Text, [CompletionResultType]::ParameterValue, $ToolTip ) } # Validates that the string is a valid PowerShell command with no nested expressions hidden static [bool] CommandIsSafe([string] $Command) { $ParsedTokens = $null $Errors = $null $null = [Parser]::ParseInput($Command, [ref]$ParsedTokens, [ref]$Errors) if ($Errors.Count -gt 0) { return $false } foreach ($Token in $ParsedTokens) { if ( $Token -isnot [StringLiteralToken] -and $Token -isnot [ParameterToken] -and $Token.Kind -ne [TokenKind]::EndOfInput -and $Token.Kind -ne [TokenKind]::Identifier ) { return $false } } return $true } static [Object[]] GetCachedResults([string] $Command, [bool] $ValidateInput) { $Result = $null if ([CompletionHelper]::ObjectCache.TryGetValue($Command, [ref] $Result)) { return $Result } $Result = if (!$ValidateInput -or [CompletionHelper]::CommandIsSafe($Command)) { try { Invoke-Expression -Command $Command } catch { return $null } } else { return $null } [CompletionHelper]::ObjectCache.Add($Command, $Result) return $Result } } Register-ArgumentCompleter -CommandName Get-ADUser,Get-ADComputer,Get-ADGroup,Get-ADOrganizationalUnit,Get-ADServiceAccount,Get-ADReplicationSite -ParameterName Properties -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $Values = @{ 'Get-ADUser' = @( 'AccountExpirationDate' 'accountExpires' 'AccountLockoutTime' 'AccountNotDelegated' 'adminCount' 'AllowReversiblePasswordEncryption' 'AuthenticationPolicy' 'AuthenticationPolicySilo' 'BadLogonCount' 'badPasswordTime' 'badPwdCount' 'c' 'CannotChangePassword' 'CanonicalName' 'Certificates' 'City' 'CN' 'co' 'codePage' 'Company' 'CompoundIdentitySupported' 'Country' 'countryCode' 'Created' 'createTimeStamp' 'Deleted' 'Department' 'Description' 'DisplayName' 'DistinguishedName' 'Division' 'DoesNotRequirePreAuth' 'dSCorePropagationData' 'EmailAddress' 'EmployeeID' 'EmployeeNumber' 'Enabled' 'Fax' 'garbageCollPeriod' 'GivenName' 'HomeDirectory' 'HomedirRequired' 'HomeDrive' 'HomePage' 'HomePhone' 'Initials' 'instanceType' 'internetEncoding' 'isDeleted' 'KerberosEncryptionType' 'l' 'LastBadPasswordAttempt' 'LastKnownParent' 'lastLogoff' 'lastLogon' 'LastLogonDate' 'lastLogonTimestamp' 'legacyExchangeDN' 'LockedOut' 'lockoutTime' 'logonCount' 'LogonWorkstations' 'mail' 'mailNickname' 'Manager' 'MemberOf' 'MNSLogonAccount' 'mobile' 'MobilePhone' 'Modified' 'modifyTimeStamp' 'mS-DS-ConsistencyGuid' 'msDS-ExternalDirectoryObjectId' 'msDS-KeyCredentialLink' 'msDS-User-Account-Control-Computed' 'msExchAddressBookFlags' 'msExchArchiveQuota' 'msExchArchiveWarnQuota' 'msExchBypassAudit' 'msExchCalendarLoggingQuota' 'msExchDumpsterQuota' 'msExchDumpsterWarningQuota' 'msExchGroupSecurityFlags' 'msExchMailboxAuditEnable' 'msExchMailboxAuditLogAgeLimit' 'msExchMailboxFolderSet' 'msExchMDBRulesQuota' 'msExchModerationFlags' 'msExchPoliciesIncluded' 'msExchProvisioningFlags' 'msExchRecipientDisplayType' 'msExchRecipientSoftDeletedStatus' 'msExchRecipientTypeDetails' 'msExchRemoteRecipientType' 'msExchSafeSendersHash' 'msExchTransportRecipientSettingsFlags' 'msExchUMDtmfMap' 'msExchUMEnabledFlags2' 'msExchUserAccountControl' 'msExchVersion' 'msRTCSIP-DeploymentLocator' 'msRTCSIP-FederationEnabled' 'msRTCSIP-InternetAccessEnabled' 'msRTCSIP-Line' 'msRTCSIP-OptionFlags' 'msRTCSIP-PrimaryUserAddress' 'msRTCSIP-UserEnabled' 'msTSExpireDate' 'msTSLicenseVersion' 'msTSLicenseVersion2' 'msTSLicenseVersion3' 'msTSManagingLS' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'objectSid' 'Office' 'OfficePhone' 'Organization' 'OtherName' 'PasswordExpired' 'PasswordLastSet' 'PasswordNeverExpires' 'PasswordNotRequired' 'physicalDeliveryOfficeName' 'POBox' 'PostalCode' 'PrimaryGroup' 'primaryGroupID' 'PrincipalsAllowedToDelegateToAccount' 'ProfilePath' 'ProtectedFromAccidentalDeletion' 'protocolSettings' 'proxyAddresses' 'pwdLastSet' 'SamAccountName' 'sAMAccountType' 'ScriptPath' 'sDRightsEffective' 'ServicePrincipalNames' 'showInAddressBook' 'SID' 'SIDHistory' 'SmartcardLogonRequired' 'sn' 'State' 'StreetAddress' 'Surname' 'targetAddress' 'telephoneNumber' 'Title' 'TrustedForDelegation' 'TrustedToAuthForDelegation' 'UseDESKeyOnly' 'userAccountControl' 'userCertificate' 'UserPrincipalName' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) 'Get-ADComputer' = @( 'AccountExpirationDate' 'accountExpires' 'AccountLockoutTime' 'AccountNotDelegated' 'AllowReversiblePasswordEncryption' 'AuthenticationPolicy' 'AuthenticationPolicySilo' 'BadLogonCount' 'badPasswordTime' 'badPwdCount' 'CannotChangePassword' 'CanonicalName' 'Certificates' 'CN' 'codePage' 'CompoundIdentitySupported' 'countryCode' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' 'DNSHostName' 'DoesNotRequirePreAuth' 'dSCorePropagationData' 'Enabled' 'HomedirRequired' 'HomePage' 'instanceType' 'IPv4Address' 'IPv6Address' 'isCriticalSystemObject' 'isDeleted' 'KerberosEncryptionType' 'LastBadPasswordAttempt' 'LastKnownParent' 'lastLogoff' 'lastLogon' 'LastLogonDate' 'lastLogonTimestamp' 'localPolicyFlags' 'Location' 'LockedOut' 'logonCount' 'ManagedBy' 'MemberOf' 'MNSLogonAccount' 'Modified' 'modifyTimeStamp' 'ms-Mcs-AdmPwdExpirationTime' 'msDS-SupportedEncryptionTypes' 'msDS-User-Account-Control-Computed' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'objectSid' 'OperatingSystem' 'OperatingSystemHotfix' 'OperatingSystemServicePack' 'OperatingSystemVersion' 'PasswordExpired' 'PasswordLastSet' 'PasswordNeverExpires' 'PasswordNotRequired' 'PrimaryGroup' 'primaryGroupID' 'PrincipalsAllowedToDelegateToAccount' 'ProtectedFromAccidentalDeletion' 'PSShowComputerName' 'pwdLastSet' 'SamAccountName' 'sAMAccountType' 'sDRightsEffective' 'ServiceAccount' 'servicePrincipalName' 'ServicePrincipalNames' 'SID' 'SIDHistory' 'TrustedForDelegation' 'TrustedToAuthForDelegation' 'UseDESKeyOnly' 'userAccountControl' 'userCertificate' 'UserPrincipalName' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) 'Get-ADGroup' = @( 'adminCount' 'CanonicalName' 'CN' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' 'dSCorePropagationData' 'GroupCategory' 'GroupScope' 'groupType' 'HomePage' 'instanceType' 'isCriticalSystemObject' 'isDeleted' 'LastKnownParent' 'ManagedBy' 'member' 'MemberOf' 'Members' 'Modified' 'modifyTimeStamp' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'objectSid' 'ProtectedFromAccidentalDeletion' 'SamAccountName' 'sAMAccountType' 'sDRightsEffective' 'SID' 'SIDHistory' 'systemFlags' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) 'Get-ADOrganizationalUnit' = @( 'CanonicalName' 'City' 'CN' 'Country' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' 'dSCorePropagationData' 'instanceType' 'isDeleted' 'LastKnownParent' 'LinkedGroupPolicyObjects' 'ManagedBy' 'Modified' 'modifyTimeStamp' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'ou' 'PostalCode' 'ProtectedFromAccidentalDeletion' 'sDRightsEffective' 'State' 'StreetAddress' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) 'Get-ADServiceAccount' = @( 'AccountExpirationDate' 'accountExpires' 'AccountLockoutTime' 'AccountNotDelegated' 'AllowReversiblePasswordEncryption' 'AuthenticationPolicy' 'AuthenticationPolicySilo' 'BadLogonCount' 'badPasswordTime' 'badPwdCount' 'CannotChangePassword' 'CanonicalName' 'Certificates' 'CN' 'codePage' 'CompoundIdentitySupported' 'countryCode' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' 'DNSHostName' 'DoesNotRequirePreAuth' 'dSCorePropagationData' 'Enabled' 'HomedirRequired' 'HomePage' 'HostComputers' 'instanceType' 'isCriticalSystemObject' 'isDeleted' 'KerberosEncryptionType' 'LastBadPasswordAttempt' 'LastKnownParent' 'lastLogoff' 'lastLogon' 'LastLogonDate' 'lastLogonTimestamp' 'localPolicyFlags' 'LockedOut' 'logonCount' 'ManagedPasswordIntervalInDays' 'MemberOf' 'MNSLogonAccount' 'Modified' 'modifyTimeStamp' 'msDS-GroupMSAMembership' 'msDS-ManagedPasswordId' 'msDS-ManagedPasswordInterval' 'msDS-ManagedPasswordPreviousId' 'msDS-SupportedEncryptionTypes' 'msDS-User-Account-Control-Computed' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'objectSid' 'PasswordExpired' 'PasswordLastSet' 'PasswordNeverExpires' 'PasswordNotRequired' 'PrimaryGroup' 'primaryGroupID' 'PrincipalsAllowedToDelegateToAccount' 'PrincipalsAllowedToRetrieveManagedPassword' 'ProtectedFromAccidentalDeletion' 'pwdLastSet' 'SamAccountName' 'sAMAccountType' 'sDRightsEffective' 'ServicePrincipalNames' 'SID' 'SIDHistory' 'TrustedForDelegation' 'TrustedToAuthForDelegation' 'UseDESKeyOnly' 'userAccountControl' 'userCertificate' 'UserPrincipalName' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) 'Get-ADReplicationSite' = @( 'AutomaticInterSiteTopologyGenerationEnabled' 'AutomaticTopologyGenerationEnabled' 'CanonicalName' 'CN' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' 'dSCorePropagationData' 'instanceType' 'InterSiteTopologyGenerator' 'isDeleted' 'LastKnownParent' 'ManagedBy' 'Modified' 'modifyTimeStamp' 'msExchServerSiteBL' 'Name' 'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'ProtectedFromAccidentalDeletion' 'RedundantServerTopologyEnabled' 'ReplicationSchedule' 'ScheduleHashingEnabled' 'sDRightsEffective' 'showInAdvancedViewOnly' 'Subnets' 'systemFlags' 'TopologyCleanupEnabled' 'TopologyDetectStaleEnabled' 'TopologyMinimumHopsEnabled' 'UniversalGroupCachingEnabled' 'UniversalGroupCachingRefreshSite' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' 'WindowsServer2000BridgeheadSelectionMethodEnabled' 'WindowsServer2000KCCISTGSelectionBehaviorEnabled' 'WindowsServer2003KCCBehaviorEnabled' 'WindowsServer2003KCCIgnoreScheduleEnabled' 'WindowsServer2003KCCSiteLinkBridgingEnabled' ) } $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $Values[$commandName]) { if ($Item.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Item) } } } Register-ArgumentCompleter -CommandName Get-ComputerInfo -ParameterName Property -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Property in [Microsoft.PowerShell.Commands.ComputerInfo].GetProperties() | Sort-Object -Property Name) { if ($Property.Name.StartsWith($TrimmedWord, [System.StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Property.Name) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Culture in [CompletionHelper]::GetCachedResults('[cultureinfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures)', $false)) { if ($null -eq $Culture) { continue } if ($Culture.Name -eq [string]::Empty -and $Culture.DisplayName.StartsWith($TrimmedWord)) { if ($commandName -in 'Get-InstalledLanguage','Install-Language','Set-SystemPreferredUILanguage','Uninstall-Language') { continue } [CompletionResult]::new( "''", $Culture.DisplayName, [CompletionResultType]::ParameterValue, $Culture.DisplayName ) continue } if ($Culture.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Culture.Name, $Culture.DisplayName) } } } Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName UICulture -CommandName Update-Help,Save-Help,New-PSSessionOption Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Culture -CommandName New-PSSessionOption Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Language -CommandName Set-WinUILanguageOverride,Get-InstalledLanguage,Install-Language,Set-SystemPreferredUILanguage,Uninstall-Language Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName SystemLocale -CommandName Set-WinSystemLocale Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName CultureInfo -CommandName Set-Culture Register-ArgumentCompleter -CommandName Disconnect-VIServer -ParameterName Server -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $global:DefaultVIServers.Name) { if ($Item.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Item) } } } Register-ArgumentCompleter -CommandName @( 'Copy-NetFirewallRule' 'Copy-NetIPsecMainModeCryptoSet' 'Copy-NetIPsecMainModeRule' 'Copy-NetIPsecPhase1AuthSet' 'Copy-NetIPsecPhase2AuthSet' 'Copy-NetIPsecQuickModeCryptoSet' 'Copy-NetIPsecRule' 'Disable-NetFirewallRule' 'Disable-NetIPsecMainModeRule' 'Disable-NetIPsecRule' 'Enable-NetFirewallRule' 'Enable-NetIPsecMainModeRule' 'Enable-NetIPsecRule' 'Get-NetFirewallAddressFilter' 'Get-NetFirewallApplicationFilter' 'Get-NetFirewallDynamicKeywordAddress' 'Get-NetFirewallInterfaceFilter' 'Get-NetFirewallInterfaceTypeFilter' 'Get-NetFirewallPortFilter' 'Get-NetFirewallProfile' 'Get-NetFirewallRule' 'Get-NetFirewallSecurityFilter' 'Get-NetFirewallServiceFilter' 'Get-NetFirewallSetting' 'Get-NetIPsecMainModeCryptoSet' 'Get-NetIPsecMainModeRule' 'Get-NetIPsecPhase1AuthSet' 'Get-NetIPsecPhase2AuthSet' 'Get-NetIPsecQuickModeCryptoSet' 'Get-NetIPsecRule' 'New-NetFirewallRule' 'New-NetIPsecMainModeCryptoSet' 'New-NetIPsecMainModeRule' 'New-NetIPsecPhase1AuthSet' 'New-NetIPsecPhase2AuthSet' 'New-NetIPsecQuickModeCryptoSet' 'New-NetIPsecRule' 'Open-NetGPO' 'Remove-NetFirewallDynamicKeywordAddress' 'Remove-NetFirewallRule' 'Remove-NetIPsecMainModeCryptoSet' 'Remove-NetIPsecMainModeRule' 'Remove-NetIPsecPhase1AuthSet' 'Remove-NetIPsecPhase2AuthSet' 'Remove-NetIPsecQuickModeCryptoSet' 'Remove-NetIPsecRule' 'Rename-NetFirewallRule' 'Rename-NetIPsecMainModeCryptoSet' 'Rename-NetIPsecMainModeRule' 'Rename-NetIPsecPhase1AuthSet' 'Rename-NetIPsecPhase2AuthSet' 'Rename-NetIPsecQuickModeCryptoSet' 'Rename-NetIPsecRule' 'Set-NetFirewallAddressFilter' 'Set-NetFirewallApplicationFilter' 'Set-NetFirewallInterfaceFilter' 'Set-NetFirewallInterfaceTypeFilter' 'Set-NetFirewallPortFilter' 'Set-NetFirewallProfile' 'Set-NetFirewallRule' 'Set-NetFirewallSecurityFilter' 'Set-NetFirewallServiceFilter' 'Set-NetFirewallSetting' 'Set-NetIPsecMainModeCryptoSet' 'Set-NetIPsecMainModeRule' 'Set-NetIPsecPhase1AuthSet' 'Set-NetIPsecPhase2AuthSet' 'Set-NetIPsecQuickModeCryptoSet' 'Set-NetIPsecRule' 'Show-NetFirewallRule' 'Show-NetIPsecRule' 'Sync-NetIPsecRule' 'Update-NetIPsecRule' 'Get-DAPolicyChange' ) -ParameterName PolicyStore -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $ValidValues = @( if ($commandName -ne "Open-NetGPO") { 'PersistentStore' 'ActiveStore' 'RSOP' 'SystemDefaults' 'StaticServiceStore' 'ConfigurableServiceStore' } [CompletionHelper]::GetCachedResults('Get-GPO -All', $false) ) foreach ($PolicyStore in $ValidValues) { if ($null -eq $PolicyStore) { continue } $PolicyStoreName = if ($PolicyStore -is [string]) { $PolicyStore } else { "$($PolicyStore.DomainName)\$($PolicyStore.DisplayName)" } if ($PolicyStoreName.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($PolicyStoreName) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $KnownPorts = @( @{Name="Any" ;Value="Any" ;ToolTip='Any port'} @{Name="RPC" ;Value="RPC" ;ToolTip='TCP port 49152-65535. RPC dynamic port range.'} @{Name="RPCEPMap" ;Value="RPCEPMap" ;ToolTip='TCP Port 135. RPC Endpoint mapper.'} if ($parameterName -eq "LocalPort") { @{Name="PlayToDiscovery" ;Value="PlayToDiscovery" ;ToolTip='PlayToDiscovery'} @{Name="Teredo" ;Value="Teredo" ;ToolTip='Teredo'} @{Name="IPHTTPSIn" ;Value="IPHTTPSIn" ;ToolTip='IPHTTPSIn'} @{Name="IPHTTPSOut" ;Value="IPHTTPSOut" ;ToolTip='IPHTTPSOut'} } else { @{Name="IPHTTPS" ;Value="IPHTTPS" ;ToolTip='IPHTTPS'} } @{Name="FTPData" ;Value="20" ;ToolTip='TCP Port 20. FTP (File Transfer Protocol) data transfer.'} @{Name="FTPControl" ;Value="21" ;ToolTip='TCP Port 21. FTP (File Transfer Protocol) control.'} @{Name="SSH" ;Value="22" ;ToolTip='TCP port 22. SSH (Secure Shell).'} @{Name="SCP" ;Value="22" ;ToolTip='TCP port 22. SCP (Secure Copy).'} #Obviously it's the same as SSH, but it's more convenient to have multiple text options. @{Name="SFTP_SSH" ;Value="22" ;ToolTip='TCP port 22. SFTP (SSH File Transfer Protocol).'} @{Name="Telnet" ;Value="23" ;ToolTip='TCP port 23. Telnet.'} @{Name="SMTP" ;Value="25" ;ToolTip='TCP port 25. SMTP (Simple Mail Transfer Protocol).'} @{Name="DNS" ;Value="53" ;ToolTip='TCP and UDP port 53. DNS (Domain Name System)'} @{Name="DHCPServer" ;Value="67" ;ToolTip='UDP port 67. DHCP (Dynamic Host Configuration Protocol) server port'} @{Name="DHCPClient" ;Value="68" ;ToolTip='UDP port 68. DHCP (Dynamic Host Configuration Protocol) client port'} @{Name="TFTP" ;Value="69" ;ToolTip='UDP port 69. TFTP (Trivial File Transfer Protocol)'} @{Name="HTTP" ;Value="80" ;ToolTip='TCP and UDP port 80. HTTP (Hypertext Transfer Protocol)'} @{Name="Kerberos" ;Value="88" ;ToolTip='TCP and UDP port 88. Kerberos authentication.'} @{Name="SFTP" ;Value="115" ;ToolTip='TCP port 115. SFTP (Simple File Transfer Protocol)'} @{Name="NTP" ;Value="123" ;ToolTip='UDP port 123. NTP (Network Time Protocol)'} @{Name="NetBiosNameService" ;Value="137" ;ToolTip='TCP and UDP port 137. Netbios name registration and resolution.'} @{Name="NetBiosDatagramService" ;Value="138" ;ToolTip='UDP port 138. Netbios datagram service.'} @{Name="NetBiosSessionService" ;Value="139" ;ToolTip='TCP port 139. Netbios session service.'} @{Name="IMAP" ;Value="143" ;ToolTip='TCP port 143. IMAP (Internet Message Access Protocol).'} @{Name="SNMP" ;Value="161" ;ToolTip='UDP port 161. SNMP (Simple Network Management Protocol)'} @{Name="SNMPTrap" ;Value="162" ;ToolTip='TCP and UDP port 162. SNMP (Simple Network Management Protocol) trap'} @{Name="LDAP" ;Value="389" ;ToolTip='TCP port 389. LDAP (Lightweight Directory Access Protocol)'} @{Name="HTTPS" ;Value="443" ;ToolTip='TCP and UDP port 443. HTTPS (Hypertext Transfer Protocol Secure)'} @{Name="SMB" ;Value="445" ;ToolTip='TCP and UDP port 445. SMB (Server Message Block)'} @{Name="KerberosSetPassword" ;Value="464" ;ToolTip='TCP and UDP port 464. Kerberos update password.'} @{Name="LDAPS" ;Value="636" ;ToolTip='TCP port 636. LDAPS (Lightweight Directory Access Protocol over TLS/SSL)'} @{Name="IMAPS" ;Value="993" ;ToolTip='TCP port 993. IMAPS (Internet Message Access Protocol over TLS/SSL)'} @{Name="MSSQL" ;Value="1433" ;ToolTip='TCP and UDP port 1433. Default instance MS SQL server port.'} @{Name="KMS" ;Value="1688" ;ToolTip='TCP port 1688. Default KMS (Key management service) port.'} @{Name="LDAPGC" ;Value="3268" ;ToolTip='TCP and UDP port 3268. LDAP global catalog.'} @{Name="LDAPSGC" ;Value="3269" ;ToolTip='TCP and UDP port 3269. LDAPS global catalog.'} @{Name="RDP" ;Value="3389" ;ToolTip='TCP and UDP port 3389. Default RDP port.'} @{Name="WinRM" ;Value="5985" ;ToolTip='TCP port 5985. Default WinRM port.'} @{Name="WinRMHttps" ;Value="5986" ;ToolTip='TCP port 5986. Default WinRM HTTPs port.'} ) foreach ($Port in $KnownPorts) { if ($Port['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $Port['Value'], $Port['Name'], [CompletionResultType]::ParameterValue, $Port['ToolTip'] ) } } } $Commands = @( 'Find-NetIPsecRule' 'New-NetFirewallRule' 'New-NetIPsecRule' 'Set-NetFirewallPortFilter' 'Set-NetFirewallRule' 'Set-NetIPsecRule' ) Register-ArgumentCompleter -CommandName $Commands -ParameterName LocalPort -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName $Commands -ParameterName RemotePort -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName @( 'Find-NetIPsecRule' 'Get-NetFirewallPortFilter' 'New-NetFirewallRule' 'New-NetIPsecRule' 'Set-NetFirewallPortFilter' 'Set-NetFirewallRule' 'Set-NetIPsecRule' ) -ParameterName Protocol -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $KnownProtocols = @( @{Name="Any"; Value="Any"} @{Name="TCP"; Value="TCP"} @{Name="UDP"; Value="UDP"} @{Name="ICMPv4"; Value="ICMPv4"} @{Name="ICMPv6"; Value="ICMPv6"} @{Name="HOPOPT"; Value="0"} @{Name="IGMP"; Value="2"} @{Name="IPv6"; Value="41"} @{Name="IPv6-Route"; Value="43"} @{Name="IPv6-Frag"; Value="44"} @{Name="GRE"; Value="47"} @{Name="IPv6-NoNxt"; Value="59"} @{Name="IPv6-Opts"; Value="60"} @{Name="VRRP"; Value="112"} @{Name="PGM"; Value="113"} @{Name="L2TP"; Value="115"} ) foreach ($Protocol in $KnownProtocols) { if ($Protocol['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $Protocol['Value'], $Protocol['Name'], [CompletionResultType]::ParameterValue, $Protocol['Value'] ) } } } Register-ArgumentCompleter -CommandName @( 'Get-NetFirewallServiceFilter' 'New-NetFirewallRule' 'Set-NetFirewallRule' 'Set-NetFirewallServiceFilter' ) -ParameterName Service -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) if ("Any".StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult("Any") } foreach ($Service in [CompletionHelper]::GetCachedResults('Get-Service', $false)) { if ($null -eq $Service) { continue } if ($Service.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Service.Name, $Service.DisplayName) } } } Register-ArgumentCompleter -CommandName Set-WinHomeLocation -ParameterName GeoId -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $AllRegions = [CompletionHelper]::GetCachedResults(@' foreach ($Culture in [cultureinfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures)) { if ($Culture.IsNeutralCulture -or $Culture.Name -eq "") { continue } [System.Globalization.RegionInfo]::new($Culture.Name) } '@, $false) foreach ($RegionInfo in $AllRegions) { if ($null -eq $RegionInfo) { continue } if ($RegionInfo.EnglishName.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $RegionInfo.GeoId, $RegionInfo.EnglishName, [CompletionResultType]::ParameterValue, $RegionInfo.EnglishName ) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $Values = switch ($parameterName) { 'LocalAddress' { Get-NetTCPConnection -LocalAddress "$TrimmedWord*" | Select-Object -ExpandProperty LocalAddress | Sort-Object -Unique break } 'RemoteAddress' { Get-NetTCPConnection -RemoteAddress "$TrimmedWord*" | Select-Object -ExpandProperty RemoteAddress | Sort-Object -Unique break } 'LocalPort' { Get-NetTCPConnection | Select-Object -ExpandProperty LocalPort | Sort-Object -Unique break } 'RemotePort' { Get-NetTCPConnection | Select-Object -ExpandProperty RemotePort | Sort-Object -Unique break } } foreach ($Value in $Values) { if ($Value -like "$wordToComplete*") { [CompletionHelper]::NewParamCompletionResult($Value) } } } Register-ArgumentCompleter -ScriptBlock $ScriptBlock -CommandName Get-NetTCPConnection -ParameterName LocalAddress Register-ArgumentCompleter -ScriptBlock $ScriptBlock -CommandName Get-NetTCPConnection -ParameterName RemoteAddress Register-ArgumentCompleter -ScriptBlock $ScriptBlock -CommandName Get-NetTCPConnection -ParameterName LocalPort Register-ArgumentCompleter -ScriptBlock $ScriptBlock -CommandName Get-NetTCPConnection -ParameterName RemotePort Register-ArgumentCompleter -CommandName Get-NetTCPConnection -ParameterName OwningProcess -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Process in Get-Process -Name "$TrimmedWord*") { $ListItem = "$($Process.Name) $($Process.Id)" if ($ListItem.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $Process.Id, $ListItem, [CompletionResultType]::ParameterValue, $ListItem ) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($TimeZone in [CompletionHelper]::GetCachedResults('Get-TimeZone -ListAvailable', $false)) { if ($null -eq $TimeZone) { continue } $MatchText = if ($parameterName -eq "Name") { $TimeZone.StandardName } else { $TimeZone.Id } if ($MatchText.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($MatchText, $TimeZone.DisplayName) } } } Register-ArgumentCompleter -CommandName Get-TimeZone -ParameterName Name -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName Get-TimeZone -ParameterName Id -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName New-ItemProperty -ParameterName PropertyType -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $ResolveArgument = if ($null -ne $fakeBoundParameters['Path']) { @{LiteralPath = $fakeBoundParameters['Path']} } elseif ($null -ne $fakeBoundParameters['LiteralPath']) { @{LiteralPath = $fakeBoundParameters['LiteralPath']} } else { @{Path = '.\'} } $Values = switch ((Resolve-Path @ResolveArgument | Select-Object -First 1).Provider.Name) { 'Registry' { @( @{Name = "String"; ToolTip = "A normal string."} @{Name = "ExpandString";ToolTip = "A string that contains unexpanded references to environment variables that are expanded when the value is retrieved."} @{Name = "Binary"; ToolTip = "Binary data in any form."} @{Name = "DWord"; ToolTip = "A 32-bit binary number."} @{Name = "MultiString"; ToolTip = "An array of strings."} @{Name = "Qword"; ToolTip = "A 64-bit binary number"} @{Name = "Unknown"; ToolTip = "An unsupported registry data type"} ) break } Default { return } } $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $Values) { if ($Item['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Item['Name'], $Item['ToolTip']) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($User in Get-LocalUser) { $MatchText = if ($parameterName -eq "Name") { $User.Name } else { $User.SID } if ($MatchText.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($MatchText, "$($User.Name) $($User.FullName)") } } } Register-ArgumentCompleter -CommandName Get-LocalUser,Set-LocalUser,Enable-LocalUser,Disable-LocalUser,Remove-LocalUser,Rename-LocalUser -ParameterName Name -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName Get-LocalUser,Set-LocalUser,Enable-LocalUser,Disable-LocalUser,Remove-LocalUser,Rename-LocalUser -ParameterName SID -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName Update-Module,Uninstall-Module -ParameterName Name -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Module in [CompletionHelper]::GetCachedResults('Get-Module -ListAvailable | Where-Object -Property RepositorySourceLocation -NE $null | Select-Object -ExpandProperty Name | Sort-Object -Unique', $false)) { if ($null -eq $Module) { continue } if ($Module.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Module) } } } Register-ArgumentCompleter -CommandName Find-Module,Install-Module,Save-Module -ParameterName Name -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Module in [CompletionHelper]::GetCachedResults("Import-Csv -Delimiter ',' -LiteralPath '$PSScriptRoot\PSGallery.csv'", $false)) { if ($null -eq $Module) { continue } if ($Module.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Module.Name, "CompanyName: $($Module.CompanyName)") } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Adapter in [CompletionHelper]::GetCachedResults("Get-NetAdapter", $false)) { if ($null -eq $Adapter) { continue } if ($Adapter.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Adapter.Name, $Adapter.InterfaceDescription) } } } Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName InterfaceAlias -CommandName @( 'Get-DnsClient' 'Get-DnsClientServerAddress' 'Get-NetConnectionProfile' 'Get-NetIPAddress' 'Get-NetIPConfiguration' 'Get-NetIPInterface' 'Get-NetNeighbor' 'Get-NetRoute' 'New-NetFirewallRule' 'New-NetIPAddress' 'New-NetIPsecRule' 'New-NetNeighbor' 'New-NetRoute' 'New-SmbMultichannelConstraint' 'Remove-NetIPAddress' 'Remove-NetNeighbor' 'Remove-NetRoute' 'Remove-SmbMultichannelConstraint' 'Set-DhcpServerv4Binding' 'Set-DhcpServerv6Binding' 'Set-DnsClient' 'Set-DnsClientServerAddress' 'Set-NetConnectionProfile' 'Set-NetFirewallInterfaceFilter' 'Set-NetFirewallRule' 'Set-NetIPAddress' 'Set-NetIPConfiguration' 'Set-NetIPInterface' 'Set-NetIPsecRule' 'Set-NetNeighbor' 'Set-NetRoute' ) Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Name -CommandName @( 'Add-NetLbfoTeamMember' 'Add-NetLbfoTeamNic' 'Disable-NetAdapter' 'Disable-NetAdapterBinding' 'Disable-NetAdapterChecksumOffload' 'Disable-NetAdapterEncapsulatedPacketTaskOffload' 'Disable-NetAdapterIPsecOffload' 'Disable-NetAdapterLso' 'Disable-NetAdapterPacketDirect' 'Disable-NetAdapterPowerManagement' 'Disable-NetAdapterQos' 'Disable-NetAdapterRdma' 'Disable-NetAdapterRsc' 'Disable-NetAdapterRss' 'Disable-NetAdapterSriov' 'Disable-NetAdapterUso' 'Disable-NetAdapterVmq' 'Enable-NetAdapter' 'Enable-NetAdapterBinding' 'Enable-NetAdapterChecksumOffload' 'Enable-NetAdapterEncapsulatedPacketTaskOffload' 'Enable-NetAdapterIPsecOffload' 'Enable-NetAdapterLso' 'Enable-NetAdapterPacketDirect' 'Enable-NetAdapterPowerManagement' 'Enable-NetAdapterQos' 'Enable-NetAdapterRdma' 'Enable-NetAdapterRsc' 'Enable-NetAdapterRss' 'Enable-NetAdapterSriov' 'Enable-NetAdapterUso' 'Enable-NetAdapterVmq' 'Get-NetAdapter' 'Get-NetAdapterAdvancedProperty' 'Get-NetAdapterBinding' 'Get-NetAdapterChecksumOffload' 'Get-NetAdapterEncapsulatedPacketTaskOffload' 'Get-NetAdapterHardwareInfo' 'Get-NetAdapterIPsecOffload' 'Get-NetAdapterLso' 'Get-NetAdapterPacketDirect' 'Get-NetAdapterPowerManagement' 'Get-NetAdapterQos' 'Get-NetAdapterRdma' 'Get-NetAdapterRsc' 'Get-NetAdapterRss' 'Get-NetAdapterSriov' 'Get-NetAdapterSriovVf' 'Get-NetAdapterStatistics' 'Get-NetAdapterUso' 'Get-NetAdapterVmq' 'Get-NetAdapterVmqQueue' 'Get-NetAdapterVPort' 'Get-NetLbfoTeamMember' 'Get-NetLbfoTeamNic' 'New-NetAdapterAdvancedProperty' 'Remove-NetAdapterAdvancedProperty' 'Remove-NetLbfoTeamMember' 'Rename-NetAdapter' 'Reset-NetAdapterAdvancedProperty' 'Restart-NetAdapter' 'Set-NetAdapter' 'Set-NetAdapterAdvancedProperty' 'Set-NetAdapterBinding' 'Set-NetAdapterChecksumOffload' 'Set-NetAdapterEncapsulatedPacketTaskOffload' 'Set-NetAdapterIPsecOffload' 'Set-NetAdapterLso' 'Set-NetAdapterPacketDirect' 'Set-NetAdapterPowerManagement' 'Set-NetAdapterQos' 'Set-NetAdapterRdma' 'Set-NetAdapterRsc' 'Set-NetAdapterRss' 'Set-NetAdapterSriov' 'Set-NetAdapterUso' 'Set-NetAdapterVmq' 'Set-NetLbfoTeamMember' 'Set-NetLbfoTeamNic' ) Register-ArgumentCompleter -CommandName New-Partition -ParameterName GptType -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $Types = @( @{Name = "Recovery"; Guid="{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"} @{Name = "EFI"; Guid="{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}"} @{Name = "MSR"; Guid="{e3c9e316-0b5c-4db8-817d-f92df00215ae}"} @{Name = "Basic"; Guid="{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}"} ) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $Types) { if ($Item['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( "'$($Item['Guid'])'", $Item['Name'], [CompletionResultType]::ParameterValue, $Item['Name'] ) } } } Register-ArgumentCompleter -CommandName Enable-WindowsOptionalFeature,Disable-WindowsOptionalFeature,Get-WindowsOptionalFeature -ParameterName FeatureName -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $FoundFeatures = if ($fakeBoundParameters["Path"]) { [CompletionHelper]::GetCachedResults("Get-WindowsOptionalFeature -Path '$($fakeBoundParameters['Path'])'", $true) } else { [CompletionHelper]::GetCachedResults('Get-WindowsOptionalFeature -Online', $false) } $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Feature in $FoundFeatures) { if ($null -eq $Feature) { continue } if ($Feature.FeatureName.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Feature.FeatureName) } } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Counter in [CompletionHelper]::GetCachedResults("Get-Counter -ListSet * | Sort-Object -Property CounterSetName", $false)) { if ($null -eq $Counter) { continue } if ($parameterName -eq "ListSet") { if ($Counter.CounterSetName.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Counter.CounterSetName) } } else { foreach ($Path in $Counter.Paths) { if ($Path.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Path) } } } } } Register-ArgumentCompleter -CommandName Get-Counter -ParameterName ListSet -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName Get-Counter -ParameterName Counter -ScriptBlock $ScriptBlock Register-ArgumentCompleter -CommandName Get-PnpDevice -ParameterName Class -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Class in [CompletionHelper]::GetCachedResults("Get-PnpDevice | Select-Object -ExpandProperty Class | Sort-Object -Unique", $false)) { if ($null -eq $Class) { continue } if ($Class.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Class) } } } Register-ArgumentCompleter -CommandName Register-ArgumentCompleter -ParameterName ParameterName -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $CommandToFind = $fakeBoundParameters['CommandName'] if ([string]::IsNullOrEmpty($CommandToFind)) { return } $CommandInfo = Get-Command -Name $CommandToFind $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Key in $CommandInfo.Parameters.Keys) { if (!$Key.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { continue } [CompletionHelper]::NewParamCompletionResult($Key) } } Register-ArgumentCompleter -CommandName @( 'Get-ADComputer' 'Get-ADFineGrainedPasswordPolicy' 'Get-ADGroup' 'Get-ADObject' 'Get-ADOptionalFeature' 'Get-ADOrganizationalUnit' 'Get-ADServiceAccount' 'Get-ADUser' 'Search-ADAccount' ) -ParameterName SearchBase -ScriptBlock { #This is not actually an argument completer, it's more like a CLI OU navigator param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $GetOuParams = @{ SearchScope = [Microsoft.ActiveDirectory.Management.ADSearchScope]::OneLevel Filter = '*' } if ($TrimmedWord.Length -gt 0) { $GetOuParams.Add('SearchBase', $TrimmedWord) } foreach ($Ou in Get-ADOrganizationalUnit @GetOuParams) { [CompletionResult]::new( "'$($Ou.DistinguishedName)'", $Ou.Name, [CompletionResultType]::ParameterValue, $Ou.DistinguishedName ) } } Register-ArgumentCompleter -CommandName Split-WindowsImage -ParameterName FileSize -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $SizeConfigs = @( @{Name = "Fat32"; Size="4096"} ) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $SizeConfigs) { if ($Item['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $Item['Size'], $Item['Name'], [CompletionResultType]::ParameterValue, "$($Item['Size'])MB for $($Item['Name'])" ) } } } Register-ArgumentCompleter -CommandName Start-Process -ParameterName Verb -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $FilePath = $fakeBoundParameters['FilePath'] if ([string]::IsNullOrWhiteSpace($FilePath)) { return } $Executable = [CompletionHelper]::GetCachedResults("Get-Command -Name '$FilePath' -CommandType Application -ErrorAction Ignore", $true) if ($null -eq $Executable) { return } $CommandInfo = [CompletionHelper]::GetCachedResults("[System.Diagnostics.ProcessStartInfo]::new('A$($Executable.Extension)')", $false) foreach ($Verb in $CommandInfo.Verbs) { if ($Verb.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Verb) } } } Register-ArgumentCompleter -CommandName Test-NetConnection -ParameterName Port -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $KnownPorts = @( @{Name="FTPData" ;Value="20" ;ToolTip='TCP Port 20. FTP (File Transfer Protocol) data transfer.'} @{Name="FTPControl" ;Value="21" ;ToolTip='TCP Port 21. FTP (File Transfer Protocol) control.'} @{Name="SSH" ;Value="22" ;ToolTip='TCP port 22. SSH (Secure Shell).'} @{Name="SCP" ;Value="22" ;ToolTip='TCP port 22. SCP (Secure Copy).'} #Obviously it's the same as SSH, but it's more convenient to have multiple text options. @{Name="SFTP_SSH" ;Value="22" ;ToolTip='TCP port 22. SFTP (SSH File Transfer Protocol).'} @{Name="Telnet" ;Value="23" ;ToolTip='TCP port 23. Telnet.'} @{Name="SMTP" ;Value="25" ;ToolTip='TCP port 25. SMTP (Simple Mail Transfer Protocol).'} @{Name="DNS" ;Value="53" ;ToolTip='TCP and UDP port 53. DNS (Domain Name System)'} @{Name="HTTP" ;Value="80" ;ToolTip='TCP and UDP port 80. HTTP (Hypertext Transfer Protocol)'} @{Name="Kerberos" ;Value="88" ;ToolTip='TCP and UDP port 88. Kerberos authentication.'} @{Name="SFTP" ;Value="115" ;ToolTip='TCP port 115. SFTP (Simple File Transfer Protocol)'} @{Name="RPCEPMap" ;Value="135" ;ToolTip='TCP Port 135. RPC Endpoint mapper.'} @{Name="NetBiosNameService" ;Value="137" ;ToolTip='TCP and UDP port 137. Netbios name registration and resolution.'} @{Name="NetBiosSessionService" ;Value="139" ;ToolTip='TCP port 139. Netbios session service.'} @{Name="IMAP" ;Value="143" ;ToolTip='TCP port 143. IMAP (Internet Message Access Protocol).'} @{Name="SNMPTrap" ;Value="162" ;ToolTip='TCP and UDP port 162. SNMP (Simple Network Management Protocol) trap'} @{Name="LDAP" ;Value="389" ;ToolTip='TCP port 389. LDAP (Lightweight Directory Access Protocol)'} @{Name="HTTPS" ;Value="443" ;ToolTip='TCP and UDP port 443. HTTPS (Hypertext Transfer Protocol Secure)'} @{Name="SMB" ;Value="445" ;ToolTip='TCP and UDP port 445. SMB (Server Message Block)'} @{Name="KerberosSetPassword" ;Value="464" ;ToolTip='TCP and UDP port 464. Kerberos update password.'} @{Name="LDAPS" ;Value="636" ;ToolTip='TCP port 636. LDAPS (Lightweight Directory Access Protocol over TLS/SSL)'} @{Name="IMAPS" ;Value="993" ;ToolTip='TCP port 993. IMAPS (Internet Message Access Protocol over TLS/SSL)'} @{Name="MSSQL" ;Value="1433" ;ToolTip='TCP and UDP port 1433. Default instance MS SQL server port.'} @{Name="KMS" ;Value="1688" ;ToolTip='TCP port 1688. Default KMS (Key management service) port.'} @{Name="LDAPGC" ;Value="3268" ;ToolTip='TCP and UDP port 3268. LDAP global catalog.'} @{Name="LDAPSGC" ;Value="3269" ;ToolTip='TCP and UDP port 3269. LDAPS global catalog.'} @{Name="RDP" ;Value="3389" ;ToolTip='TCP and UDP port 3389. Default RDP port.'} @{Name="WinRM" ;Value="5985" ;ToolTip='TCP port 5985. Default WinRM port.'} @{Name="WinRMHttps" ;Value="5986" ;ToolTip='TCP port 5986. Default WinRM HTTPs port.'} ) foreach ($Port in $KnownPorts) { if ($Port['Name'].StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( $Port['Value'], $Port['Name'], [CompletionResultType]::ParameterValue, $Port['ToolTip'] ) } } } Register-ArgumentCompleter -CommandName Add-WindowsCapability,Get-WindowsCapability,Remove-WindowsCapability -ParameterName Name -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $FoundFeatures = if ($fakeBoundParameters["Path"]) { [CompletionHelper]::GetCachedResults("Get-WindowsCapability -Path '$($fakeBoundParameters['Path'])'", $true) } else { [CompletionHelper]::GetCachedResults('Get-WindowsCapability -Online', $false) } $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Feature in $FoundFeatures) { if ($null -eq $Feature) { continue } if ($Feature.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Feature.Name) } } } Register-ArgumentCompleter -CommandName Export-WindowsImage,New-WindowsImage -ParameterName CompressionType -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($CompressionType in "None","Fast","Max") { if ($CompressionType.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($CompressionType) } } } $Scriptblock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Log in [CompletionHelper]::GetCachedResults('Get-WinEvent -ListLog *', $false)) { if ($null -eq $Log) { continue } if ($Log.LogName -like "*$TrimmedWord*") { [CompletionHelper]::NewParamCompletionResult($Log.LogName) } } } Register-ArgumentCompleter -CommandName Get-WinEvent -ParameterName LogName -ScriptBlock $Scriptblock Register-ArgumentCompleter -CommandName Get-WinEvent -ParameterName ListLog -ScriptBlock $Scriptblock $Scriptblock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Log in [CompletionHelper]::GetCachedResults('Get-WinEvent -ListProvider *', $false)) { if ($null -eq $Log) { continue } if ($Log.Name -like "*$TrimmedWord*") { [CompletionHelper]::NewParamCompletionResult($Log.Name) } } } Register-ArgumentCompleter -CommandName Get-WinEvent -ParameterName ProviderName -ScriptBlock $Scriptblock Register-ArgumentCompleter -CommandName Get-WinEvent -ParameterName ListProvider -ScriptBlock $Scriptblock <# .SYNOPSIS Lists all the argument completers supported by this module. .PARAMETER CommandName Filters the displayed argument completers to the specified commands. .PARAMETER CommandName Filters the displayed argument completers to the specified parameters. #> function Get-UsefulArgumentCompleter { Param ( [Parameter()] [SupportsWildcards()] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $Commands = [CompletionHelper]::GetCachedResults("Import-Csv -Path '$PSScriptRoot\ArgumentCompleters.csv' -Delimiter ','", $false) | Select-Object -ExpandProperty CommandName | Sort-Object -Unique foreach ($Item in $Commands) { if ($Item.StartsWith($TrimmedWord), [StringComparison]::OrdinalIgnoreCase) { [CompletionHelper]::NewParamCompletionResult($Item) } } })] [string[]] $CommandName = "*", [Parameter()] [SupportsWildcards()] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $Parameters = [CompletionHelper]::GetCachedResults("Import-Csv -Path '$PSScriptRoot\ArgumentCompleters.csv' -Delimiter ','", $false) | Select-Object -ExpandProperty ParameterName | Sort-Object -Unique foreach ($Item in $Parameters) { if ($Item.StartsWith($TrimmedWord), [StringComparison]::OrdinalIgnoreCase) { [CompletionHelper]::NewParamCompletionResult($Item) } } })] [string[]] $ParameterName = "*" ) End { foreach ($Completer in [CompletionHelper]::GetCachedResults("Import-Csv -Path '$PSScriptRoot\ArgumentCompleters.csv' -Delimiter ','", $false)) { $CommandMatch = $false foreach ($Name in $CommandName) { if ($Completer.CommandName -like $Name) { $CommandMatch = $true break } } if (!$CommandMatch) { continue } foreach ($Name in $ParameterName) { if ($Completer.ParameterName -like $Name) { $Completer break } } } } } <# .SYNOPSIS Imports optional argument completers. This is intended to handle argument completers that may conflict with other commands such as Hyper-V VS PowerCLI commands. .PARAMETER OptionalCompleter Name of completer to load. #> function Import-UsefulArgumentCompleterSet { Param ( [Parameter(Mandatory)] [Alias("Completer")] [ValidateSet("Hyperv")] [string[]] $OptionalCompleter ) End { switch ($OptionalCompleter) { 'HyperV' { & $Script:HypervCompleters break } } } } if ($PSEdition -eq 'Desktop') { $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Package in [CompletionHelper]::GetCachedResults('Get-AppxPackage | Sort-Object -Property Name', $false)) { if ($null -eq $Package) { continue } $MatchText = if ($parameterName -eq "Package") { $Package.PackageFullName } else { $Package.Name } if ($MatchText -like "*$TrimmedWord*") { [CompletionHelper]::NewParamCompletionResult($MatchText, $Package.Name) } } } Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Name -CommandName Get-AppxPackage Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Package -CommandName Get-AppxPackageManifest,Move-AppxPackage,Remove-AppxPackage,Reset-AppxPackage Register-ArgumentCompleter -CommandName Get-AppxPackage -ParameterName Publisher -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Publisher in [CompletionHelper]::GetCachedResults('Get-AppxPackage | Select-Object -ExpandProperty Publisher | Sort-Object -Unique', $false)) { if ($null -eq $Publisher) { continue } if ($Publisher -like "*$TrimmedWord*") { [CompletionHelper]::NewParamCompletionResult($Publisher) } } } Register-ArgumentCompleter -CommandName Get-CimInstance -ParameterName Property -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) if (!$fakeBoundParameters['ClassName']) { return } $GetCimClassParams = @{ClassName = $fakeBoundParameters['ClassName']} if ($fakeBoundParameters['Namespace']) { $GetCimClassParams.Add('Namespace',$fakeBoundParameters['Namespace']) } $FoundClass = Get-CimClass @GetCimClassParams -ErrorAction Ignore if (!$FoundClass) { return } $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) foreach ($Item in $FoundClass.CimClassProperties) { if ($Item.Name.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionHelper]::NewParamCompletionResult($Item.Name, "$($Item.Name) [$($Item.CimType)]") } } } } if ($PSEdition -eq 'Core') { } $Script:HypervCompleters = { $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $TrimmedWord = [CompletionHelper]::TrimQuotes($wordToComplete) $FoundVMs = if ($parameterName -eq "VMName" -or $parameterName -eq "Name") { Hyper-V\Get-VM -Name "$TrimmedWord*" -ErrorAction Ignore } elseif ($parameterName -eq 'VMId' -or $parameterName -eq 'Id') { Hyper-V\Get-VM -ErrorAction Ignore | Where-Object -FilterScript {$_.Id.Guid -like "$TrimmedWord*"} } else { return } foreach ($VM in $FoundVMs) { $MatchText = if ($parameterName -eq "Name" -or $parameterName -eq "VMName") { $VM.Name } else { "{$($VM.Id.Guid)}" } if ($MatchText.StartsWith($TrimmedWord, [StringComparison]::OrdinalIgnoreCase)) { [CompletionResult]::new( [CompletionHelper]::AddQuotesIfNeeded($MatchText), $VM.Name, [CompletionResultType]::ParameterValue, $VM.Name ) } } } Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName VMName -CommandName @( 'Add-VMAssignableDevice' 'Add-VMDvdDrive' 'Add-VMFibreChannelHba' 'Add-VMGpuPartitionAdapter' 'Add-VMHardDiskDrive' 'Add-VMKeyStorageDrive' 'Add-VMNetworkAdapter' 'Add-VMNetworkAdapterAcl' 'Add-VMNetworkAdapterExtendedAcl' 'Add-VMNetworkAdapterRoutingDomainMapping' 'Add-VMPmemController' 'Add-VMRemoteFx3dVideoAdapter' 'Add-VMScsiController' 'Add-VMSwitchExtensionPortFeature' 'Complete-VMFailover' 'Connect-VMNetworkAdapter' 'Disable-VMConsoleSupport' 'Disable-VMIntegrationService' 'Disable-VMResourceMetering' 'Disable-VMTPM' 'Disconnect-VMNetworkAdapter' 'Enable-VMConsoleSupport' 'Enable-VMIntegrationService' 'Enable-VMReplication' 'Enable-VMResourceMetering' 'Enable-VMTPM' 'Enter-PSSession' 'Export-VMSnapshot' 'Get-PSSession' 'Get-VMAssignableDevice' 'Get-VMBios' 'Get-VMComPort' 'Get-VMConnectAccess' 'Get-VMDvdDrive' 'Get-VMFibreChannelHba' 'Get-VMFirmware' 'Get-VMFloppyDiskDrive' 'Get-VMGpuPartitionAdapter' 'Get-VMHardDiskDrive' 'Get-VMIdeController' 'Get-VMIntegrationService' 'Get-VMKeyProtector' 'Get-VMKeyStorageDrive' 'Get-VMMemory' 'Get-VMNetworkAdapter' 'Get-VMNetworkAdapterAcl' 'Get-VMNetworkAdapterExtendedAcl' 'Get-VMNetworkAdapterFailoverConfiguration' 'Get-VMNetworkAdapterIsolation' 'Get-VMNetworkAdapterRdma' 'Get-VMNetworkAdapterRoutingDomainMapping' 'Get-VMNetworkAdapterTeamMapping' 'Get-VMNetworkAdapterVlan' 'Get-VMPmemController' 'Get-VMProcessor' 'Get-VMRemoteFx3dVideoAdapter' 'Get-VMReplication' 'Get-VMScsiController' 'Get-VMSecurity' 'Get-VMSnapshot' 'Get-VMStorageSettings' 'Get-VMSwitchExtensionPortData' 'Get-VMSwitchExtensionPortFeature' 'Get-VMVideo' 'Grant-VMConnectAccess' 'Import-VMInitialReplication' 'Invoke-Command' 'Measure-VMReplication' 'New-PSSession' 'Remove-PSSession' 'Remove-VMAssignableDevice' 'Remove-VMDvdDrive' 'Remove-VMFibreChannelHba' 'Remove-VMGpuPartitionAdapter' 'Remove-VMHardDiskDrive' 'Remove-VMKeyStorageDrive' 'Remove-VMNetworkAdapter' 'Remove-VMNetworkAdapterAcl' 'Remove-VMNetworkAdapterExtendedAcl' 'Remove-VMNetworkAdapterRoutingDomainMapping' 'Remove-VMNetworkAdapterTeamMapping' 'Remove-VMPmemController' 'Remove-VMRemoteFx3dVideoAdapter' 'Remove-VMReplication' 'Remove-VMSavedState' 'Remove-VMScsiController' 'Remove-VMSnapshot' 'Remove-VMSwitchExtensionPortFeature' 'Rename-VMNetworkAdapter' 'Rename-VMSnapshot' 'Reset-VMReplicationStatistics' 'Reset-VMResourceMetering' 'Restore-VMSnapshot' 'Resume-VMReplication' 'Revoke-VMConnectAccess' 'Set-VMBios' 'Set-VMComPort' 'Set-VMDvdDrive' 'Set-VMFibreChannelHba' 'Set-VMFirmware' 'Set-VMFloppyDiskDrive' 'Set-VMGpuPartitionAdapter' 'Set-VMHardDiskDrive' 'Set-VMKeyProtector' 'Set-VMKeyStorageDrive' 'Set-VMMemory' 'Set-VMNetworkAdapter' 'Set-VMNetworkAdapterFailoverConfiguration' 'Set-VMNetworkAdapterIsolation' 'Set-VMNetworkAdapterRdma' 'Set-VMNetworkAdapterRoutingDomainMapping' 'Set-VMNetworkAdapterTeamMapping' 'Set-VMNetworkAdapterVlan' 'Set-VMProcessor' 'Set-VMRemoteFx3dVideoAdapter' 'Set-VMReplication' 'Set-VMSecurity' 'Set-VMSecurityPolicy' 'Set-VMStorageSettings' 'Set-VMSwitchExtensionPortFeature' 'Set-VMVideo' 'Start-VMFailover' 'Start-VMInitialReplication' 'Stop-VMFailover' 'Stop-VMInitialReplication' 'Stop-VMReplication' 'Suspend-VMReplication' 'Test-VMNetworkAdapter' ) Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Name -CommandName @( 'Checkpoint-VM' 'Copy-VMFile' 'Debug-VM' 'Export-VM' 'Get-VM' 'Measure-VM' 'Move-VMStorage' 'New-VM' 'Remove-VM' 'Rename-VM' 'Restart-VM' 'Resume-VM' 'Save-VM' 'Set-VM' 'Start-VM' 'Stop-VM' 'Suspend-VM' 'Update-VMVersion' 'Wait-VM' ) Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName VMId -CommandName @( 'Enter-PSSession' 'Get-PSSession' 'Get-VHD' 'Get-VMConnectAccess' 'Grant-VMConnectAccess' 'Invoke-Command' 'New-PSSession' 'Remove-PSSession' 'Revoke-VMConnectAccess' ) Register-ArgumentCompleter -ScriptBlock $ScriptBlock -ParameterName Id -CommandName Get-VM } |