 |
|
Cmdlet Extension Library
Category: Windows general
Contributed by Kirk Munro (Poshoholic) on 2007-11-27, last updated 2008-01-15 • user rating:     5Description:
This script contains a library of useful functions and will grow over time. In its current revision its purpose is as follows:
1. To extend Get-Help so that the cmdlet help documentation for core cmdlets includes all dynamic parameter information as well.
2. To provide Get-PSResourceString to help support script internationalization.
3. To provide Invoke-Member to help ease the invocation of members within a pipeline.
4. To provide a version of Should-Process that supports localized PowerShell.
Note that when extending cmdlets I have tried to ensure that the original cmdlet and the corresponding cmdlet extension function can be used interchangeably in scripts without requiring any modifications. The only known exception to this is when scripts are modified to explicitly use some information that is only exposed by the function extending the cmdlet.
Also I have made an effort to support localized versions of PowerShell in these functions as well by using the resource strings that come with PowerShell for the current culture through the Get-PSResourceString cmdlet. There are a few strings that will still only be available in English though, such as variable and alias descriptions.
Non-core snapins required to run this:
None
Formatted code:
1 ########################################################################################################################
2 # #
3 # File: CmdletExtensionLibrary.ps1 #
4 # Author: Kirk Munro #
5 # Author's Blog: http://poshoholic.com #
6 # Revision: 1.0.3 #
7 # Contents: A collection of functions designed with two purposes in mind: #
8 # 1. To seamlessly extend published cmdlet functionality transparently to the end user #
9 # 2. To wrap common operations in fully documented, well named functions designed to extend #
10 # PowerShell's core set of features #
11 # In the first case, every effort is made to ensure that the original cmdlet and the corresponding #
12 # function can be used interchangeably in scripts without requiring any modifications. The only #
13 # known exception to this is when scripts are modified to explicitly use some information that is #
14 # only exposed by the function extending the cmdlet. #
15 # In the second case, functionality is being exposed as functions to solicit community feedback. It #
16 # is my intention to publish these sorts of functions as cmdlets in the future. #
17 # History: v1.0.0 - Initial release designed to enhance support for dynamic parameters in the PowerShell help #
18 # system #
19 # v1.0.1 - Addition of Invoke-Member function to allow users to invoke any member on a data set #
20 # without having to use ForEach-Object #
21 # v1.0.2 - Fixed grs alias for Get-PSResourceString #
22 # - Added ... alias for Invoke-Member #
23 # - Added pipeline support to Invoke-Cmdlet, Add-PSSnapin, Remove-PSSnapin and Get-Help #
24 # v1.0.3 - Added retrieval of Microsoft.PowerShell.ConsoleHost strings to Get-PSResourceString #
25 # - Added -list parameter to Get-PSResourceString #
26 # - Added more examples to Get-PSResourceString documentation (comments) #
27 # - Added Should-Process function to provide -whatif, -confirm and -verbose support to other #
28 # functions #
29 # - Added -whatif, -confirm and -verbose support to Invoke-Member function #
30 # #
31 ########################################################################################################################
32
33 ########################################################################################################################
34 # NAME
35 # Get-PSResourceString
36 #
37 # SYNOPSIS
38 # Returns a resource string that is looked up in the System.Management.Automation namespace or the
39 # Microsoft.PowerShell.ConsoleHost namespace, or a list of resource root names or resource identifiers that are
40 # available.
41 #
42 # SYNTAX
43 # Get-PSResourceString [-baseName] <string> [-resourceId] <string> [[-defaultValue] <string>]
44 # [[-culture] <System.Globalization.CultureInfo>]
45 # Get-PSResourceString [[-baseName] <string>] -list
46 #
47 # DETAILED DESCRIPTION
48 # The Get-PSResourceString function returns a resource string that is looked up in the System.Management.Automation
49 # namespace or the Microsoft.PowerShell.ConsoleHost namespace, or a list of resource root names or resource
50 # identifiers that are available. If a resource string was requested and it is not found, the default value (if
51 # present) will be returned.
52 #
53 # PARAMETERS
54 # -baseName <string>
55 # Specifies the root name of the resources.
56 #
57 # Required? true
58 # Position? 1
59 # Default value
60 # Accept pipeline input? false
61 # Accept wildcard characters? false
62 #
63 # -resourceId <string>
64 # Specifies the identifier of the resource that is being retrieved.
65 #
66 # Required? true
67 # Position? 2
68 # Default value
69 # Accept pipeline input? false
70 # Accept wildcard characters? false
71 #
72 # -defaultValue <string>
73 # Specifies the default value for the resource string. If the string is not found, the default value will be
74 # returned.
75 #
76 # Required? false
77 # Position? 3
78 # Default value null
79 # Accept pipeline input? false
80 # Accept wildcard characters? false
81 #
82 # -culture <System.Globalization.CultureInfo>
83 # Specifies the culture to use when looking up the resource string.
84 #
85 # Required? false
86 # Position? 4
87 # Default value $host.CurrentCulture
88 # Accept pipeline input? false
89 # Accept wildcard characters? false
90 #
91 # -list <Switch>
92 # When this parameter is used by itself, this function outputs the root names that are available. When this
93 # parameter is used in conjunction with the baseName parameter, this function outputs the resource identifiers
94 # that are availab.e
95 #
96 # Required? false
97 # Position? named
98 # Default value false
99 # Accept pipeline input? false
100 # Accept wildcard characters? false
101 #
102 # INPUT TYPE
103 # String,System.Globalization.CultureInfo,Switch
104 #
105 # RETURN TYPE
106 # String,String[]
107 #
108 # NOTES
109 # For more information the System.Globalization.CultureInfo type consult the relevant MSDN documentation.
110 #
111 # -------------------------- EXAMPLE 1 --------------------------
112 #
113 # C:\PS>get-psresourcestring -list
114 #
115 #
116 # This command retrieves the list of resource root names that are available.
117 #
118 #
119 # -------------------------- EXAMPLE 2 --------------------------
120 #
121 # C:\PS>get-psresourcestring -basename helpdisplaystrings -list
122 #
123 #
124 # This command retrieves the list of resource strings in the resource root called 'helpdisplaystrings' using the
125 # current culture.
126 #
127 #
128 # -------------------------- EXAMPLE 3 --------------------------
129 #
130 # C:\PS>get-psresourcestring -list | foreach-object { get-psresourcestring -basename $_ -list }
131 #
132 #
133 # This command retrieves all resource strings that are available using the current culture.
134 #
135 #
136 # -------------------------- EXAMPLE 4 --------------------------
137 #
138 # C:\PS>get-psresourcestring -basename helpdisplaystrings -resourceid falseshort
139 #
140 #
141 # This command retrieves the string associated with the 'falseshort' resource id using the current culture.
142 #
143 #
144
145 Function Get-PSResourceString {
146 param(
147 [string]$baseName = $null,
148 [string]$resourceId = $null,
149 [string]$defaultValue = $null,
150 [System.Globalization.CultureInfo]$culture = $host.CurrentCulture,
151 [Switch]$list
152 )
153
154 if ($list -and ($resourceId -or $defaultValue)) {
155 throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'AmbiguousParameterSet')
156 }
157
158 if ($list) {
159 $engineAssembly = [System.Reflection.Assembly]::GetExecutingAssembly()
160 $hostAssembly = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.PowerShell.ConsoleHost')
161 if ($baseName) {
162 $engineAssembly.GetManifestResourceNames() | Where-Object { $_ -eq "$baseName.resources" } | ForEach-Object {
163 $resourceManager = New-Object -TypeName System.Resources.ResourceManager($baseName, $engineAssembly)
164 $resourceManager.GetResourceSet($host.CurrentCulture,$true,$true) | Add-Member -Name BaseName -MemberType NoteProperty -Value $baseName -Force -PassThru | ForEach-Object {
165 $_.PSObject.TypeNames.Clear()
166 $_.PSObject.TypeNames.Add('ResourceString')
167 $_ | Write-Output
168 }
169 }
170 $hostAssembly.GetManifestResourceNames() | Where-Object { $_ -eq "$baseName.resources" } | ForEach-Object {
171 $resourceManager = New-Object -TypeName System.Resources.ResourceManager($baseName, $hostAssembly)
172 $resourceManager.GetResourceSet($host.CurrentCulture,$true,$true) | Add-Member -Name BaseName -MemberType NoteProperty -Value $baseName -Force -PassThru | ForEach-Object {
173 $_.PSObject.TypeNames.Clear()
174 $_.PSObject.TypeNames.Add('ResourceString')
175 $_ | Write-Output
176 }
177 }
178 } else {
179 $engineAssembly.GetManifestResourceNames() | Where-Object { $_ -match '\.resources$' } | ForEach-Object { $_.Replace('.resources','') }
180 $hostAssembly.GetManifestResourceNames() | Where-Object { $_ -match '\.resources$' } | ForEach-Object { $_.Replace('.resources','') }
181 }
182 } else {
183 if (-not $baseName) {
184 throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'BaseName')
185 }
186 if (-not $resourceId) {
187 throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'ResourceId')
188 }
189 if (-not $global:PSResourceStringTable) {
190 $engineAssembly = [System.Reflection.Assembly]::GetExecutingAssembly()
191 $hostAssembly = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.PowerShell.ConsoleHost')
192 if ($engineAssembly.GetManifestResourceNames() -contains "$baseName.resources") {
193 New-Variable -Scope Global -Name PSResourceStringTable -Value @{} -Description 'A cache of PowerShell resource strings. To access data in this table, use Get-ResourceString.'
194 $global:PSResourceStringTable['EngineAssembly'] = @{'Assembly'=$engineAssembly;'Cultures'=@{}}
195 $global:PSResourceStringTable['HostAssembly'] = @{'Assembly'=$hostAssembly;'Cultures'=@{}}
196 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
197 $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
198 } elseif ($hostAssembly.GetManifestResourceNames() -contains "$baseName.resources") {
199 New-Variable -Scope Global -Name PSResourceStringTable -Value @{} -Description 'A cache of PowerShell resource strings. To access data in this table, use Get-ResourceString.'
200 $global:PSResourceStringTable['EngineAssembly'] = @{'Assembly'=$engineAssembly;'Cultures'=@{}}
201 $global:PSResourceStringTable['HostAssembly'] = @{'Assembly'=$hostAssembly;'Cultures'=@{}}
202 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
203 $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
204 }
205 } elseif ($global:PSResourceStringTable.EngineAssembly.Assembly.GetManifestResourceNames() -contains "$baseName.resources") {
206 if (-not $global:PSResourceStringTable.EngineAssembly.Cultures.ContainsKey($culture.Name)) {
207 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
208 $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
209 } elseif (-not $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
210 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
211 $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name][$baseName] = @{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)};
212 }
213 } elseif ($global:PSResourceStringTable.HostAssembly.Assembly.GetManifestResourceNames() -contains "$baseName.resources") {
214 if (-not $global:PSResourceStringTable.HostAssembly.Cultures.ContainsKey($culture.Name)) {
215 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
216 $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
217 } elseif (-not $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
218 $resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
219 $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name][$baseName] = @{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)};
220 }
221 }
222
223 $resourceString = $null
224 if ($global:PSResourceStringTable) {
225 if ($global:PSResourceStringTable.EngineAssembly.Cultures -and $global:PSResourceStringTable.EngineAssembly.Cultures.ContainsKey($culture.Name) -and $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
226 $resourceString = ($global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name][$baseName].Strings | Where-Object { $_.Name -eq $resourceId }).Value
227 } elseif ($global:PSResourceStringTable.HostAssembly.Cultures -and $global:PSResourceStringTable.HostAssembly.Cultures.ContainsKey($culture.Name) -and $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
228 $resourceString = ($global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name][$baseName].Strings | Where-Object { $_.Name -eq $resourceId }).Value
229 }
230 }
231 if (-not $resourceString) {
232 $resourceString = $defaultValue
233 }
234
235 return $resourceString
236 }
237 }
238
239 if (-not (Get-Alias -Name grs -ErrorAction SilentlyContinue)) {
240 New-Alias -Name grs -Value Get-PSResourceString -Description 'Returns a resource string that is looked up in the System.Management.Automation namespace.'
241 }
242
243 ########################################################################################################################
244 # NAME
245 # Should-Process
246 #
247 # SYNOPSIS
248 # Determines whether the specified operation should be performed on the target object.
249 #
250 # SYNTAX
251 # Should-Process [-operation] <string> [-target] <string> [-whatIf]
252 # Should-Process [-operation] <string> [-target] <string> [-confirmResponse] <REF> [[-confirmPrompt] <string>]
253 # [-confirm]
254 # Should-Process [-operation] <string> [-target] <string> [-verbose]
255 #
256 # DETAILED DESCRIPTION
257 # Determines whether the specified operation should be performed on the target object. Returns true if the operation
258 # should be performed. Should-Process never performs the operation; it just indicates whether or not it should be
259 # performed to the caller. If the whatIf switch is used, Should-Process outputs strings indicating what it would do
260 # if whatIf wasn't used. If the confirm switch is used, Should-Process asks the user to confirm that they want to
261 # perform the operation. If the verbose switch is used, Should-Process writes verbose output for each operation that
262 # will be performed on each target.
263 #
264 # PARAMETERS
265 # -operation <string>
266 # Specifies the name of the function that was invoked.
267 #
268 # Required? true
269 # Position? 1
270 # Default value
271 # Accept pipeline input? false
272 # Accept wildcard characters? false
273 #
274 # -target <string>
275 # Specifies the identifier of the object that is being used in the operation.
276 #
277 # Required? true
278 # Position? 2
279 # Default value
280 # Accept pipeline input? false
281 # Accept wildcard characters? false
282 #
283 # -confirmResponse <REF>
284 # Reference variable that retains any confirm question response that applies to all objects being processed.
285 #
286 # Required? true
287 # Position? 3
288 # Default value
289 # Accept pipeline input? false
290 # Accept wildcard characters? false
291 #
292 # -confirmPrompt <string>
293 # Specifies the string that will be displayed to the caller when the -confirm switch is used.
294 #
295 # Required? false
296 # Position? 4
297 # Default value Are you sure you want to perform this action?
298 # Accept pipeline input? false
299 # Accept wildcard characters? false
300 #
301 # -verbose <switch>
302 # When this parameter is used, this function outputs verbose information to the host.
303 #
304 # Required? false
305 # Position? named
306 # Default value
307 # Accept pipeline input? false
308 # Accept wildcard characters? false
309 #
310 # -confirm <switch>
311 # When this parameter is used, this function requests confirmation from the user for the actions it will take.
312 #
313 # Required? false
314 # Position? named
315 # Default value
316 # Accept pipeline input? false
317 # Accept wildcard characters? false
318 #
319 # -whatif <switch>
320 # When this parameter is used, this function outputs what it would do without actually taking action.
321 #
322 # Required? false
323 # Position? named
324 # Default value
325 # Accept pipeline input? false
326 # Accept wildcard characters? false
327 #
328 # INPUT TYPE
329 # String,Ref,Switch
330 #
331 # RETURN TYPE
332 # Boolean
333 #
334 # NOTES
335 # Whatif takes precedence over confirm. Confirm takes precedence over verbose. If more than one switch parameter is
336 # used, this precedence order will be followed and only the highest precedence switch will be used.
337 #
338 # The ConfirmResponse reference parameter is used to determine if "YES to All" or "NO to all" has been previously
339 # selected.
340 #
341 # When using Should-Process inside of functions that can be used in a pipeline, you should initialize your reference
342 # variable in the begin block and then call Should-Process in the process block.
343 #
344 # -------------------------- EXAMPLE 1 --------------------------
345 #
346 #
347 # C:\PS>function Stop-Calc ([Switch]$Verbose, [Switch]$Confirm, [Switch]$Whatif) {
348 # $ConfirmResponse = $null
349 # foreach ($p in Get-Process calc) {
350 # if (Should-Process Stop-Calc $p.Id ([REF]$ConfirmResponse) `
351 # -Verbose:$Verbose -Confirm:$Confirm -Whatif:$Whatif) {
352 # Stop-Process $p.Id
353 # }
354 # }
355 # }
356 # C:\PS>stop-calc -confirm
357 #
358 #
359 # This prompts you to confirm you want to stop all calc processes when using the simple Stop-Process function.
360 #
361 #
362 # RELATED LINKS
363 # about_commonparameters
364 # about_ref
365 #
366
367 Function Should-Process {
368 param(
369 [string]$Operation = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Operation')),
370 [string]$Target = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Target')),
371 [REF]$ConfirmResponse = ([REF]$null),
372 [string]$ConfirmPrompt = $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessWarningFallback') -f $null),
373 [Switch]$Verbose,
374 [Switch]$Confirm,
375 [Switch]$Whatif
376 )
377
378 if ($ConfirmResponse.Value -eq $false) {
379 return $false
380 } elseif ($ConfirmResponse.Value -eq $true) {
381 return $true
382 }
383
384 if ($Whatif) {
385 Write-Host $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessWhatIfMessage') -f $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target))
386 return $false
387 } elseif ($Confirm) {
388 $ConfirmText = @"
389 $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'InquireCaptionDefault')
390 $ConfirmPrompt
391 $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target)
392 "@
393 Write-Host $ConfirmText
394 $Yes = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueOneLabel')
395 $All = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueAllLabel')
396 $No = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipOneLabel')
397 $None = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipAllLabel')
398 $Suspend = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'PauseLabel')
399 $Help = $(Get-PSResourceString -BaseName 'ConsoleHostUserInterfaceStrings' -ResourceId 'PromptForChoiceHelp')
400
401 $YesHotkey = $Yes.ToUpper()[$Yes.IndexOf('&') + 1]
402 $AllHotkey = $All.ToUpper()[$All.IndexOf('&') + 1]
403 $NoHotkey = $No.ToUpper()[$No.IndexOf('&') + 1]
404 $NoneHotkey = $None.ToUpper()[$None.IndexOf('&') + 1]
405 $SuspendHotkey = $Suspend.ToUpper()[$Suspend.IndexOf('&') + 1]
406 $HelpHotkey = $Help.ToUpper()[$Help.IndexOf('[') + 1]
407
408 $YesHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueOneHelpMessage')
409 $AllHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueAllHelpMessage')
410 $NoHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipOneHelpMessage')
411 $NoneHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipAllHelpMessage')
412 $SuspendHelp = $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'PauseHelpMessage') -f 'exit')
413 $DefaultValue = $($(Get-PSResourceString -BaseName 'ConsoleHostUserInterfaceStrings' -ResourceId 'DefaultChoicePrompt') -f $YesHotKey)
414
415 while ($true) {
416 $answer = Read-Host @"
417 [$YesHotkey] $($Yes.Replace('&','')) [$AllHotkey] $($All.Replace('&','')) [$NoHotkey] $($No.Replace('&','')) [$NoneHotkey] $($None.Replace('&','')) [$SuspendHotkey] $($Suspend.Replace('&','')) $Help $DefaultValue
418 "@
419 switch ($answer) {
420 "$YesHotkey" { return $true }
421 "" { return $true }
422 "$AllHotkey" { $ConfirmResponse.Value = $true; return $true }
423 "$NoHotkey" { return $false }
424 "$NoneHotkey" { $ConfirmResponse.Value = $false; return $false }
425 "$SuspendHotkey" { $host.EnterNestedPrompt(); Write-Host $ConfirmText }
426 "$HelpHotkey" { Write-Host @"
427 $YesHotkey - $YesHelp
428 $AllHotkey - $AllHelp
429 $NoHotkey - $NoHelp
430 $NoneHotkey - $NoneHelp
431 $SuspendHotkey - $SuspendHelp
432 "@
433 }
434 }
435 }
436 } elseif ($verbose) {
437 Write-Verbose $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target)
438 }
439
440 return $true
441 }
442
443 if (-not (Get-Alias -Name sps -ErrorAction SilentlyContinue)) {
444 New-Alias -Name sps -Value Should-Process -Description 'Determines whether the specified operation should be performed on the target object. Returns true if the operation should be performed.'
445 }
446
447 ########################################################################################################################
448 # NAME
449 # Invoke-Member
450 #
451 # SYNOPSIS
452 # Invoke members of each of a set of input objects.
453 #
454 # SYNTAX
455 # Invoke-Member [-name] <string[]> [[-inputObject] <psobject>] [-whatif] [-confirm] [-verbose]
456 #
457 # DETAILED DESCRIPTION
458 # Invokes a member of each of a set of input objects. The input objects can be piped to the cmdlet or specified by
459 # using the InputObject parameter. If an input object does not have the specified member, it will be skipped. The
460 # results of the invocation of the members are passed down the pipeline.
461 #
462 # PARAMETERS
463 # -name <string[]>
464 # Specifies the name of the member to invoke. For members that accept parameters, pass the member name with the
465 # parameters in parentheses inside of quotation marks.
466 #
467 # Required? true
468 # Position? 1
469 # Default value
470 # Accept pipeline input? false
471 # Accept wildcard characters? false
472 #
473 # -inputObject <psobject>
474 # Accepts an object for which the member will be invoked. Enter a variable that contains the objects or type a
475 # command or expression that gets the objects.
476 #
477 # Required? false
478 # Position? 2
479 # Default value
480 # Accept pipeline input? true (ByValue)
481 # Accept wildcard characters? false
482 #
483 # -whatIf
484 # Describes what would happen if you executed the command without actually executing the command.
485 #
486 # Required? false
487 # Position? named
488 # Default value
489 # Accept pipeline input? false
490 # Accept wildcard characters? false
491 #
492 # -confirm
493 # Prompts you for confirmation before executing the command.
494 #
495 # Required? false
496 # Position? named
497 # Default value
498 # Accept pipeline input? false
499 # Accept wildcard characters? false
500 #
501 # <CommonParameters>
502 # This cmdlet supports the common parameters: -Verbose. For more information, type,
503 # "get-help about_commonparameters".
504 #
505 # INPUT TYPE
506 # String[],PSObject
507 #
508 # RETURN TYPE
509 # Object
510 #
511 # NOTES
512 # When a collection of objects is passed in via the InputObject parameter, the member will be invoked on the
513 # collection object, not on the items in the collection.
514 #
515 #
516 # -------------------------- EXAMPLE 1 --------------------------
517 #
518 # C:\PS>get-childitem -literalpath C:\ -force | invoke-member -name PSObject.typenames | select-object -unique
519 #
520 #
521 # This command retrieves all unique base and derived object type names.
522 #
523 #
524 # -------------------------- EXAMPLE 2 --------------------------
525 #
526 # C:\PS>get-help -category cmdlet | sort-object -property name | invoke-member -name syntax
527 #
528 #
529 # This command retrieves a sorted list of the syntax for all cmdlets based on help information.
530 #
531 #
532 # RELATED LINKS
533 # Get-Member
534 # Invoke-Expression
535 # ForEach-Object
536 #
537
538 Function Invoke-Member {
539 param (
540 [string[]]$name = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Name')),
541 $inputObject = $null,
542 [Switch]$whatif,
543 [Switch]$confirm,
544 [Switch]$verbose
545 )
546
547 BEGIN {
548 $confirmResponse = $null
549 }
550 PROCESS {
551 if ($inputObject -and $_) {
552 throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'InputObjectNotBound')
553 break
554 } elseif ($inputObject) {
555 foreach ($member in $name) {
556 if (Should-Process Invoke-Member $member ([REF]$confirmResponse) -Verbose:$verbose -Confirm:$confirm -Whatif:$whatif) {
557 Invoke-Expression "`$inputObject.$member"
558 }
559 }
560 } elseif ($_) {
561 foreach ($member in $name) {
562 if (Should-Process Invoke-Member $member ([REF]$confirmResponse) -Verbose:$verbose -Confirm:$confirm -Whatif:$whatif) {
563 Invoke-Expression "`$_.$member"
564 }
565 }
566 } else {
567 throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'AmbiguousParameterSet')
568 }
569 }
570 END {
571 }
572 }
573
574 if (-not (Get-Alias -Name im -ErrorAction SilentlyContinue)) {
575 New-Alias -Name im -Value Invoke-Member -Description 'Invokes a member of each of a set of input objects.'
576 }
577
578 if (-not (Get-Alias -Name ... -ErrorAction SilentlyContinue)) {
579 New-Alias -Name ... -Value Invoke-Member -Description 'Invokes a member of each of a set of input objects.'
580 }
581
582 ########################################################################################################################
583 # NAME
584 # Invoke-Cmdlet
585 #
586 # SYNOPSIS
587 # Invokes a cmdlet by using its fully qualified name.
588 #
589 # SYNTAX
590 # Invoke-Cmdlet [-cmdletName] <string> [<CmdletParameters>]
591 #
592 # DETAILED DESCRIPTION
593 # The Invoke-Cmdlet function invokes a cmdlet directly by using its fully qualified name. This allows cmdlets to be
594 # invoked even if there are functions or aliases with the same name. It follows Microsoft's house rules whereby the
595 # core snapins take precedence over added snapins.
596 #
597 # PARAMETERS
598 # -cmdletName <string>
599 # Specifies the name of a cmdlet. When this parameter is used, this function invokes the cmdlet identified by
600 # this parameter.
601 #
602 # Required? true
603 # Position? 1
604 # Default value
605 # Accept pipeline input? false
606 # Accept wildcard characters? false
607 #
608 # <CmdletParameters>
609 # This cmdlet supports all parameters that are supported by the cmdlet being invoked. Consult the cmdlet help
610 # parameter list for more information.
611 #
612 # INPUT TYPE
613 # String
614 #
615 # RETURN TYPE
616 # Consult the cmdlet help return type for more information.
617 #
618 # NOTES
619 # For more information, consult the help documentation for the cmdlet that you are invoking.
620 #
621 # Cmdlets that have a cmdletName parameter are not supported by this cmdlet.
622 #
623 # -------------------------- EXAMPLE 1 --------------------------
624 #
625 # C:\PS>invoke-cmdlet get-help * -parameter codesigningcert
626 #
627 #
628 # This command gets all commands that have a CodeSigningCert parameter. This will only include those cmdlets whose
629 # documentation specifically includes the CodeSigningCert parameter unless the CmdletExtensionLibrary is being used
630 # and the Get-Help function has been called at least once.
631 #
632 # RELATED LINKS
633 # Get-Command
634 # Invoke-Expression
635 #
636
637 Function Invoke-Cmdlet {
638 param([string]$cmdletName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'CmdletName')))
639
640 BEGIN {
641 $matchingCmdlets = Microsoft.PowerShell.Core\Get-Command -CommandType cmdlet -Name $cmdletName
642 if (@($matchingCmdlets).Count -eq 0) {
643 throw $($(Get-PSResourceString -BaseName 'DiscoveryExceptions' -ResourceId 'CmdletNotFoundException') -f 'CmdletName',$cmdletName)
644 }
645 $cmdletName = $null
646 foreach ($cmdlet in $matchingCmdlets) {
647 if ($cmdlet.PSSnapin.IsDefault) {
648 $cmdletName = "$($cmdlet.PSSnapin.Name)\$($cmdlet.Name)"
649 break
650 } elseif (-not $cmdletName) {
651 $cmdletName = "$($cmdlet.PSSnapin.Name)\$($cmdlet.Name)"
652 }
653 }
654 }
655 PROCESS {
656 if ($_) {
657 Microsoft.PowerShell.Utility\Invoke-Expression "`$_ | $cmdletName $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
658 } else {
659 Microsoft.PowerShell.Utility\Invoke-Expression "$cmdletName $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
660 }
661 }
662 END {
663 }
664 }
665
666 if (-not (Get-Alias -Name ic -ErrorAction SilentlyContinue)) {
667 New-Alias -Name ic -Value Invoke-Cmdlet -Description 'Invokes a cmdlet by using its fully qualified name.'
668 }
669
670 ########################################################################################################################
671 # NAME
672 # Get-DynamicParameterMap
673 #
674 # SYNOPSIS
675 # Displays a mapping of cmdlet names to dynamic parameters.
676 #
677 # SYNTAX
678 # Get-DynamicParameterMap [-refresh]
679 #
680 # DETAILED DESCRIPTION
681 # The Get-DynamicParameterMap function extracts the dynamic parameter help information from the PSProvider help
682 # documentation and builds a map of cmdlet names to dynamic parameters. If the map has already been built, it is
683 # immediately returned. If the Refresh switch parameter is used, the map is rebuilt.
684 #
685 # PARAMETERS
686 # -refresh <switch>
687 # When this parameter is used, this function reloads the dynamic parameter map before returning it to the
688 # caller.
689 #
690 # Required? false
691 # Position? named
692 # Default value
693 # Accept pipeline input? false
694 # Accept wildcard characters? false
695 #
696 # INPUT TYPE
697 # Switch
698 #
699 # RETURN TYPE
700 # Associative Array
701 #
702 # NOTES
703 # If multiple providers include a dynamic parameter with the same name but a different type or documentation, both
704 # versions will be used.
705 #
706 # -------------------------- EXAMPLE 1 --------------------------
707 #
708 # C:\PS>get-dynamicparametermap
709 #
710 #
711 # This command retrieves all dynamic parameter help documentation from the PSProviders that are loaded and returns
712 # an associative array mapping cmdlet names to dynamic parameters.
713 #
714 # RELATED LINKS
715 # Invoke-Cmdlet
716 # about_associative_array
717 #
718
719 Function Get-DynamicParameterMap {
720 param ([Switch]$Refresh)
721
722 if (($refresh) -or (-not $global:dynamicParameterMap)) {
723 Remove-Variable -Force -Scope Global -Name dynamicParameterMap -ErrorAction SilentlyContinue
724 New-Variable -Scope Global -Name dynamicParameterMap -Value @{} -Description 'Maps cmdlet names to dynamic parameter help information. This variable is managed via custom scripts that provide better support for dynamic parameters and should only be used by those custom scripts.'
725 Invoke-Cmdlet Get-Help -Category Provider -ErrorAction SilentlyContinue | ForEach-Object {
726 $providerHelp = $_
727 $_.DynamicParameters.DynamicParameter | Where-Object { $_.CmdletSupported } | ForEach-Object {
728 $type = New-Object -TypeName System.Management.Automation.PSObject
729 $type.PSObject.TypeNames.Clear()
730 $type.PSObject.TypeNames.Add('MamlCommandHelpInfo#type')
731 $type | Add-Member -Name name -MemberType NoteProperty -Value $_.Type.Name
732 $type | Add-Member -Name uri -MemberType NoteProperty -Value $([String]$null)
733 $description = New-Object -TypeName System.Management.Automation.PSObject
734 $description.PSObject.TypeNames.Clear()
735 $description.PSObject.TypeNames.Add('MamlParaTextItem')
736 $description.PSObject.TypeNames.Add('MamlTextItem')
737 $description | Add-Member -Name Text -MemberType NoteProperty -Value $_.Description
738 $descriptionArray = @($description)
739 foreach ($cmdletSupported in $_.CmdletSupported.Split(', ', [StringSplitOptions]::RemoveEmptyEntries)) {
740 if (-not $global:dynamicParameterMap.ContainsKey($cmdletSupported)) {
741 $global:dynamicParameterMap[$cmdletSupported] = @{$providerHelp.Name=@{$_.Name=@{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}}}
742 } elseif (-not $global:dynamicParameterMap[$cmdletSupported].ContainsKey($providerHelp.Name)) {
743 $global:dynamicParameterMap[$cmdletSupported][$providerHelp.Name] = @{$_.Name=@{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}}
744 } else {
745 $global:dynamicParameterMap[$cmdletSupported][$providerHelp.Name][$_.Name] = @{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}
746 }
747 }
748 }
749 }
750 foreach ($cmdlet in $global:dynamicParameterMap.Keys) {
751 Invoke-Cmdlet Get-Help -Name $cmdlet -Category Cmdlet -ErrorAction SilentlyContinue | ForEach-Object {
752 $_.Parameters.parameter = [System.Management.Automation.PSObject[]]($_.Parameters.parameter | Where-Object { $_.isDynamic -ne $true })
753 $_.Syntax.syntaxItem = [System.Management.Automation.PSObject[]]($_.Syntax.syntaxItem | Where-Object { $_.name -notmatch "`r`n" })
754 }
755 }
756 }
757 $global:dynamicParameterMap
758 }
759
760 ########################################################################################################################
761 # NAME
762 # Add-PSSnapin
763 #
764 # SYNOPSIS
765 # Wraps the Add-PSSnapin cmdlet. Consult the Add-PSSnapin cmdlet help for more information.
766 #
767 # SYNTAX
768 # Consult the Add-PSSnapin cmdlet help for the syntax.
769 #
770 # DETAILED DESCRIPTION
771 # Wraps the Add-PSSnapin cmdlet. After the Add-PSSnapin cmdlet returns, it recreates the dynamic parameter map.
772 #
773 # NOTES
774 # Consult the Add-PSSnapin cmdlet help for more information on syntax, detailed description, input types, return
775 # types, notes, examples, and related links.
776 #
777 # RELATED LINKS
778 # Add-PSSnapin (cmdlet)
779 #
780
781 Function Add-PSSnapin {
782 BEGIN {
783 }
784 PROCESS {
785 if ($_) {
786 Invoke-Expression "`$_ | Invoke-Cmdlet Add-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
787 } else {
788 Invoke-Expression "Invoke-Cmdlet Add-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
789 }
790 }
791 END {
792 Get-DynamicParameterMap -Refresh | Out-Null
793 }
794 }
795
796 ########################################################################################################################
797 # NAME
798 # Remove-PSSnapin
799 #
800 # SYNOPSIS
801 # Wraps the Remove-PSSnapin cmdlet. Consult the Remove-PSSnapin cmdlet help for more information.
802 #
803 # SYNTAX
804 # Consult the Remove-PSSnapin cmdlet help for the syntax.
805 #
806 # DETAILED DESCRIPTION
807 # Wraps the Remove-PSSnapin cmdlet. After the Remove-PSSnapin cmdlet returns, it recreates the dynamic parameter
808 # map.
809 #
810 # NOTES
811 # Consult the Remove-PSSnapin cmdlet help for more information on syntax, detailed description, input types, return
812 # types, notes, examples, and related links.
813 #
814 # RELATED LINKS
815 # Remove-PSSnapin (cmdlet)
816 #
817
818 Function Remove-PSSnapin {
819 BEGIN {
820 }
821 PROCESS {
822 if ($_) {
823 Invoke-Expression "`$_ | Invoke-Cmdlet Remove-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
824 } else {
825 Invoke-Expression "Invoke-Cmdlet Remove-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
826 }
827 }
828 END {
829 Get-DynamicParameterMap -Refresh | Out-Null
830 }
831 }
832
833 ########################################################################################################################
834 # NAME
835 # Get-Help
836 #
837 # SYNOPSIS
838 # Wraps the Get-Help cmdlet and integrates dynamic parameter help information. Consult the Get-Help cmdlet help for
839 # more information.
840 #
841 # SYNTAX
842 # Consult the Get-Help cmdlet help for the syntax.
843 #
844 # DETAILED DESCRIPTION
845 # Wraps the Get-Help cmdlet and integrates dynamic parameter help information. By default, dynamic parameters are
846 # not included in the help information for cmdlets. Consult the Get-Help cmdlet help or the provider specific help
847 # for more information.
848 #
849 # INPUT TYPE
850 # Consult the Get-Help cmdlet help for more information.
851 #
852 # RETURN TYPE
853 # Consult the Get-Help cmdlet help for more information.
854 #
855 # NOTES
856 # For more information, consult the help information for the Get-Help cmdlet.
857 #
858 # If multiple providers include a dynamic parameter with the same name but a different type or documentation, the
859 # documentation for the last one found will be used.
860 #
861 # -------------------------- EXAMPLE 1 --------------------------
862 #
863 # C:\PS>get-help * -parameter -codesigningcert
864 #
865 #
866 # This command gets all commands that have a CodeSigningCert parameter. This will include all cmdlets that support
867 # the dynamic CodeSigningCert parameter, including those cmdlets whose documentation specifically includes the
868 # CodeSigningCert parameter as well as those whose documentation does not specifically include the CodeSigningCert
869 # parameter but who support the parameter through a dynamic parameter that is included in a specific provider.
870 #
871 # RELATED LINKS
872 # Get-Help (cmdlet)
873 #
874
875 Function Get-Help {
876 BEGIN {
877 $resourceManager = New-Object -TypeName System.Resources.ResourceManager('HelpDisplayStrings', [System.Reflection.Assembly]::GetExecutingAssembly())
878 $falseString = $resourceManager.GetString('FalseShort')
879 $namedString = $resourceManager.GetString('NamedParameter')
880
881 $createDynamicParameterHelpInfoScriptBlock = {
882 param(
883 $dynamicParameterName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterName')),
884 $dynamicParameterInfo = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterInfo'))
885 )
886
887 $shortTypeName = Invoke-Expression "[$($dynamicParameterInfo.Type.Name)].Name"
888 $dynamicParameterHelpInfoBase = New-Object -TypeName System.Management.Automation.PSObject
889 $dynamicParameterHelpInfoBase | Add-Member -Name type -MemberType NoteProperty -Value $dynamicParameterInfo.Type
890 $dynamicParameterHelpInfoBase | Add-Member -Name defaultValue -MemberType NoteProperty -Value $(if ($dynamicParameterInfo.Type.Name -eq 'System.Management.Automation.SwitchParameter') { $falseString } else { $null })
891 $dynamicParameterHelpInfoBase | Add-Member -Name possibleValues -MemberType NoteProperty -Value $dynamicParameterInfo.PossibleValues
892 $dynamicParameterHelpInfoBase | Add-Member -Name name -MemberType NoteProperty -Value $dynamicParameterName
893 $dynamicParameterHelpInfoBase | Add-Member -Name parameterValue -MemberType NoteProperty -Value $shortTypeName
894 $dynamicParameterHelpInfoBase | Add-Member -Name description -MemberType NoteProperty -Value $dynamicParameterInfo.Description
895 $dynamicParameterHelpInfo = New-Object -TypeName System.Management.Automation.PSObject($dynamicParameterHelpInfoBase)
896 $dynamicParameterHelpInfo.PSObject.TypeNames.Clear()
897 $dynamicParameterHelpInfo.PSObject.TypeNames.Add('MamlCommandHelpInfo#parameter')
898 $dynamicParameterHelpInfo | Add-Member -Name required -MemberType NoteProperty -Value $falseString
899 $dynamicParameterHelpInfo | Add-Member -Name variableLength -MemberType NoteProperty -Value ($dynamicParameterInfo.Type.Name -eq 'System.String').ToString().ToLower()
900 $dynamicParameterHelpInfo | Add-Member -Name globbing -MemberType NoteProperty -Value $falseString
901 $dynamicParameterHelpInfo | Add-Member -Name pipelineInput -MemberType NoteProperty -Value $falseString
902 $dynamicParameterHelpInfo | Add-Member -Name position -MemberType NoteProperty -Value $namedString
903 $dynamicParameterHelpInfo | Add-Member -Name isDynamic -MemberType NoteProperty -Value $true
904 $dynamicParameterHelpInfo
905 }
906
907 $updateParametersScriptBlock = {
908 param(
909 [REF]$parameters = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Parameters')),
910 $dynamicParameterName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterName')),
911 $dynamicParameterInfo = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterInfo'))
912 )
913
914 if (@($parameters.Value.parameter | Where-Object { $_.Name -eq $dynamicParameterName }).Count -eq 0) {
915 $parameters.Value.parameter = [System.Management.Automation.PSObject[]]($parameters.Value.parameter + $(&$createDynamicParameterHelpInfoScriptBlock $dynamicParameterName $dynamicParameterInfo))
916 }
917 }
918
919 $parameterMap = Get-DynamicParameterMap
920
921 foreach ($cmdlet in $parameterMap.Keys) {
922 Invoke-Cmdlet Get-Help -Name $cmdlet -Category Cmdlet -ErrorAction SilentlyContinue | ForEach-Object {
923 foreach ($provider in $parameterMap[$cmdlet].Keys) {
924 foreach ($dynamicParameter in $parameterMap[$cmdlet][$provider].Keys) {
925 &$updateParametersScriptBlock ([REF]($_.Parameters)) $dynamicParameter $parameterMap[$cmdlet][$provider][$dynamicParameter]
926 }
927 if (@($_.Syntax.syntaxItem | Where-Object { $_.Name -eq "[$provider]`r`n$cmdlet" }).Count -eq 0) {
928 $_.Syntax.syntaxItem += &{
929 foreach ($parameterSet in $_.Syntax.syntaxItem | Where-Object { $_.name -notmatch "`r`n" }) {
930 $syntaxItem = New-Object -TypeName System.Management.Automation.PSObject
931 $syntaxItem.PSObject.TypeNames.Clear()
932 $syntaxItem.PSObject.TypeNames.Add('MamlCommandHelpInfo#syntaxItem')
933 $syntaxItem | Add-Member -Name name -MemberType NoteProperty -Value "[$provider]`r`n$cmdlet"
934 $syntaxItem | Add-Member -Name parameter -MemberType NoteProperty -Value $parameterSet.parameter
935 foreach ($dynamicParameter in $parameterMap[$cmdlet][$provider].Keys) {
936 &$updateParametersScriptBlock ([REF]($syntaxItem)) $dynamicParameter $parameterMap[$cmdlet][$provider][$dynamicParameter]
937 }
938 $syntaxItem
939 }
940 }
941 }
942 }
943 }
944 }
945 }
946 PROCESS {
947 if ($_) {
948 Invoke-Expression "`$_ | Invoke-Cmdlet Get-Help $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
949 } else {
950 Invoke-Expression "Invoke-Cmdlet Get-Help $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
951 }
952 }
953 END {
954 }
955 }
956
957 ########################################################################################################################
958
959 if ($MyInvocation.InvocationName -eq '&') {
960 Write-Warning @"
961 The functions and aliases in '$(Split-Path -Path $MyInvocation.MyCommand.Definition -Leaf)' were not added to your PowerShell session properly. To add these to your PowerShell session or profile, you must dot-source the file. To do this, execute the following command:
962 . '$($MyInvocation.MyCommand.Definition)'
963 "@
964 }
965
966 ########################################################################################################################
Plain-text code:
########################################################################################################################
# #
# File: CmdletExtensionLibrary.ps1 #
# Author: Kirk Munro #
# Author's Blog: http://poshoholic.com #
# Revision: 1.0.3 #
# Contents: A collection of functions designed with two purposes in mind: #
# 1. To seamlessly extend published cmdlet functionality transparently to the end user #
# 2. To wrap common operations in fully documented, well named functions designed to extend #
# PowerShell's core set of features #
# In the first case, every effort is made to ensure that the original cmdlet and the corresponding #
# function can be used interchangeably in scripts without requiring any modifications. The only #
# known exception to this is when scripts are modified to explicitly use some information that is #
# only exposed by the function extending the cmdlet. #
# In the second case, functionality is being exposed as functions to solicit community feedback. It #
# is my intention to publish these sorts of functions as cmdlets in the future. #
# History: v1.0.0 - Initial release designed to enhance support for dynamic parameters in the PowerShell help #
# system #
# v1.0.1 - Addition of Invoke-Member function to allow users to invoke any member on a data set #
# without having to use ForEach-Object #
# v1.0.2 - Fixed grs alias for Get-PSResourceString #
# - Added ... alias for Invoke-Member #
# - Added pipeline support to Invoke-Cmdlet, Add-PSSnapin, Remove-PSSnapin and Get-Help #
# v1.0.3 - Added retrieval of Microsoft.PowerShell.ConsoleHost strings to Get-PSResourceString #
# - Added -list parameter to Get-PSResourceString #
# - Added more examples to Get-PSResourceString documentation (comments) #
# - Added Should-Process function to provide -whatif, -confirm and -verbose support to other #
# functions #
# - Added -whatif, -confirm and -verbose support to Invoke-Member function #
# #
########################################################################################################################
########################################################################################################################
# NAME
# Get-PSResourceString
#
# SYNOPSIS
# Returns a resource string that is looked up in the System.Management.Automation namespace or the
# Microsoft.PowerShell.ConsoleHost namespace, or a list of resource root names or resource identifiers that are
# available.
#
# SYNTAX
# Get-PSResourceString [-baseName] <string> [-resourceId] <string> [[-defaultValue] <string>]
# [[-culture] <System.Globalization.CultureInfo>]
# Get-PSResourceString [[-baseName] <string>] -list
#
# DETAILED DESCRIPTION
# The Get-PSResourceString function returns a resource string that is looked up in the System.Management.Automation
# namespace or the Microsoft.PowerShell.ConsoleHost namespace, or a list of resource root names or resource
# identifiers that are available. If a resource string was requested and it is not found, the default value (if
# present) will be returned.
#
# PARAMETERS
# -baseName <string>
# Specifies the root name of the resources.
#
# Required? true
# Position? 1
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -resourceId <string>
# Specifies the identifier of the resource that is being retrieved.
#
# Required? true
# Position? 2
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -defaultValue <string>
# Specifies the default value for the resource string. If the string is not found, the default value will be
# returned.
#
# Required? false
# Position? 3
# Default value null
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -culture <System.Globalization.CultureInfo>
# Specifies the culture to use when looking up the resource string.
#
# Required? false
# Position? 4
# Default value $host.CurrentCulture
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -list <Switch>
# When this parameter is used by itself, this function outputs the root names that are available. When this
# parameter is used in conjunction with the baseName parameter, this function outputs the resource identifiers
# that are availab.e
#
# Required? false
# Position? named
# Default value false
# Accept pipeline input? false
# Accept wildcard characters? false
#
# INPUT TYPE
# String,System.Globalization.CultureInfo,Switch
#
# RETURN TYPE
# String,String[]
#
# NOTES
# For more information the System.Globalization.CultureInfo type consult the relevant MSDN documentation.
#
# -------------------------- EXAMPLE 1 --------------------------
#
# C:\PS>get-psresourcestring -list
#
#
# This command retrieves the list of resource root names that are available.
#
#
# -------------------------- EXAMPLE 2 --------------------------
#
# C:\PS>get-psresourcestring -basename helpdisplaystrings -list
#
#
# This command retrieves the list of resource strings in the resource root called 'helpdisplaystrings' using the
# current culture.
#
#
# -------------------------- EXAMPLE 3 --------------------------
#
# C:\PS>get-psresourcestring -list | foreach-object { get-psresourcestring -basename $_ -list }
#
#
# This command retrieves all resource strings that are available using the current culture.
#
#
# -------------------------- EXAMPLE 4 --------------------------
#
# C:\PS>get-psresourcestring -basename helpdisplaystrings -resourceid falseshort
#
#
# This command retrieves the string associated with the 'falseshort' resource id using the current culture.
#
#
Function Get-PSResourceString {
param(
[string]$baseName = $null,
[string]$resourceId = $null,
[string]$defaultValue = $null,
[System.Globalization.CultureInfo]$culture = $host.CurrentCulture,
[Switch]$list
)
if ($list -and ($resourceId -or $defaultValue)) {
throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'AmbiguousParameterSet')
}
if ($list) {
$engineAssembly = [System.Reflection.Assembly]::GetExecutingAssembly()
$hostAssembly = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.PowerShell.ConsoleHost')
if ($baseName) {
$engineAssembly.GetManifestResourceNames() | Where-Object { $_ -eq "$baseName.resources" } | ForEach-Object {
$resourceManager = New-Object -TypeName System.Resources.ResourceManager($baseName, $engineAssembly)
$resourceManager.GetResourceSet($host.CurrentCulture,$true,$true) | Add-Member -Name BaseName -MemberType NoteProperty -Value $baseName -Force -PassThru | ForEach-Object {
$_.PSObject.TypeNames.Clear()
$_.PSObject.TypeNames.Add('ResourceString')
$_ | Write-Output
}
}
$hostAssembly.GetManifestResourceNames() | Where-Object { $_ -eq "$baseName.resources" } | ForEach-Object {
$resourceManager = New-Object -TypeName System.Resources.ResourceManager($baseName, $hostAssembly)
$resourceManager.GetResourceSet($host.CurrentCulture,$true,$true) | Add-Member -Name BaseName -MemberType NoteProperty -Value $baseName -Force -PassThru | ForEach-Object {
$_.PSObject.TypeNames.Clear()
$_.PSObject.TypeNames.Add('ResourceString')
$_ | Write-Output
}
}
} else {
$engineAssembly.GetManifestResourceNames() | Where-Object { $_ -match '\.resources$' } | ForEach-Object { $_.Replace('.resources','') }
$hostAssembly.GetManifestResourceNames() | Where-Object { $_ -match '\.resources$' } | ForEach-Object { $_.Replace('.resources','') }
}
} else {
if (-not $baseName) {
throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'BaseName')
}
if (-not $resourceId) {
throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'ResourceId')
}
if (-not $global:PSResourceStringTable) {
$engineAssembly = [System.Reflection.Assembly]::GetExecutingAssembly()
$hostAssembly = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.PowerShell.ConsoleHost')
if ($engineAssembly.GetManifestResourceNames() -contains "$baseName.resources") {
New-Variable -Scope Global -Name PSResourceStringTable -Value @{} -Description 'A cache of PowerShell resource strings. To access data in this table, use Get-ResourceString.'
$global:PSResourceStringTable['EngineAssembly'] = @{'Assembly'=$engineAssembly;'Cultures'=@{}}
$global:PSResourceStringTable['HostAssembly'] = @{'Assembly'=$hostAssembly;'Cultures'=@{}}
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
$global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
} elseif ($hostAssembly.GetManifestResourceNames() -contains "$baseName.resources") {
New-Variable -Scope Global -Name PSResourceStringTable -Value @{} -Description 'A cache of PowerShell resource strings. To access data in this table, use Get-ResourceString.'
$global:PSResourceStringTable['EngineAssembly'] = @{'Assembly'=$engineAssembly;'Cultures'=@{}}
$global:PSResourceStringTable['HostAssembly'] = @{'Assembly'=$hostAssembly;'Cultures'=@{}}
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
$global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
}
} elseif ($global:PSResourceStringTable.EngineAssembly.Assembly.GetManifestResourceNames() -contains "$baseName.resources") {
if (-not $global:PSResourceStringTable.EngineAssembly.Cultures.ContainsKey($culture.Name)) {
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
$global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
} elseif (-not $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.EngineAssembly.Assembly));
$global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name][$baseName] = @{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)};
}
} elseif ($global:PSResourceStringTable.HostAssembly.Assembly.GetManifestResourceNames() -contains "$baseName.resources") {
if (-not $global:PSResourceStringTable.HostAssembly.Cultures.ContainsKey($culture.Name)) {
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
$global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name] = @{$baseName=@{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)}};
} elseif (-not $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
$resourceManager = (New-Object -TypeName System.Resources.ResourceManager($baseName, $global:PSResourceStringTable.HostAssembly.Assembly));
$global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name][$baseName] = @{'ResourceManager'=$resourceManager;'Strings'=$resourceManager.GetResourceSet($culture,$true,$true)};
}
}
$resourceString = $null
if ($global:PSResourceStringTable) {
if ($global:PSResourceStringTable.EngineAssembly.Cultures -and $global:PSResourceStringTable.EngineAssembly.Cultures.ContainsKey($culture.Name) -and $global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
$resourceString = ($global:PSResourceStringTable.EngineAssembly.Cultures[$culture.Name][$baseName].Strings | Where-Object { $_.Name -eq $resourceId }).Value
} elseif ($global:PSResourceStringTable.HostAssembly.Cultures -and $global:PSResourceStringTable.HostAssembly.Cultures.ContainsKey($culture.Name) -and $global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name].ContainsKey($baseName)) {
$resourceString = ($global:PSResourceStringTable.HostAssembly.Cultures[$culture.Name][$baseName].Strings | Where-Object { $_.Name -eq $resourceId }).Value
}
}
if (-not $resourceString) {
$resourceString = $defaultValue
}
return $resourceString
}
}
if (-not (Get-Alias -Name grs -ErrorAction SilentlyContinue)) {
New-Alias -Name grs -Value Get-PSResourceString -Description 'Returns a resource string that is looked up in the System.Management.Automation namespace.'
}
########################################################################################################################
# NAME
# Should-Process
#
# SYNOPSIS
# Determines whether the specified operation should be performed on the target object.
#
# SYNTAX
# Should-Process [-operation] <string> [-target] <string> [-whatIf]
# Should-Process [-operation] <string> [-target] <string> [-confirmResponse] <REF> [[-confirmPrompt] <string>]
# [-confirm]
# Should-Process [-operation] <string> [-target] <string> [-verbose]
#
# DETAILED DESCRIPTION
# Determines whether the specified operation should be performed on the target object. Returns true if the operation
# should be performed. Should-Process never performs the operation; it just indicates whether or not it should be
# performed to the caller. If the whatIf switch is used, Should-Process outputs strings indicating what it would do
# if whatIf wasn't used. If the confirm switch is used, Should-Process asks the user to confirm that they want to
# perform the operation. If the verbose switch is used, Should-Process writes verbose output for each operation that
# will be performed on each target.
#
# PARAMETERS
# -operation <string>
# Specifies the name of the function that was invoked.
#
# Required? true
# Position? 1
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -target <string>
# Specifies the identifier of the object that is being used in the operation.
#
# Required? true
# Position? 2
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -confirmResponse <REF>
# Reference variable that retains any confirm question response that applies to all objects being processed.
#
# Required? true
# Position? 3
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -confirmPrompt <string>
# Specifies the string that will be displayed to the caller when the -confirm switch is used.
#
# Required? false
# Position? 4
# Default value Are you sure you want to perform this action?
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -verbose <switch>
# When this parameter is used, this function outputs verbose information to the host.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -confirm <switch>
# When this parameter is used, this function requests confirmation from the user for the actions it will take.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -whatif <switch>
# When this parameter is used, this function outputs what it would do without actually taking action.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# INPUT TYPE
# String,Ref,Switch
#
# RETURN TYPE
# Boolean
#
# NOTES
# Whatif takes precedence over confirm. Confirm takes precedence over verbose. If more than one switch parameter is
# used, this precedence order will be followed and only the highest precedence switch will be used.
#
# The ConfirmResponse reference parameter is used to determine if "YES to All" or "NO to all" has been previously
# selected.
#
# When using Should-Process inside of functions that can be used in a pipeline, you should initialize your reference
# variable in the begin block and then call Should-Process in the process block.
#
# -------------------------- EXAMPLE 1 --------------------------
#
#
# C:\PS>function Stop-Calc ([Switch]$Verbose, [Switch]$Confirm, [Switch]$Whatif) {
# $ConfirmResponse = $null
# foreach ($p in Get-Process calc) {
# if (Should-Process Stop-Calc $p.Id ([REF]$ConfirmResponse) `
# -Verbose:$Verbose -Confirm:$Confirm -Whatif:$Whatif) {
# Stop-Process $p.Id
# }
# }
# }
# C:\PS>stop-calc -confirm
#
#
# This prompts you to confirm you want to stop all calc processes when using the simple Stop-Process function.
#
#
# RELATED LINKS
# about_commonparameters
# about_ref
#
Function Should-Process {
param(
[string]$Operation = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Operation')),
[string]$Target = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Target')),
[REF]$ConfirmResponse = ([REF]$null),
[string]$ConfirmPrompt = $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessWarningFallback') -f $null),
[Switch]$Verbose,
[Switch]$Confirm,
[Switch]$Whatif
)
if ($ConfirmResponse.Value -eq $false) {
return $false
} elseif ($ConfirmResponse.Value -eq $true) {
return $true
}
if ($Whatif) {
Write-Host $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessWhatIfMessage') -f $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target))
return $false
} elseif ($Confirm) {
$ConfirmText = @"
$(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'InquireCaptionDefault')
$ConfirmPrompt
$($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target)
"@
Write-Host $ConfirmText
$Yes = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueOneLabel')
$All = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueAllLabel')
$No = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipOneLabel')
$None = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipAllLabel')
$Suspend = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'PauseLabel')
$Help = $(Get-PSResourceString -BaseName 'ConsoleHostUserInterfaceStrings' -ResourceId 'PromptForChoiceHelp')
$YesHotkey = $Yes.ToUpper()[$Yes.IndexOf('&') + 1]
$AllHotkey = $All.ToUpper()[$All.IndexOf('&') + 1]
$NoHotkey = $No.ToUpper()[$No.IndexOf('&') + 1]
$NoneHotkey = $None.ToUpper()[$None.IndexOf('&') + 1]
$SuspendHotkey = $Suspend.ToUpper()[$Suspend.IndexOf('&') + 1]
$HelpHotkey = $Help.ToUpper()[$Help.IndexOf('[') + 1]
$YesHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueOneHelpMessage')
$AllHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ContinueAllHelpMessage')
$NoHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipOneHelpMessage')
$NoneHelp = $(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'SkipAllHelpMessage')
$SuspendHelp = $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'PauseHelpMessage') -f 'exit')
$DefaultValue = $($(Get-PSResourceString -BaseName 'ConsoleHostUserInterfaceStrings' -ResourceId 'DefaultChoicePrompt') -f $YesHotKey)
while ($true) {
$answer = Read-Host @"
[$YesHotkey] $($Yes.Replace('&','')) [$AllHotkey] $($All.Replace('&','')) [$NoHotkey] $($No.Replace('&','')) [$NoneHotkey] $($None.Replace('&','')) [$SuspendHotkey] $($Suspend.Replace('&','')) $Help $DefaultValue
"@
switch ($answer) {
"$YesHotkey" { return $true }
"" { return $true }
"$AllHotkey" { $ConfirmResponse.Value = $true; return $true }
"$NoHotkey" { return $false }
"$NoneHotkey" { $ConfirmResponse.Value = $false; return $false }
"$SuspendHotkey" { $host.EnterNestedPrompt(); Write-Host $ConfirmText }
"$HelpHotkey" { Write-Host @"
$YesHotkey - $YesHelp
$AllHotkey - $AllHelp
$NoHotkey - $NoHelp
$NoneHotkey - $NoneHelp
$SuspendHotkey - $SuspendHelp
"@
}
}
}
} elseif ($verbose) {
Write-Verbose $($(Get-PSResourceString -BaseName 'CommandBaseStrings' -ResourceId 'ShouldProcessMessage') -f $Operation,$Target)
}
return $true
}
if (-not (Get-Alias -Name sps -ErrorAction SilentlyContinue)) {
New-Alias -Name sps -Value Should-Process -Description 'Determines whether the specified operation should be performed on the target object. Returns true if the operation should be performed.'
}
########################################################################################################################
# NAME
# Invoke-Member
#
# SYNOPSIS
# Invoke members of each of a set of input objects.
#
# SYNTAX
# Invoke-Member [-name] <string[]> [[-inputObject] <psobject>] [-whatif] [-confirm] [-verbose]
#
# DETAILED DESCRIPTION
# Invokes a member of each of a set of input objects. The input objects can be piped to the cmdlet or specified by
# using the InputObject parameter. If an input object does not have the specified member, it will be skipped. The
# results of the invocation of the members are passed down the pipeline.
#
# PARAMETERS
# -name <string[]>
# Specifies the name of the member to invoke. For members that accept parameters, pass the member name with the
# parameters in parentheses inside of quotation marks.
#
# Required? true
# Position? 1
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -inputObject <psobject>
# Accepts an object for which the member will be invoked. Enter a variable that contains the objects or type a
# command or expression that gets the objects.
#
# Required? false
# Position? 2
# Default value
# Accept pipeline input? true (ByValue)
# Accept wildcard characters? false
#
# -whatIf
# Describes what would happen if you executed the command without actually executing the command.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# -confirm
# Prompts you for confirmation before executing the command.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# <CommonParameters>
# This cmdlet supports the common parameters: -Verbose. For more information, type,
# "get-help about_commonparameters".
#
# INPUT TYPE
# String[],PSObject
#
# RETURN TYPE
# Object
#
# NOTES
# When a collection of objects is passed in via the InputObject parameter, the member will be invoked on the
# collection object, not on the items in the collection.
#
#
# -------------------------- EXAMPLE 1 --------------------------
#
# C:\PS>get-childitem -literalpath C:\ -force | invoke-member -name PSObject.typenames | select-object -unique
#
#
# This command retrieves all unique base and derived object type names.
#
#
# -------------------------- EXAMPLE 2 --------------------------
#
# C:\PS>get-help -category cmdlet | sort-object -property name | invoke-member -name syntax
#
#
# This command retrieves a sorted list of the syntax for all cmdlets based on help information.
#
#
# RELATED LINKS
# Get-Member
# Invoke-Expression
# ForEach-Object
#
Function Invoke-Member {
param (
[string[]]$name = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Name')),
$inputObject = $null,
[Switch]$whatif,
[Switch]$confirm,
[Switch]$verbose
)
BEGIN {
$confirmResponse = $null
}
PROCESS {
if ($inputObject -and $_) {
throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'InputObjectNotBound')
break
} elseif ($inputObject) {
foreach ($member in $name) {
if (Should-Process Invoke-Member $member ([REF]$confirmResponse) -Verbose:$verbose -Confirm:$confirm -Whatif:$whatif) {
Invoke-Expression "`$inputObject.$member"
}
}
} elseif ($_) {
foreach ($member in $name) {
if (Should-Process Invoke-Member $member ([REF]$confirmResponse) -Verbose:$verbose -Confirm:$confirm -Whatif:$whatif) {
Invoke-Expression "`$_.$member"
}
}
} else {
throw $(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'AmbiguousParameterSet')
}
}
END {
}
}
if (-not (Get-Alias -Name im -ErrorAction SilentlyContinue)) {
New-Alias -Name im -Value Invoke-Member -Description 'Invokes a member of each of a set of input objects.'
}
if (-not (Get-Alias -Name ... -ErrorAction SilentlyContinue)) {
New-Alias -Name ... -Value Invoke-Member -Description 'Invokes a member of each of a set of input objects.'
}
########################################################################################################################
# NAME
# Invoke-Cmdlet
#
# SYNOPSIS
# Invokes a cmdlet by using its fully qualified name.
#
# SYNTAX
# Invoke-Cmdlet [-cmdletName] <string> [<CmdletParameters>]
#
# DETAILED DESCRIPTION
# The Invoke-Cmdlet function invokes a cmdlet directly by using its fully qualified name. This allows cmdlets to be
# invoked even if there are functions or aliases with the same name. It follows Microsoft's house rules whereby the
# core snapins take precedence over added snapins.
#
# PARAMETERS
# -cmdletName <string>
# Specifies the name of a cmdlet. When this parameter is used, this function invokes the cmdlet identified by
# this parameter.
#
# Required? true
# Position? 1
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# <CmdletParameters>
# This cmdlet supports all parameters that are supported by the cmdlet being invoked. Consult the cmdlet help
# parameter list for more information.
#
# INPUT TYPE
# String
#
# RETURN TYPE
# Consult the cmdlet help return type for more information.
#
# NOTES
# For more information, consult the help documentation for the cmdlet that you are invoking.
#
# Cmdlets that have a cmdletName parameter are not supported by this cmdlet.
#
# -------------------------- EXAMPLE 1 --------------------------
#
# C:\PS>invoke-cmdlet get-help * -parameter codesigningcert
#
#
# This command gets all commands that have a CodeSigningCert parameter. This will only include those cmdlets whose
# documentation specifically includes the CodeSigningCert parameter unless the CmdletExtensionLibrary is being used
# and the Get-Help function has been called at least once.
#
# RELATED LINKS
# Get-Command
# Invoke-Expression
#
Function Invoke-Cmdlet {
param([string]$cmdletName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'CmdletName')))
BEGIN {
$matchingCmdlets = Microsoft.PowerShell.Core\Get-Command -CommandType cmdlet -Name $cmdletName
if (@($matchingCmdlets).Count -eq 0) {
throw $($(Get-PSResourceString -BaseName 'DiscoveryExceptions' -ResourceId 'CmdletNotFoundException') -f 'CmdletName',$cmdletName)
}
$cmdletName = $null
foreach ($cmdlet in $matchingCmdlets) {
if ($cmdlet.PSSnapin.IsDefault) {
$cmdletName = "$($cmdlet.PSSnapin.Name)\$($cmdlet.Name)"
break
} elseif (-not $cmdletName) {
$cmdletName = "$($cmdlet.PSSnapin.Name)\$($cmdlet.Name)"
}
}
}
PROCESS {
if ($_) {
Microsoft.PowerShell.Utility\Invoke-Expression "`$_ | $cmdletName $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
} else {
Microsoft.PowerShell.Utility\Invoke-Expression "$cmdletName $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
}
}
END {
}
}
if (-not (Get-Alias -Name ic -ErrorAction SilentlyContinue)) {
New-Alias -Name ic -Value Invoke-Cmdlet -Description 'Invokes a cmdlet by using its fully qualified name.'
}
########################################################################################################################
# NAME
# Get-DynamicParameterMap
#
# SYNOPSIS
# Displays a mapping of cmdlet names to dynamic parameters.
#
# SYNTAX
# Get-DynamicParameterMap [-refresh]
#
# DETAILED DESCRIPTION
# The Get-DynamicParameterMap function extracts the dynamic parameter help information from the PSProvider help
# documentation and builds a map of cmdlet names to dynamic parameters. If the map has already been built, it is
# immediately returned. If the Refresh switch parameter is used, the map is rebuilt.
#
# PARAMETERS
# -refresh <switch>
# When this parameter is used, this function reloads the dynamic parameter map before returning it to the
# caller.
#
# Required? false
# Position? named
# Default value
# Accept pipeline input? false
# Accept wildcard characters? false
#
# INPUT TYPE
# Switch
#
# RETURN TYPE
# Associative Array
#
# NOTES
# If multiple providers include a dynamic parameter with the same name but a different type or documentation, both
# versions will be used.
#
# -------------------------- EXAMPLE 1 --------------------------
#
# C:\PS>get-dynamicparametermap
#
#
# This command retrieves all dynamic parameter help documentation from the PSProviders that are loaded and returns
# an associative array mapping cmdlet names to dynamic parameters.
#
# RELATED LINKS
# Invoke-Cmdlet
# about_associative_array
#
Function Get-DynamicParameterMap {
param ([Switch]$Refresh)
if (($refresh) -or (-not $global:dynamicParameterMap)) {
Remove-Variable -Force -Scope Global -Name dynamicParameterMap -ErrorAction SilentlyContinue
New-Variable -Scope Global -Name dynamicParameterMap -Value @{} -Description 'Maps cmdlet names to dynamic parameter help information. This variable is managed via custom scripts that provide better support for dynamic parameters and should only be used by those custom scripts.'
Invoke-Cmdlet Get-Help -Category Provider -ErrorAction SilentlyContinue | ForEach-Object {
$providerHelp = $_
$_.DynamicParameters.DynamicParameter | Where-Object { $_.CmdletSupported } | ForEach-Object {
$type = New-Object -TypeName System.Management.Automation.PSObject
$type.PSObject.TypeNames.Clear()
$type.PSObject.TypeNames.Add('MamlCommandHelpInfo#type')
$type | Add-Member -Name name -MemberType NoteProperty -Value $_.Type.Name
$type | Add-Member -Name uri -MemberType NoteProperty -Value $([String]$null)
$description = New-Object -TypeName System.Management.Automation.PSObject
$description.PSObject.TypeNames.Clear()
$description.PSObject.TypeNames.Add('MamlParaTextItem')
$description.PSObject.TypeNames.Add('MamlTextItem')
$description | Add-Member -Name Text -MemberType NoteProperty -Value $_.Description
$descriptionArray = @($description)
foreach ($cmdletSupported in $_.CmdletSupported.Split(', ', [StringSplitOptions]::RemoveEmptyEntries)) {
if (-not $global:dynamicParameterMap.ContainsKey($cmdletSupported)) {
$global:dynamicParameterMap[$cmdletSupported] = @{$providerHelp.Name=@{$_.Name=@{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}}}
} elseif (-not $global:dynamicParameterMap[$cmdletSupported].ContainsKey($providerHelp.Name)) {
$global:dynamicParameterMap[$cmdletSupported][$providerHelp.Name] = @{$_.Name=@{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}}
} else {
$global:dynamicParameterMap[$cmdletSupported][$providerHelp.Name][$_.Name] = @{'Description'=$descriptionArray;'Type'=$type;'PossibleValues'=$_.PossibleValues}
}
}
}
}
foreach ($cmdlet in $global:dynamicParameterMap.Keys) {
Invoke-Cmdlet Get-Help -Name $cmdlet -Category Cmdlet -ErrorAction SilentlyContinue | ForEach-Object {
$_.Parameters.parameter = [System.Management.Automation.PSObject[]]($_.Parameters.parameter | Where-Object { $_.isDynamic -ne $true })
$_.Syntax.syntaxItem = [System.Management.Automation.PSObject[]]($_.Syntax.syntaxItem | Where-Object { $_.name -notmatch "`r`n" })
}
}
}
$global:dynamicParameterMap
}
########################################################################################################################
# NAME
# Add-PSSnapin
#
# SYNOPSIS
# Wraps the Add-PSSnapin cmdlet. Consult the Add-PSSnapin cmdlet help for more information.
#
# SYNTAX
# Consult the Add-PSSnapin cmdlet help for the syntax.
#
# DETAILED DESCRIPTION
# Wraps the Add-PSSnapin cmdlet. After the Add-PSSnapin cmdlet returns, it recreates the dynamic parameter map.
#
# NOTES
# Consult the Add-PSSnapin cmdlet help for more information on syntax, detailed description, input types, return
# types, notes, examples, and related links.
#
# RELATED LINKS
# Add-PSSnapin (cmdlet)
#
Function Add-PSSnapin {
BEGIN {
}
PROCESS {
if ($_) {
Invoke-Expression "`$_ | Invoke-Cmdlet Add-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
} else {
Invoke-Expression "Invoke-Cmdlet Add-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
}
}
END {
Get-DynamicParameterMap -Refresh | Out-Null
}
}
########################################################################################################################
# NAME
# Remove-PSSnapin
#
# SYNOPSIS
# Wraps the Remove-PSSnapin cmdlet. Consult the Remove-PSSnapin cmdlet help for more information.
#
# SYNTAX
# Consult the Remove-PSSnapin cmdlet help for the syntax.
#
# DETAILED DESCRIPTION
# Wraps the Remove-PSSnapin cmdlet. After the Remove-PSSnapin cmdlet returns, it recreates the dynamic parameter
# map.
#
# NOTES
# Consult the Remove-PSSnapin cmdlet help for more information on syntax, detailed description, input types, return
# types, notes, examples, and related links.
#
# RELATED LINKS
# Remove-PSSnapin (cmdlet)
#
Function Remove-PSSnapin {
BEGIN {
}
PROCESS {
if ($_) {
Invoke-Expression "`$_ | Invoke-Cmdlet Remove-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
} else {
Invoke-Expression "Invoke-Cmdlet Remove-PSSnapin $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
}
}
END {
Get-DynamicParameterMap -Refresh | Out-Null
}
}
########################################################################################################################
# NAME
# Get-Help
#
# SYNOPSIS
# Wraps the Get-Help cmdlet and integrates dynamic parameter help information. Consult the Get-Help cmdlet help for
# more information.
#
# SYNTAX
# Consult the Get-Help cmdlet help for the syntax.
#
# DETAILED DESCRIPTION
# Wraps the Get-Help cmdlet and integrates dynamic parameter help information. By default, dynamic parameters are
# not included in the help information for cmdlets. Consult the Get-Help cmdlet help or the provider specific help
# for more information.
#
# INPUT TYPE
# Consult the Get-Help cmdlet help for more information.
#
# RETURN TYPE
# Consult the Get-Help cmdlet help for more information.
#
# NOTES
# For more information, consult the help information for the Get-Help cmdlet.
#
# If multiple providers include a dynamic parameter with the same name but a different type or documentation, the
# documentation for the last one found will be used.
#
# -------------------------- EXAMPLE 1 --------------------------
#
# C:\PS>get-help * -parameter -codesigningcert
#
#
# This command gets all commands that have a CodeSigningCert parameter. This will include all cmdlets that support
# the dynamic CodeSigningCert parameter, including those cmdlets whose documentation specifically includes the
# CodeSigningCert parameter as well as those whose documentation does not specifically include the CodeSigningCert
# parameter but who support the parameter through a dynamic parameter that is included in a specific provider.
#
# RELATED LINKS
# Get-Help (cmdlet)
#
Function Get-Help {
BEGIN {
$resourceManager = New-Object -TypeName System.Resources.ResourceManager('HelpDisplayStrings', [System.Reflection.Assembly]::GetExecutingAssembly())
$falseString = $resourceManager.GetString('FalseShort')
$namedString = $resourceManager.GetString('NamedParameter')
$createDynamicParameterHelpInfoScriptBlock = {
param(
$dynamicParameterName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterName')),
$dynamicParameterInfo = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterInfo'))
)
$shortTypeName = Invoke-Expression "[$($dynamicParameterInfo.Type.Name)].Name"
$dynamicParameterHelpInfoBase = New-Object -TypeName System.Management.Automation.PSObject
$dynamicParameterHelpInfoBase | Add-Member -Name type -MemberType NoteProperty -Value $dynamicParameterInfo.Type
$dynamicParameterHelpInfoBase | Add-Member -Name defaultValue -MemberType NoteProperty -Value $(if ($dynamicParameterInfo.Type.Name -eq 'System.Management.Automation.SwitchParameter') { $falseString } else { $null })
$dynamicParameterHelpInfoBase | Add-Member -Name possibleValues -MemberType NoteProperty -Value $dynamicParameterInfo.PossibleValues
$dynamicParameterHelpInfoBase | Add-Member -Name name -MemberType NoteProperty -Value $dynamicParameterName
$dynamicParameterHelpInfoBase | Add-Member -Name parameterValue -MemberType NoteProperty -Value $shortTypeName
$dynamicParameterHelpInfoBase | Add-Member -Name description -MemberType NoteProperty -Value $dynamicParameterInfo.Description
$dynamicParameterHelpInfo = New-Object -TypeName System.Management.Automation.PSObject($dynamicParameterHelpInfoBase)
$dynamicParameterHelpInfo.PSObject.TypeNames.Clear()
$dynamicParameterHelpInfo.PSObject.TypeNames.Add('MamlCommandHelpInfo#parameter')
$dynamicParameterHelpInfo | Add-Member -Name required -MemberType NoteProperty -Value $falseString
$dynamicParameterHelpInfo | Add-Member -Name variableLength -MemberType NoteProperty -Value ($dynamicParameterInfo.Type.Name -eq 'System.String').ToString().ToLower()
$dynamicParameterHelpInfo | Add-Member -Name globbing -MemberType NoteProperty -Value $falseString
$dynamicParameterHelpInfo | Add-Member -Name pipelineInput -MemberType NoteProperty -Value $falseString
$dynamicParameterHelpInfo | Add-Member -Name position -MemberType NoteProperty -Value $namedString
$dynamicParameterHelpInfo | Add-Member -Name isDynamic -MemberType NoteProperty -Value $true
$dynamicParameterHelpInfo
}
$updateParametersScriptBlock = {
param(
[REF]$parameters = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'Parameters')),
$dynamicParameterName = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterName')),
$dynamicParameterInfo = $(throw $($(Get-PSResourceString -BaseName 'ParameterBinderStrings' -ResourceId 'ParameterArgumentValidationErrorNullNotAllowed') -f $null,'DynamicParameterInfo'))
)
if (@($parameters.Value.parameter | Where-Object { $_.Name -eq $dynamicParameterName }).Count -eq 0) {
$parameters.Value.parameter = [System.Management.Automation.PSObject[]]($parameters.Value.parameter + $(&$createDynamicParameterHelpInfoScriptBlock $dynamicParameterName $dynamicParameterInfo))
}
}
$parameterMap = Get-DynamicParameterMap
foreach ($cmdlet in $parameterMap.Keys) {
Invoke-Cmdlet Get-Help -Name $cmdlet -Category Cmdlet -ErrorAction SilentlyContinue | ForEach-Object {
foreach ($provider in $parameterMap[$cmdlet].Keys) {
foreach ($dynamicParameter in $parameterMap[$cmdlet][$provider].Keys) {
&$updateParametersScriptBlock ([REF]($_.Parameters)) $dynamicParameter $parameterMap[$cmdlet][$provider][$dynamicParameter]
}
if (@($_.Syntax.syntaxItem | Where-Object { $_.Name -eq "[$provider]`r`n$cmdlet" }).Count -eq 0) {
$_.Syntax.syntaxItem += &{
foreach ($parameterSet in $_.Syntax.syntaxItem | Where-Object { $_.name -notmatch "`r`n" }) {
$syntaxItem = New-Object -TypeName System.Management.Automation.PSObject
$syntaxItem.PSObject.TypeNames.Clear()
$syntaxItem.PSObject.TypeNames.Add('MamlCommandHelpInfo#syntaxItem')
$syntaxItem | Add-Member -Name name -MemberType NoteProperty -Value "[$provider]`r`n$cmdlet"
$syntaxItem | Add-Member -Name parameter -MemberType NoteProperty -Value $parameterSet.parameter
foreach ($dynamicParameter in $parameterMap[$cmdlet][$provider].Keys) {
&$updateParametersScriptBlock ([REF]($syntaxItem)) $dynamicParameter $parameterMap[$cmdlet][$provider][$dynamicParameter]
}
$syntaxItem
}
}
}
}
}
}
}
PROCESS {
if ($_) {
Invoke-Expression "`$_ | Invoke-Cmdlet Get-Help $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
} else {
Invoke-Expression "Invoke-Cmdlet Get-Help $($passThruArgs = $args; for ($i = 0; $i -lt $passThruArgs.Count; $i++) { if ($passThruArgs[$i] -match '^-') { $passThruArgs[$i] } else { `"`$passThruArgs[$i]`" } })"
}
}
END {
}
}
########################################################################################################################
if ($MyInvocation.InvocationName -eq '&') {
Write-Warning @"
The functions and aliases in '$(Split-Path -Path $MyInvocation.MyCommand.Definition -Leaf)' were not added to your PowerShell session properly. To add these to your PowerShell session or profile, you must dot-source the file. To do this, execute the following command:
. '$($MyInvocation.MyCommand.Definition)'
"@
}
########################################################################################################################
|
|
 |