Manipulating Wildcards
Many Windows PowerShell cmdlets support wildcard characters for their parameter values. For example, almost every cmdlet that has the Name or Path parameter supports wildcard characters for these parameters. When writing scripts, you often need to design a function or a script that can run against a group of resources rather than against a single resource. In such cases you must provide support for wildcard characters. Inside your function you might want to know if the argument you get for a wildcard parameter actually contains wildcard characters.
Note: The process of using wildcard characters is sometimes referred to as globbing.
WildcardPattern Static methods
The System.Management.Automation namespace has a WildcardPattern class that represents a wildcard pattern that is used for matching. We can use its static members to escape (adding a backtick character in front of wildcard characters) or unescape wildcard patterns or check if a given string has any wildcard characters in it.
PS> [System.Management.Automation.WildcardPattern] | Get-Member -Static
TypeName: System.Management.Automation.WildcardPattern
Name MemberType Definition
---- ---------- ----------
ContainsWildcardCharacters Method static bool ContainsWildcardCharacters(string pattern)
Equals Method static bool Equals(System.Object objA, System.Object objB)
Escape Method static string Escape(string pattern)
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object objB)
Unescape Method static string Unescape(string pattern)
# check if a given string has any wildcard characters in it
PS> $pattern = 's?[cn]*'
PS> [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($pattern)
True
# escape the pattern, interpret it literally
PS> [System.Management.Automation.WildcardPattern]::Escape($pattern)
s`?`[cn`]`*
# unescape
PS> [System.Management.Automation.WildcardPattern]::Unescape('s`?`[cn`]`*')
s?[cn]
Creating WildcardPattern objects
The WildcardPattern class has also Instance methods. Using New-Object, we can instantiate the class with a string pattern and access the instance methods:
PS> New-Object System.Management.Automation.WildcardPattern -ArgumentList $pattern | Get-Member
TypeName: System.Management.Automation.WildcardPattern
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
IsMatch Method bool IsMatch(string input)
ToString Method string ToString()
ToWql Method string ToWql()
With the IsMatch method we can determine if the supplied string matches the wildcard pattern you specified as an argument. The ToWql method, as its name implies, converts the pattern to a WMI Query Language (WQL) filter.
If not stated otherwise, wildcard pattern matching is performed on a case-insensitive basis. You can also create a case-insensitive pattern using another constructor by passing a WilcardOptions object. The following command creates a case-insensitive pattern that ignores cultural differences.
New-Object System.Management.Automation.WildcardPattern -ArgumentList $pattern,'IgnoreCase,CultureInvariant'
Putting it all together, you can get a string, check if it contains wildcard characters, and if so convert it to WQL (WMI Query Language) so the result can be used in a WMI filter.
Let’s see which process names match our pattern. The pattern, ‘s?[cn]*’, starts with the letter ‘s’, then it should match any single character (e.g ?), then the letter ‘c’ or ‘n’, and zero or more characters (e.g *)
PS> Get-Process -Name $pattern | Format-Table Name
Name
----
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
SyncServer
SynTPEnh
SynTPHelper
SynTPLpr
As you can see all process names match the pattern. Now let’s try to convert it to WQL and use it with the Get-WmiObject cmdlet.
We’ll start by checking if the pattern contains wildcard characters, if so, the converted pattern will be written to the console, the wildcard pattern will be converted to WQL so you get all processes that match the pattern
$IsWP = [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($pattern)
if($IsWP)
{
$wp= (New-Object System.Management.Automation.WildcardPattern -ArgumentList $pattern)
$wqlPattern = $wp.ToWql()
Write-Host "WilcardPattern '$wildcard' in WQL is: '$wqlPattern'"
Get-WmiObject -Class Win32_Process -Filter "Name LIKE '$wqlPattern '" | Format-Table Name
}
WilcardPattern 's?[cn]*' in WQL is: 's_[cn]%'
Name
----
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
svchost.exe
SynTPEnh.exe
SynTPLpr.exe
SynTPHelper.exe
SyncServer.exe
And sure enough, we get the same result!
Share on: