This is more about my weak understanding of pipelines and functions than anything, so would appreciate help. As an example:
Get-Service | Select-String win # fails
Get-Service | Out-String -Stream | Select-String win # works
I've seen explanations on why the Out-String -Stream
is required, but it frustrates me a bit, so I want a function oss
that does the Out-String -Stream
part. My idea is like this:
function oss { Out-String -Stream }
Get-Service | oss | Select-String win
But this fails. Can someone tell me how to make this work, i.e. make the oss
function pipeline compatible?
And from that, how do we then do the following (obviously this doesn't work, but I'm really curious how this would be achieved)?
function slx { Out-String -Stream | Select-String <and allow all of the same switches as Select-String> }
Get-Service | slx win
So that, effectively, slx
is a variant of Select-String
that always does the Out-String -Stream
part as well?
To find a string inside of a string with PowerShell, you can use the Substring() method. This method is found on every string object in PowerShell. The first argument to pass to the Substring() method is the position of the leftmost character. In this case, the leftmost character is T .
You can use it like Grep in UNIX and Findstr in Windows with Select-String in PowerShell. Select-String is based on lines of text. By default, Select-String finds the first match in each line and, for each match, it displays the file name, line number, and all text in the line containing the match.
Select-String uses the Pattern parameter to specify HELLO. The CaseSensitive parameter specifies that the case must match only the upper-case pattern. SimpleMatch is an optional parameter and specifies that the string in the pattern isn't interpreted as a regular expression.
The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.
The Pattern parameter uses the string About_ as the search criteria. To run the function, type Search-Help. The function's Select-String command displays the output in the PowerShell console. This example searches for a string in a Windows event log. The variable $_ represents the current object in the pipeline.
Summary: Microsoft MVP, Adam Bertram, talks about accepting pipelined input into Windows PowerShell advanced functions. Microsoft Scripting Guy, Ed Wilson, is here. Today Microsoft MVP, Adam Bertram, returns to talk about accepting pipeline input into advanced Windows PowerShell functions. Note This is the second post in a series.
The pipeline is what makes PowerShell so unique. The thought of a pipeline is not new. We've been able to pipe strings from the output of one command to the input of another command for a long time. However, it wasn't until PowerShell came along that we had a language that allowed us to pipe objects from one command to another.
In some cases, calling it isn’t quite enough and PowerShell V2 delivered the steppable pipeline which can take a PowerShell command (or set of commands piped together) and allow us to run its begin block , process block, and end block, under the control of a function. So a Proxy function looks like this :
I appreciate that you want to learn, so I will not just give you a working solution, but also explain a few things.
It seems like your you have a basic understanding of how functions and the pipeline work. If you want to learn more about it have a look at about_Pipelines and about_Functions (and related help topics), or let me know what in particular you want to know in the comments.
One thing you need to understand though if you are new to Powershell, is that it it's object-based, not text-based. It's objects that are passed through the pipeline, and you should work with them as such, and not convert them to text (unless for file output).
The documentation about Select-String states specifically, that it is meant for finding text in strings and files. But this is not what you are trying to do here. As I said, work with objects, not text. So omit the Out-String
. The proper command to filter objects in a pipeline is Where-Object or one of its aliases where
or ?
.
Example:
Get-Service | where { $_.DisplayName -like *win* }
# in newer Powershell versions, this shorter syntax is also possible:
Get-Service | where DisplayName -like *win*
But as you specifically asked about making a function "pipeline aware", this can be done in several ways. But your problem is not only getting input from the pipeline, but also they way you pass it to Out-String
, because the output will change if you pass only one item at a time.
Basically you have to pass the input all at once. So, the simplest way to achieve this in your case is using the $Input automatic variable:
function oss { $Input | Out-String -Stream }
If you need to process one pipeline item at a time, there are more ways to get pipeline input. For example an advanced function:
function example {
process {
$_ # current item
}
}
You can also use the parameter attribute to bind the pipeline input to a function parameter:
function example {
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject
)
process {
$InputObject # current item
}
}
The last way I can think of is using a filter, which is a special kind of function which is specifically designed to perform an operation on each pipeline element:
filter example {
$_ # current item
}
To learn more about it I recommend a google search which will quickly provide you with useful articles such as Build a PowerShell function for the pipeline or Incorporating Pipelined Input into PowerShell Functions.
If you truly want to build a method that is basically a wrapper for another cmdlet like Out-String
or Select-String
with all the same switches, you should have a look at proxy functions. But I think this would be overkill for what you're trying to do:
function oss {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true)]
[psobject]$InputObject
)
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
# set -Stream switch always
$PSBoundParameters["Stream"] = $true
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Out-String', [System.Management.Automation.CommandTypes]::Cmdlet)
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
}
Note: This answer complements marsze's helpful answer.
Windows PowerShell v5.1 and PowerShell [Core] v6+ have an oss
function built in, which effectively provides the functionality of Out-String -Stream
via a proxy function, as shown in @marsze's answer.
OutBuffer
-related code only applies to server-side proxy functions that need to guard against DoS (denial-of-service) attacks, and the throw
statements should be $PSCmdlet.ThrowTerminatingError($_)
instead - see GitHub issue #10863.While this helper function is useful, it shouldn't be required in the first place, because Select-String
should implicitly operate on formatted output to begin with:
That is, for input that isn't already a string (text), Select-String
should search the same richly formatted text representation that you see in the console (terminal).
Where-Object
.GitHub suggestion #10726 proposes just that, though there seem to be backward-compatibility concerns, even though I think there shouldn't be.
You can adapt the proxy-function approach from marsze's answers to properly implement the slx
function you envision, as advanced function Select-StringFormatted
, aliased to scs
(see rationale below; of course, you can also define slx
).
Note:
The bulk of the code is the auto-generated declaration of the same parameters that Select-String
supports; the actual proxying (wrapping) code via Out-String -Stream
is minimal.
Alias scs
is what Select-String
's built-in alias sls
should have been, given that the official alias prefix for approved verb Select
is sc
, not ls
; in PowerShell [Core] v6+ you an easily verify that with Get-Verb Select
. Since the implicit Out-String -Stream
behavior should be Select-String
's default behavior anyway, I think it makes sense to pick this alias; if/when Select-String
gets fixed, you can redefine scs
to point to Select-String
.
All parameters supported as of v7.0 are declared; if you try to use ones only introduced in 7.0 in earlier versions, namely -Culture
, -Raw
, and -NoEmphasis
, they are ignored and a warning is emitted.
Example command (compare to the output from Get-Process | sls service
):
PS> Get-Process | scs service # scs == Select-StringFormatted
395 16 3728 14656 5664 0 SecurityHealthService
360 11 3864 7696 632 0 services
173 12 3324 8628 2388 0 VGAuthService
Note: The function below is also available as an MIT-licensed Gist, and only the latter will be maintained going forward. Assuming you have looked at the linked code to ensure that it is safe (which I can personally assure you of, but you should always check), you can install it as follows:
irm https://gist.github.com/mklement0/46fea9e6e5ef1a3ceaf681c976cb68e3/raw/Select-StringFormatted.ps1 | iex
Set-Alias scs Select-StringFormatted
function Select-StringFormatted {
<#
.SYNOPSIS
Select-String wrapper command that for non-string input searches the
*formatted* object representations rather than the often useless
.ToString() representations.
All Select-String parameters are supported. See the latter's help for more.
.EXAMPLE
Get-Process | Select-StringFormatted pwsh
Output lines that contain "pwsh" in Get-Process' formatted output.
.LINK
Select-String
#>
[CmdletBinding(DefaultParameterSetName = 'File', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2097119')]
param(
[ValidateSet('Ordinal', 'Invariant', 'Current', '', 'af', 'af-NA', 'af-ZA', 'agq', 'agq-CM', 'ak', 'ak-GH', 'am', 'am-ET', 'ar', 'ar-001', 'ar-AE', 'ar-BH', 'ar-DJ', 'ar-DZ', 'ar-EG', 'ar-EH', 'ar-ER', 'ar-IL', 'ar-IQ', 'ar-JO', 'ar-KM', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-MR', 'ar-OM', 'ar-PS', 'ar-QA', 'ar-SA', 'ar-SD', 'ar-SO', 'ar-SS', 'ar-SY', 'ar-TD', 'ar-TN', 'ar-YE', 'arn', 'arn-CL', 'as', 'as-IN', 'asa', 'asa-TZ', 'ast', 'ast-ES', 'az', 'az-Cyrl', 'az-Cyrl-AZ', 'az-Latn', 'az-Latn-AZ', 'ba', 'ba-RU', 'bas', 'bas-CM', 'be', 'be-BY', 'bem', 'bem-ZM', 'bez', 'bez-TZ', 'bg', 'bg-BG', 'bm', 'bm-ML', 'bn', 'bn-BD', 'bn-IN', 'bo', 'bo-CN', 'bo-IN', 'br', 'br-FR', 'brx', 'brx-IN', 'bs', 'bs-Cyrl', 'bs-Cyrl-BA', 'bs-Latn', 'bs-Latn-BA', 'byn', 'byn-ER', 'ca', 'ca-AD', 'ca-ES', 'ca-FR', 'ca-IT', 'ccp', 'ccp-BD', 'ccp-IN', 'ce', 'ce-RU', 'ceb', 'ceb-PH', 'cgg', 'cgg-UG', 'chr', 'chr-US', 'ckb', 'ckb-IQ', 'ckb-IR', 'co', 'co-FR', 'cs', 'cs-CZ', 'cv', 'cv-RU', 'cy', 'cy-GB', 'da', 'da-DK', 'da-GL', 'dav', 'dav-KE', 'de', 'de-AT', 'de-BE', 'de-CH', 'de-DE', 'de-IT', 'de-LI', 'de-LU', 'dje', 'dje-NE', 'dsb', 'dsb-DE', 'dua', 'dua-CM', 'dv', 'dv-MV', 'dyo', 'dyo-SN', 'dz', 'dz-BT', 'ebu', 'ebu-KE', 'ee', 'ee-GH', 'ee-TG', 'el', 'el-CY', 'el-GR', 'en', 'en-001', 'en-150', 'en-AD', 'en-AE', 'en-AG', 'en-AI', 'en-AL', 'en-AR', 'en-AS', 'en-AT', 'en-AU', 'en-BA', 'en-BB', 'en-BD', 'en-BE', 'en-BG', 'en-BI', 'en-BM', 'en-BR', 'en-BS', 'en-BW', 'en-BZ', 'en-CA', 'en-CC', 'en-CH', 'en-CK', 'en-CL', 'en-CM', 'en-CN', 'en-CO', 'en-CX', 'en-CY', 'en-CZ', 'en-DE', 'en-DG', 'en-DK', 'en-DM', 'en-EE', 'en-ER', 'en-ES', 'en-FI', 'en-FJ', 'en-FK', 'en-FM', 'en-FR', 'en-GB', 'en-GD', 'en-GG', 'en-GH', 'en-GI', 'en-GM', 'en-GR', 'en-GU', 'en-GY', 'en-HK', 'en-HR', 'en-HU', 'en-ID', 'en-IE', 'en-IL', 'en-IM', 'en-IN', 'en-IO', 'en-IS', 'en-IT', 'en-JE', 'en-JM', 'en-JP', 'en-KE', 'en-KI', 'en-KN', 'en-KR', 'en-KY', 'en-LC', 'en-LR', 'en-LS', 'en-LT', 'en-LU', 'en-LV', 'en-ME', 'en-MG', 'en-MH', 'en-MM', 'en-MO', 'en-MP', 'en-MS', 'en-MT', 'en-MU', 'en-MV', 'en-MW', 'en-MX', 'en-MY', 'en-NA', 'en-NF', 'en-NG', 'en-NL', 'en-NO', 'en-NR', 'en-NU', 'en-NZ', 'en-PG', 'en-PH', 'en-PK', 'en-PL', 'en-PN', 'en-PR', 'en-PT', 'en-PW', 'en-RO', 'en-RS', 'en-RU', 'en-RW', 'en-SA', 'en-SB', 'en-SC', 'en-SD', 'en-SE', 'en-SG', 'en-SH', 'en-SI', 'en-SK', 'en-SL', 'en-SS', 'en-SX', 'en-SZ', 'en-TC', 'en-TH', 'en-TK', 'en-TO', 'en-TR', 'en-TT', 'en-TV', 'en-TW', 'en-TZ', 'en-UA', 'en-UG', 'en-UM', 'en-US', 'en-US-POSIX', 'en-VC', 'en-VG', 'en-VI', 'en-VU', 'en-WS', 'en-ZA', 'en-ZM', 'en-ZW', 'eo', 'eo-001', 'es', 'es-419', 'es-AG', 'es-AI', 'es-AR', 'es-AW', 'es-BB', 'es-BL', 'es-BM', 'es-BO', 'es-BQ', 'es-BR', 'es-BS', 'es-BZ', 'es-CA', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-CW', 'es-DM', 'es-DO', 'es-EA', 'es-EC', 'es-ES', 'es-FK', 'es-GD', 'es-GF', 'es-GL', 'es-GP', 'es-GQ', 'es-GT', 'es-GY', 'es-HN', 'es-HT', 'es-IC', 'es-KN', 'es-KY', 'es-LC', 'es-MF', 'es-MQ', 'es-MS', 'es-MX', 'es-NI', 'es-PA', 'es-PE', 'es-PH', 'es-PM', 'es-PR', 'es-PY', 'es-SR', 'es-SV', 'es-SX', 'es-TC', 'es-TT', 'es-US', 'es-UY', 'es-VC', 'es-VE', 'es-VG', 'es-VI', 'et', 'et-EE', 'eu', 'eu-ES', 'ewo', 'ewo-CM', 'fa', 'fa-AF', 'fa-IR', 'ff', 'ff-Latn', 'ff-Latn-BF', 'ff-Latn-CM', 'ff-Latn-GH', 'ff-Latn-GM', 'ff-Latn-GN', 'ff-Latn-GW', 'ff-Latn-LR', 'ff-Latn-MR', 'ff-Latn-NE', 'ff-Latn-NG', 'ff-Latn-SL', 'ff-Latn-SN', 'fi', 'fi-FI', 'fil', 'fil-PH', 'fo', 'fo-DK', 'fo-FO', 'fr', 'fr-BE', 'fr-BF', 'fr-BI', 'fr-BJ', 'fr-BL', 'fr-CA', 'fr-CD', 'fr-CF', 'fr-CG', 'fr-CH', 'fr-CI', 'fr-CM', 'fr-DJ', 'fr-DZ', 'fr-FR', 'fr-GA', 'fr-GF', 'fr-GN', 'fr-GP', 'fr-GQ', 'fr-HT', 'fr-KM', 'fr-LU', 'fr-MA', 'fr-MC', 'fr-MF', 'fr-MG', 'fr-ML', 'fr-MQ', 'fr-MR', 'fr-MU', 'fr-NC', 'fr-NE', 'fr-PF', 'fr-PM', 'fr-RE', 'fr-RW', 'fr-SC', 'fr-SN', 'fr-SY', 'fr-TD', 'fr-TG', 'fr-TN', 'fr-VU', 'fr-WF', 'fr-YT', 'fur', 'fur-IT', 'fy', 'fy-NL', 'ga', 'ga-IE', 'gaa', 'gaa-GH', 'gd', 'gd-GB', 'gez', 'gez-ER', 'gez-ET', 'gl', 'gl-ES', 'gn', 'gn-PY', 'gsw', 'gsw-CH', 'gsw-FR', 'gsw-LI', 'gu', 'gu-IN', 'guz', 'guz-KE', 'gv', 'gv-IM', 'ha', 'ha-GH', 'ha-NE', 'ha-NG', 'haw', 'haw-US', 'he', 'he-IL', 'hi', 'hi-IN', 'hi-Latn', 'hr', 'hr-BA', 'hr-HR', 'hsb', 'hsb-DE', 'hu', 'hu-HU', 'hy', 'hy-AM', 'ia', 'ia-001', 'id', 'id-ID', 'ig', 'ig-NG', 'ii', 'ii-CN', 'io', 'io-001', 'is', 'is-IS', 'it', 'it-CH', 'it-IT', 'it-SM', 'it-VA', 'iu', 'iu-CA', 'ja', 'ja-JP', 'jbo', 'jbo-001', 'jgo', 'jgo-CM', 'jmc', 'jmc-TZ', 'jv', 'jv-ID', 'ka', 'ka-GE', 'kab', 'kab-DZ', 'kaj', 'kaj-NG', 'kam', 'kam-KE', 'kcg', 'kcg-NG', 'kde', 'kde-TZ', 'kea', 'kea-CV', 'khq', 'khq-ML', 'ki', 'ki-KE', 'kk', 'kk-KZ', 'kkj', 'kkj-CM', 'kl', 'kl-GL', 'kln', 'kln-KE', 'km', 'km-KH', 'kn', 'kn-IN', 'ko', 'ko-KP', 'ko-KR', 'kok', 'kok-IN', 'kpe', 'kpe-GN', 'kpe-LR', 'ks', 'ks-Arab', 'ks-Arab-IN', 'ks-Aran', 'ks-Aran-IN', 'ks-Deva', 'ks-IN', 'ksb', 'ksb-TZ', 'ksf', 'ksf-CM', 'ksh', 'ksh-DE', 'ku', 'ku-TR', 'kw', 'kw-GB', 'ky', 'ky-KG', 'lag', 'lag-TZ', 'lb', 'lb-LU', 'lg', 'lg-UG', 'lkt', 'lkt-US', 'ln', 'ln-AO', 'ln-CD', 'ln-CF', 'ln-CG', 'lo', 'lo-LA', 'lrc', 'lrc-IQ', 'lrc-IR', 'lt', 'lt-LT', 'lu', 'lu-CD', 'luo', 'luo-KE', 'luy', 'luy-KE', 'lv', 'lv-LV', 'mas', 'mas-KE', 'mas-TZ', 'mer', 'mer-KE', 'mfe', 'mfe-MU', 'mg', 'mg-MG', 'mgh', 'mgh-MZ', 'mgo', 'mgo-CM', 'mi', 'mi-NZ', 'mk', 'mk-MK', 'ml', 'ml-IN', 'mn', 'mn-MN', 'mni', 'mni-Beng', 'mni-Beng-IN', 'mni-Mtei', 'mni-Mtei-IN', 'moh', 'moh-CA', 'mr', 'mr-IN', 'ms', 'ms-Arab', 'ms-Arab-BN', 'ms-Arab-MY', 'ms-BN', 'ms-MY', 'ms-SG', 'mt', 'mt-MT', 'mua', 'mua-CM', 'my', 'my-MM', 'myv', 'myv-RU', 'mzn', 'mzn-IR', 'naq', 'naq-NA', 'nb', 'nb-NO', 'nb-SJ', 'nd', 'nd-ZW', 'nds', 'nds-DE', 'nds-NL', 'ne', 'ne-IN', 'ne-NP', 'nl', 'nl-AW', 'nl-BE', 'nl-BQ', 'nl-CW', 'nl-NL', 'nl-SR', 'nl-SX', 'nmg', 'nmg-CM', 'nn', 'nn-NO', 'nnh', 'nnh-CM', 'nqo', 'nqo-GN', 'nr', 'nr-ZA', 'nso', 'nso-ZA', 'nus', 'nus-SS', 'ny', 'ny-MW', 'nyn', 'nyn-UG', 'oc', 'oc-FR', 'om', 'om-ET', 'om-KE', 'or', 'or-IN', 'os', 'os-GE', 'os-RU', 'pa', 'pa-Arab', 'pa-Arab-PK', 'pa-Aran', 'pa-Aran-PK', 'pa-Guru', 'pa-Guru-IN', 'pl', 'pl-PL', 'ps', 'ps-AF', 'ps-PK', 'pt', 'pt-AO', 'pt-BR', 'pt-CH', 'pt-CV', 'pt-FR', 'pt-GQ', 'pt-GW', 'pt-LU', 'pt-MO', 'pt-MZ', 'pt-PT', 'pt-ST', 'pt-TL', 'qu', 'qu-BO', 'qu-EC', 'qu-PE', 'rm', 'rm-CH', 'rn', 'rn-BI', 'ro', 'ro-MD', 'ro-RO', 'rof', 'rof-TZ', 'ru', 'ru-BY', 'ru-KG', 'ru-KZ', 'ru-MD', 'ru-RU', 'ru-UA', 'rw', 'rw-RW', 'rwk', 'rwk-TZ', 'sa', 'sa-IN', 'sah', 'sah-RU', 'saq', 'saq-KE', 'sat', 'sat-Deva', 'sat-Deva-IN', 'sat-Olck', 'sat-Olck-IN', 'sbp', 'sbp-TZ', 'sc', 'sc-IT', 'scn', 'scn-IT', 'sd', 'sd-Deva', 'sd-PK', 'se', 'se-FI', 'se-NO', 'se-SE', 'seh', 'seh-MZ', 'ses', 'ses-ML', 'sg', 'sg-CF', 'shi', 'shi-Latn', 'shi-Latn-MA', 'shi-Tfng', 'shi-Tfng-MA', 'si', 'si-LK', 'sk', 'sk-SK', 'sl', 'sl-SI', 'smn', 'smn-FI', 'sn', 'sn-ZW', 'so', 'so-DJ', 'so-ET', 'so-KE', 'so-SO', 'sq', 'sq-AL', 'sq-MK', 'sq-XK', 'sr', 'sr-Cyrl', 'sr-Cyrl-BA', 'sr-Cyrl-ME', 'sr-Cyrl-RS', 'sr-Cyrl-XK', 'sr-Latn', 'sr-Latn-BA', 'sr-Latn-ME', 'sr-Latn-RS', 'sr-Latn-XK', 'ss', 'ss-SZ', 'ss-ZA', 'st', 'st-LS', 'st-ZA', 'sv', 'sv-AX', 'sv-FI', 'sv-SE', 'sw', 'sw-CD', 'sw-KE', 'sw-TZ', 'sw-UG', 'syr', 'syr-IQ', 'syr-SY', 'ta', 'ta-IN', 'ta-LK', 'ta-MY', 'ta-SG', 'te', 'te-IN', 'teo', 'teo-KE', 'teo-UG', 'tg', 'tg-TJ', 'th', 'th-TH', 'ti', 'ti-ER', 'ti-ET', 'tig', 'tig-ER', 'tk', 'tk-TM', 'tn', 'tn-BW', 'tn-ZA', 'to', 'to-TO', 'tr', 'tr-CY', 'tr-TR', 'trv', 'trv-TW', 'ts', 'ts-ZA', 'tt', 'tt-RU', 'twq', 'twq-NE', 'tzm', 'tzm-MA', 'ug', 'ug-CN', 'uk', 'uk-UA', 'ur', 'ur-Arab', 'ur-Arab-IN', 'ur-Arab-PK', 'ur-Aran', 'ur-Aran-IN', 'ur-Aran-PK', 'ur-IN', 'ur-PK', 'uz', 'uz-Arab', 'uz-Arab-AF', 'uz-Cyrl', 'uz-Cyrl-UZ', 'uz-Latn', 'uz-Latn-UZ', 'vai', 'vai-Latn', 'vai-Latn-LR', 'vai-Vaii', 'vai-Vaii-LR', 've', 've-ZA', 'vi', 'vi-VN', 'vun', 'vun-TZ', 'wa', 'wa-BE', 'wae', 'wae-CH', 'wal', 'wal-ET', 'wo', 'wo-SN', 'wuu', 'xh', 'xh-ZA', 'xog', 'xog-UG', 'yav', 'yav-CM', 'yi', 'yi-001', 'yo', 'yo-BJ', 'yo-NG', 'yue', 'yue-Hans', 'yue-Hans-CN', 'yue-Hant', 'yue-Hant-HK', 'zgh', 'zgh-MA', 'zh', 'zh-Hans', 'zh-Hans-CN', 'zh-Hans-HK', 'zh-Hans-MO', 'zh-Hans-SG', 'zh-Hant', 'zh-Hant-CN', 'zh-Hant-HK', 'zh-Hant-MO', 'zh-Hant-TW', 'zu', 'zu-ZA')]
[ValidateNotNull()]
[string]
${Culture},
[Parameter(ParameterSetName = 'ObjectRaw', Mandatory, ValueFromPipeline)]
[Parameter(ParameterSetName = 'Object', Mandatory, ValueFromPipeline)]
[AllowEmptyString()]
[AllowNull()]
[psobject]
${InputObject},
[Parameter(Mandatory, Position = 0)]
[string[]]
${Pattern},
[Parameter(ParameterSetName = 'FileRaw', Mandatory, Position = 1, ValueFromPipelineByPropertyName)]
[Parameter(ParameterSetName = 'File', Mandatory, Position = 1, ValueFromPipelineByPropertyName)]
[string[]]
${Path},
[Parameter(ParameterSetName = 'LiteralFileRaw', Mandatory, ValueFromPipelineByPropertyName)]
[Parameter(ParameterSetName = 'LiteralFile', Mandatory, ValueFromPipelineByPropertyName)]
[Alias('PSPath', 'LP')]
[string[]]
${LiteralPath},
[Parameter(ParameterSetName = 'LiteralFileRaw', Mandatory)]
[Parameter(ParameterSetName = 'FileRaw', Mandatory)]
[Parameter(ParameterSetName = 'ObjectRaw', Mandatory)]
[switch]
${Raw},
[switch]
${SimpleMatch},
[switch]
${CaseSensitive},
[Parameter(ParameterSetName = 'File')]
[Parameter(ParameterSetName = 'Object')]
[Parameter(ParameterSetName = 'LiteralFile')]
[switch]
${Quiet},
[switch]
${List},
[switch]
${NoEmphasis},
[ValidateNotNullOrEmpty()]
[string[]]
${Include},
[ValidateNotNullOrEmpty()]
[string[]]
${Exclude},
[switch]
${NotMatch},
[switch]
${AllMatches},
[ValidateNotNullOrEmpty()]
[System.Text.Encoding]
${Encoding},
[ValidateRange(0, 2147483647)]
[ValidateNotNullOrEmpty()]
[ValidateCount(1, 2)]
[int[]]
${Context})
begin {
# Ignore parameters that are only supported in v7+
if ($PSVersionTable.PSVersion.Major -lt 7) {
('Culture', 'Raw', 'NoEmphasis').ForEach( {
if ($PSBoundParameters.ContainsKey($_)) {
$null = $PSBoundParameters.Remove($_)
Write-Warning "Ignoring parameter $_, because it is only supported in PowerShell 7.0 or above."
}
})
}
# Set up the steppable pipeline.
try {
$commandToWrap = { Out-String -Stream | Select-String @PSBoundParameters }
$steppablePipeline = $commandToWrap.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
process {
$steppablePipeline.Process($_)
}
end {
$steppablePipeline.End()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With