Обновление переменных среды сеанса

I am currently trying to get a command that I know works in CLI to run through a PowerShell Ise script but it will not allow me to run it as it is picking up a part of the command as a parameter.

Start-Process ssh -o KexAlgorithms=diffie-hellman-group14-sha1 Username@IP
Start-Process : Parameter cannot be processed because the parameter name 'o' is ambiguous. Possible matches include: -OutVariable -OutBuffer.
At line:1 char:30
+ Start-Process ssh -o KexAlgorithms=diffie-hellman-group14- ...
+                              ~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.StartProcessCommand

What is supposed to happen is the cli should pop up and allow me to access a switch which as i have stated earlier works when I manually input it into Cli.

mklement0's user avatar

68 gold badges673 silver badges862 bronze badges

asked Aug 7, 2023 at 10:47

Callum Cooper's user avatar

As Mathias notes, you must quote the list of arguments to pass through to ssh:

# Note the '...' around the entire list of pass-through arguments.
# Use "..." if you need string interpolation.
# Use *embedded* "..." quoting for arguments that contain spaces, for instance.
Start-Process ssh '-o KexAlgorithms=diffie-hellman-group14-sha1 Username@IP'

There are two problems with your approach:

  • Because -o is unquoted, Start-Process interprets it as one of its parameter names.

    • Thus, pass-through arguments that happen to look like PowerShell parameters, must be quoted, e.g. – if passed individually (which isn’t advisable; see next point) – '-o'.

    • As for the error you saw:

      • PowerShell’s “elastic syntax” allows you to use parameter-name prefixes for brevity, so you don’t have to type / tab-complete the full parameter name.

      • However, such a prefix must be unambiguous; if it isn’t, PowerShell complains and lists the candidate parameter names, such as -OutVariable and -OutBuffer for -o in this case. Thus, prefix -outv would have avoided the ambiguity, for instance. Also note that some parameters have unambiguous short aliases, such as -ov for -OutVariable.

  • More fundamentally, trying to pass multiple pass-through arguments individually to Start-Process causes a syntax error:

    • It is best to specify all pass-through arguments as a single, quoted string, using embedded double-quoting, if necessary.

      • This answer explains the syntax problem in detail, but the short of it is that Start-Process expects pass-through arguments via a single argument, passed to its -ArgumentList (-Args) parameter, which is the 2nd positional parameter.
      • This answer explains why – even though you can specify the pass-through arguments individually as the elements of an array (,-separated), a long-standing bug makes the single-string approach preferable.

answered Aug 7, 2023 at 14:07

mklement0's user avatar

68 gold badges673 silver badges862 bronze badges

SYNOPSIS​

Updates the environment variables for the current PowerShell session with any environment variable changes that may have occurred during script execution.

SYNTAX​

DESCRIPTION​

Environment variable changes that take place during script execution are not visible to the current PowerShell session.

Use this function to refresh the current PowerShell session with all environment variable settings.

EXAMPLES​

EXAMPLE 1

PARAMETERS​

-LoadLoggedOnUserEnvironmentVariables



Accept pipeline input
Accept wildcard characters

-ContinueOnError

Continue if an error is encountered.
Default is: $true.



Accept pipeline input
Accept wildcard characters

CommonParameters

INPUTS​

None

You cannot pipe objects to this function.

OUTPUTS​

None. This function does not return objects.

NOTES​

This function has an alias: Refresh-SessionEnvironmentVariables

Syntax Basics

Get-MgTeam [-TeamId <String>] [-All] [-Filter <String>] [-Search <String>] [-Property <String[]>] [<CommonParameters>]

Parameters Explanation

  • -TeamId <String>: Specifies the ID of the Team you want to retrieve. If you know the specific Team ID, you can use this parameter to get details about that particular Team.
  • -All: Retrieves all Teams in the organization. This parameter is useful when you need to get information about every Team.
  • -Filter <String>: Filters the Teams based on specific criteria. The filter must follow the OData query standards.
  • -Search <String>: Searches for Teams based on a specified string. This is useful for finding Teams that match a certain keyword in their display name or other searchable properties.
  • -Property <String[]>: Specifies which properties to include in the results. By default, the cmdlet returns a standard set of properties, but you can use this parameter to request specific properties.
  • <CommonParameters>: Supports common parameters used by all PowerShell cmdlets, such as -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, and -Verbose. These parameters help in controlling the cmdlet’s behavior and output.

Usage Examples

Example 1: Retrieve All Teams

Get-MgTeam -All

This command retrieves all Teams in the organization.

Обновление переменных среды сеанса

Example 2: Retrieve a Specific Team by Team ID

Get-MgTeam -TeamId "team-id"

Replace “team-id” with the actual ID of the Team you want to retrieve.

Обновление переменных среды сеанса

Example 3: Filter Teams Based on a Property

Get-MgTeam -Filter "displayName eq 'MSFT'"

This command retrieves Teams with the display name “MSFT”.

Обновление переменных среды сеанса

Example 4: Retrieve Specific Properties of All Teams

Get-MgTeam -All -Property "id", "displayName"

This command retrieves only the ID, display name, and description properties of all Teams.

Обновление переменных среды сеанса

Simple Scripts Illustrating Get-MgTeam Cmdlet Usage

Script to List All Teams and Display Their Names and Descriptions

$teams = Get-MgTeam -All -Property "displayName", "description"
$teams | ForEach-Object {
    "Team Name: $($_.displayName) Description: $($_.description)"
}

This script fetches all the Teams within the tenant, loops through them, and displays the team name and description.

Обновление переменных среды сеанса

Script to Find Teams Containing “Sales” in Their Display Name

$teams = Get-MgTeam -All | Where-Object { $_.displayName -like '*Sales*' }
$teams | ForEach-Object {
    "Team ID: $($_.Id) Team Name: $($_.displayName)"
}

This script fetches all the Teams that contain ‘Sales’ in the display name, loops through them, and displays their team ID and name.

Обновление переменных среды сеанса

Possible Errors

Authentication Error

Get-MgTeam : Authorization_RequestDenied

Invalid Team ID

Get-MgTeam : Resource 'team-id' does not exist or one of its queried reference-property objects are not present.

Verify that the Team ID is correct and that the Team exists in your organization.

Filter Syntax Error

Get-MgTeam : Invalid filter clause

Ensure that your filter syntax adheres to the OData query standards. Refer to the Microsoft Graph documentation for valid filter options.

Cmdlet Tips

  • Use the -All Parameter: When you need to retrieve information about all Teams, use the -All parameter to ensure you get a complete list.
  • Optimize Filters and Searches: Using filters and search parameters can significantly reduce the amount of data returned, making your scripts more efficient.
  • Select Specific Properties: When you only need certain properties, use the -Property parameter to specify which ones. This reduces the amount of data processed and can improve performance.
  • Error Handling: Always include error handling in your scripts to manage common issues like authentication problems or invalid input.

Conclusion

Related Articles:

Parameters

When viewing help for a command, several different conventions are used to describe when a parameter is required and how it should be used. These conventions include:

  • Optional parameters, where parameter names and arguments are enclosed in a single pair of square brackets.
  • Optional positional parameters – the same as an optional parameter but with the parameter name also enclosed in square brackets.
  • Mandatory parameters, where the parameter name and argument are not bracketed.
  • Mandatory positional parameters, where the parameter name is in square brackets, but the argument is not.

Optional parameters

Optional parameters are surrounded by square brackets. If a parameter is used, a value (or argument) must be supplied. A fragment of the syntax for Get-Help is shown below. It shows that a Category parameter is available and that the parameter is optional.

SYNTAX
     ... [- <[]>] ...
  HelpFile

The command above filters help documents to help files, the “about” documents.

Optional positional parameters

An optional positional parameter is surrounded by square brackets, like an optional parameter. In addition, the parameter name itself is enclosed in square brackets. This indicates that the parameter is optional and that if it is used, the parameter and value can be supplied, or just the value without the parameter name.

It is not uncommon to see an optional positional parameter as the first parameter:

SYNTAX
     [[-] <[]>] ...
  pwsh
 pwsh

The output from the two commands is identical. This includes the parameter name, which, even when it is optional, is less ambiguous and therefore a recommended practice.

Mandatory parameters

SYNTAX
      <string> ...

In this case, the Filter parameter name must be used, and it must be given a value. For example, to supply a Filter for the command, the Filter parameter must be explicitly written:

  'sAMAccountName -eq "SomeName"'

Mandatory positional parameters

Mandatory parameters must always be supplied, but in some cases, it is possible to supply the value without using the parameter name. The parameter the value applies to is based on position.

:/>  Диск загружен на 100 процентов в Windows 10 | remontka.pro

Parameters that are mandatory and accept values based on position are written with the parameter name only in square brackets, as shown here:

SYNTAX
     [-] <ADUser> ...
  useridentity
 useridentity

In both cases, the supplied value fills the Identity parameter.

The Add-Content command has a parameter set that uses more than one mandatory positional parameter. The first part of the syntax for the parameter set is shown here:

 [-] <string[]> [-] <object[]>
  c:\temp\file.txt  
    c:\temp\file.txt
   c:\temp\file.txt
 c:\temp\file.txt  
 c:\temp\file.txt 

The first of these is easiest to read as both parameters are explicitly named and tends to be the better style to use.

Each of the parameters so far has required an argument, a value. PowerShell also allows parameters that do not require arguments.

Switch parameters

A switch parameter does not require an argument. If the switch is present, the value is equivalent to true, while if the switch parameter is absent, it is equivalent to false.

As with the other types of parameters, optional use is denoted by using square brackets around the parameter.

Switch parameters are typically used to toggle a behavior on. For example, Recurse is a switch parameter for Get-ChildItem:

SYNTAX
     ... [-] ...

Using the switch instructs Get-ChildItem to recurse when listing the content of a directory, as shown here:

 c:\windows 

It is possible to supply a value for a switch parameter from a variable. This might be desirable when writing a script where the presence of a switch parameter is based on another variable. As switch parameters do not normally expect a value, a syntax change is required:

# Code which determines if Recurse is required
 = 
 c:\windows :

In some cases, a switch parameter will default to present, and it may be desirable to stop the parameter from applying. The most common example is the Confirm parameter, which will be explored later in this chapter.

Parameter values

 [-] <String>
  Win32_Service

ClassName must always be a single value. If more than one value is supplied, an error will be displayed:

>   Win32_Service, Win32_Process
: Cannot convert  to the   required by  . Specified method is not supported.
 [[-] <[]>]

In this case, the parameter type is an array of strings. An array may consist of one or more strings separated by a comma:

PS> Get-Service -Name WinDefend, WlanSvc
Status   Name               DisplayName
------   ----               -----------
Running  WinDefend          Windows Defender Antivirus Service
Running  WlanSvc            WLAN AutoConfig

PowerShell will attempt to coerce any value supplied into the required type. A single string can be used as an argument for the parameter. PowerShell will convert the single value into an array of strings with one element. For example:

  WinDefend

Each of the commands used in this section will allow the value to be entered without the parameter name. For example, for Get-Service, the Name parameter can be omitted:

 WinDefend
 WinDefend, WlanSvc

When using positional parameters, PowerShell can use the type to determine which parameter (and which parameter set) should be used.

Parameter sets

In PowerShell, a parameter set is a set of parameters that may be used together when running a command.

Many of the commands in PowerShell have more than one parameter set. This was seen when looking at the Syntax section when using Get-Help.

For example, the Stop-Process command has three parameter sets:

SYNTAX
     [-] <Int32[]> [-] [-] [-] [-] [<>]
  
     [-] <[]> [-] [-] [-] [-] [<>]
  
     [-] [-]  <String[]> [-] [-] [<>]

PowerShell will attempt to find a matching parameter set based on the parameters and values it is given.

The parameter sets for Stop-Process have two different sets that will accept a value by position:

 [-] <Int32[]>
 [-] <[]>

The first expects an ID as an integer. The second expects a Process object, an object returned by the Get-Process command.

 
 =  notepad 
  
 
 | 
  • Get-Help Stop-Process -Parameter *
  • Get-Help Stop-Process -Full

Examples are likely to show how to use the parameters with a pipeline.

If Get-Help is incomplete, Get-Command can be used to explore parameters:

Each of the parameter sets here also shows that the command supports common parameters.

Common parameters

Common parameters are used to control some of the standardized functionality PowerShell provides, such as verbose output and actions to take when errors occur.

When looking at the syntax, most commands will end with a CommonParameters item:

SYNTAX
     ... [<>]
  • Debug
  • ErrorAction
  • ErrorVariable
  • InformationAction
  • InformationVariable
  • OutBuffer
  • OutVariable
  • PipelineVariable
  • Verbose
  • WarningAction
  • WarningVariable

Each is described in the about_CommonParameters document:

 about_CommonParameters

The help document is also available online: .

For example, Stop-Process does not explicitly state that it has a Verbose switch parameter, but since Verbose is a common parameter, it may be used. This can be seen if notepad is started and immediately stopped:

Start-Process notepad -Verbose -PassThru | Stop-Process -Verbose
VERBOSE: Performing the operation "Stop-Process" on target "notepad (5592)".

Not so verbose

Just because a command supports common parameters does not mean it uses them. For example, Get-Process supports the Verbose parameter, yet it does not write any verbose output when Verbose is specified.

In addition to common parameters, PowerShell also offers specialized parameters for commands that make changes.

Confirm and WhatIf

Confirm and WhatIf can be used with commands that make changes to files, variables, data, and so on. These parameters are often used with commands that use the verbs New, Set, or Remove, but the parameters are not limited to specific verbs.

 about_Preference_Variables

The Confirm switch parameter is used to control automatic prompting for high impact operations by default.

Confirm and ConfirmPreference

The Confirm switch parameter and the ConfirmPreference variable can be used to decide if a command should prompt. The decision to prompt is based on a comparison of ConfirmPreference with ConfirmImpact when set by a command author.

ConfirmPreference has four possible values:

  • High: Prompts when command impact is High (default)
  • Medium: Prompts when command impact is Medium or High
  • Low: Prompts when command impact is Low, Medium, or High
  • None: Never prompts

ConfirmImpact uses the same four values.

In Windows PowerShell, the default value for ConfirmImpact is Medium.

Finding commands with a specific impact

$metadata.ConfirmImpact -eq 'High'

The Confirm switch parameter therefore causes a command to prompt before an action is taken; for example, the Confirm switch parameter forces Remove-Item to prompt when a file is to be removed:

Set-Location :TEMP
New-Item FileName.txt -Force
Remove-Item FileName.txt -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove File" on target "C:\Users\whoami\AppData\Local\Temp\FileName.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):

In the previous example, a confirmation prompt was explicitly requested. In a similar manner, confirmation prompts may be suppressed. For example, the value of the Confirm parameter may be explicitly set to false:

 
 FileName.txt 
 FileName.txt :

The ability to provide a value for the Confirm parameter is useful for commands that prompt by default; for example, Clear-RecycleBin prompts by default:

Clear-RecycleBin
  
Confirm
Are you sure you want to perform this action?
Performing the operation "Clear-RecycleBin" on target " All of the contents of the Recycle Bin".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):

Setting the Confirm parameter to false for Clear-RecycleBin bypasses the prompt and immediately empties the recycle bin:

 :

If the Confirm parameter is not set, whether a prompt is shown is determined by PowerShell. The value of the ConfirmPreference variable is compared with ConfirmImpact on a command.

There is more than one way to prompt

ShouldProcess is affected by the Confirm parameter and ConfirmPreference variable.

ShouldContinue is a forced prompt and is unaffected by the Confirm parameter and ConfirmPreference variable.

For example, Remove-Item will always prompt when attempting to delete a directory that is not empty without supplying the Recurse parameter.

It is not possible to easily discover commands using forced prompts. Reviewing documentation and testing is vital.


High

In scripts and functions, the ConfirmImpact setting is part of the CmdletBinding attribute:

:/>  Как почистить реестр на Windows 10 – инструкция

If CmdletBinding or ConfirmImpact is not present, the impact is Medium in Windows PowerShell and None in PowerShell 7.

The impact of a function or cmdlet may be viewed using the ConfirmImpact property of a command’s metadata:

A new value for ConfirmPreference may be set by assigning it in the console; for example, it can be set to Low. When the preference variable is set to Low, prompts may be raised by all commands where ConfirmImpact is Low, Medium, or High:

 = 

ConfirmPreference and the Confirm parameter

When ConfirmPreference is set to None to suppress confirmation prompts, confirmation may still be explicitly requested using the Confirm parameter; for example:

$ConfirmPreference = 'None'

New-Item NewFile.txt -Confirm

Support for confirmation also provides support for WhatIf.

WhatIf and WhatIfPreference

WhatIf is typically used when testing a command. If implemented correctly by a command author, WhatIf should allow a state-changing command to be run without it making the change.

WhatIf is not always implemented as expected

WhatIf support for a command is defined by a command author. If the author does not correctly handle the preference, an undesirable change may be made.

The Set-ADAccountPassword had a bug for a while where WhatIf was ignored.

Even if a command supports WhatIf, test it on small sets of data before using the parameter to verify a large change.

The WhatIf parameter has an associated preference variable, WhatIfPreference, which may be set to either true or false. The default value is false.

The WhatIf parameter replaces the confirmation prompt with a simple statement describing the action the command would have taken. Using Remove-Item as an example again, a message will be displayed, and the file will not be deleted:

Set-Location :TEMP
New-Item FileName.txt -Force
Remove-Item FileName.txt -WhatIf
What if: Performing the operation "Remove File" on target "C:\Users\whoami\AppData\Local\Temp\FileName.txt".

WhatIf can be explicitly set on a per-command basis by supplying a value in the same manner as the Confirm parameter. For example, WhatIf might be explicitly set to false:

 |  \test.txt :

Setting WhatIf in the manner used here might, for instance, be useful if a log file should be written even if other state-changing commands are ignored.

 = 
 = 
New-Item NewFile.txt -Confirm
What if: Performing the operation "Create File" on target "Destination: C:\Users\whoami\AppData\Local\Temp\NewFile.txt".

Restarting the console will restore preference variables to their default values.

The behavior of Confirm and WhatIf is prescribed by PowerShell. Parameters such as Force and PassThru are commonly used in PowerShell but have less well-defined behavior.

Force parameter

The Force parameter is not one of the common parameters with behavior defined by PowerShell itself, but the parameter is frequently used.

Force has no fixed usage; the effect of using Force is a choice a command author must make. Help documentation should state the effect of using Force with a command. For example, the use of Force with Remove-Item is available:

   Force

With the Force parameter, New-Item overwrites any existing file with the same path. When used with Remove-Item, the Force parameter allows the removal of files with Hidden or System attributes.

 
 FileName.txt 
 FileName.txt  Attributes  
 FileName.txt
: You do not have sufficient access rights to perform this operation or the item is hidden, system, or read only. RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand

Adding the Force parameter allows the operation to continue:

 FileName.txt 

The Force parameter may be worth exploring if a command is prompting, and the prompts cannot be suppressed using the Confirm parameter or the ConfirmPreference variable.

PassThru parameter

The PassThru parameter, like Force, is frequently used, but the behavior of the parameter is not defined by PowerShell. However, PassThru tends to have predictable behavior.

The PassThru parameter is typically used with commands that do not normally generate output and is used to force the command to return the object it was working with.

For example, the Start-Process command does not normally return any output. If PassThru is used, it will return the process it created:

Start-Process notepad -PassThru
 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
      9     1.98       6.70       0.05   22636   1 notepad

The PassThru parameter is therefore useful if more work is to be done with the object after the first command has finished.

For example, PassThru might be used with Set-Service, which ordinarily does not return output, allowing a service to be started immediately after another change:

 Audiosrv |
      Automatic  |
    

Parameters in PowerShell are a complex topic but are a vital part of working with the language.

In my last article, I introduced the Practical PowerShell series. When working on PowerShell scripts, there might come a point where a set of instructions repeats code elsewhere in the script. It is also possible that you might want to incorporate code from elsewhere into your script so that you can easily call the code.

This description might remind you about cmdlets, which have names and, optionally, one or more parameters to control their operation. But what if you want the same thing for your code, like some code with a high reusability factor? Welcome to the world of PowerShell functions. Before we get too deep, let’s define exactly what we are talking about.

Scripts

A script is a text file with a .ps1 extension containing PowerShell code. The code consists of cmdlets and (optionally) functions. You can call scripts in various ways:

  • Using the ampersand (& .\Process-Something.ps1). The code runs in a child session with its scope. This means any definitions, such as variables or functions in the script, disappear when the script terminates. When you run interactive PowerShell scripts, you usually omit the ampersand, but when you want to run code pointed to in a variable, you must use this invocation method, e.g., & { Get-ChildItem }

    Make sure to understand the difference between using the ampersand at the start and end of a command. Using an ampersand at the end instructs PowerShell to run the code in a background job.

  • Using dot-sourcing (e.g. .\Helper-Functions.ps1)., the code runs in the current PowerShell session. This means that any variables or functions you define in the script become available in the session. If these definitions existed before, they would simply be overwritten.

The ability to run PowerShell scripts depends on the local machine’s current execution policy. This is a security measure to prevent malicious scripts from running. Scripts from Microsoft are generally signed, but many community-sourced scripts downloaded from the internet are usually not. You may need to run Set-ExecutionPolicy unrestricted before you can run scripts created by others, provided company policies do not prevent you from modifying the execution policy.

Обновление переменных среды сеанса

Reusable Code

Function Get-MyReport {
    #reusable code
}

If you create a function that redefines an existing command, the existing definition is overwritten in the current session. The code’s output will be returned to the caller, and you can output the result to the screen or assign it to a variable for further processing.

In addition to the function itself, you can also define parameters for the code contained in the function. The code within the function can then perform its task using information passed through the parameters, as the parameters become variables usable in the context of the function’s code.

Function Get-DistributionGroupInfo( $Identity, $MemberCount)
{
    Get-DistributionGroup $Identity | Select-Object Identity,PrimarySmtpAddress, @{n='MemberCount';e={ If( $MemberCount) { (Get-DistributionGroupMember -Identity $_ | Measure-Object).Count } }}}
}

This code is acceptable when drafting a script or working on a proof of concept. However, issues might become apparent when using the function later or somebody else who is less familiar with the use case takes responsibility for the code.

Among the issues with this function are:

  • The distribution group passed in the variable $Identity can be unspecified ($null). This can lead to unintended side effects, as many Get cmdlets happily return all objects when you specify $null as a value. Take the following code:
Function Process-Mailbox( $Id) {
    Get-Mailbox -Identity $Id | Set-Mailbox -HiddenFromAddressListEnabled $True
}

Can you guess what happens if you do not pass the ID parameter or when the ID is empty? All mailboxes are returned and Set-Mailbox will happily hide all the mailboxes from address lists. It is probably not something you intended.

  • In the example above, Identity and Members can be anything; they do not need to be a distribution group or switch, respectively. You might add code that checks if $Identity is a distribution group and if Members is a Boolean ($true or $false), but that would require additional code. The code might become quite complex if it must process multiple parameters.
Function Get-DistributionGroupInfo {
    [CmdletBinding()]
    Param(

        [Parameter(Position= 0, Mandatory= $true, ValueFromPipeline= $true, ValueFromPipelineByPropertyName=$true, HelpMessage= 'Please provide a Distribution Group')]
        [String]$Identity,

        [Parameter(HelpMessage= 'Output member count')]
        [Switch]$MemberCount
    )
    Process {
        Write-Verbose ('Fetching Distribution Group {0}' -f $Identity)
        Get-DistributionGroup $Identity | Select-Object Identity,PrimarySmtpAddress, @{n='MemberCount';e={ If( $MemberCount) { (Get-DistributionGroupMember -Identity $_ | Measure-Object).Count } }}
    }
}
  • [CmdletBinding()] before the first parameter definition tells PowerShell that the function supports common parameters. Examples of common parameters are Verbose and Confirm. You can then include code in your function to support this. For example, if you pass -Verbose and your function contains Write-Verbose commands, verbose output will be displayed. When you omit -Verbose, the output is not displayed.
  • Position=0 in the first parameter specification instructs PowerShell that the first unnamed parameter passed to Get-DistributionGroupInfo is treated as the Identity. So, the following two commands are the same:
Get-DistributionGroupInfo -Identity 'DG-X'
Get-DistributionGroupInfo 'DG-X'

Additional unnamed parameters can be specified as Position=1, etc.

  • Mandatory=$true tells PowerShell that this parameter is mandatory. When a user omits the Identity when running the script, PowerShell will ask for it. Parameters can be optional by setting Mandatory to $false or omitting the condition.
  • We want to be able to pass the Identity when the function is called in a pipeline. You can enable pipeline usage for this parameter by specifying ValueFromPipeline. You can use the property of passed objects by specifying ValueFromPipelineByPropertyName. Calling the function in a pipeline can then look like this:
Get-DistributionGroup -Identity 'DG-X' | Get-DistributionGroupInfo
  • When you omit a mandatory parameter, HelpMessage defines help information. This help information is displayed when you enter !? when PowerShell asks you for input, and it is also displayed when you use:
Get-Help Get-DistributionGroupInfo -Full

I do not know anyone who uses !?, but you can if you want.

  • After specifying the constraints, you define the parameter itself. You do this by giving it a name or, in this case, an identity. This name contains the value passed as a parameter when the function is called, making it available within its scope. You can optionally define the type of object the parameter will accept. In this case, we specify [String], which equals [System.String], but PowerShell has some type accelerators (short aliases) for built-in types.
Function Test {
    param(
        [int]$A
    )
    Write-Output ($A)
}
❯ test -A 123
123
❯ test -A 'string'
Test: Cannot process argument transformation on parameter 'A'. Cannot convert value "string" to type "System.Int32". Error: "The input string 'string' was not in a correct format."

I recommend using strict typing with parameters whenever possible. Typing helps with troubleshooting usage and also helps to document the code, as explained later. One thing to consider is that values might get converted through interpretation. For example, if you pass a parameter value 123, and a string is expected, PowerShell will happily convert this to a string representation, ‘123’.

  • The second parameter (note the comma after Identity) is a Switch named MemberCount. Since this parameter is not mandatory and pipeline usage is unnecessary, these are not specified in the definition. The nice thing with switches is that you can use them just by mentioning, e.g. –MemberCount ; will set the MemberCount variable to $true. When you do not, it will be $false. You cannot use -MemberCount $true, as PowerShell will interpret $true as the next parameter since MemberCount is a switch. If needed, for example when $true or $false is stored in a variable, you can set it using a variable by specifying <Switch>:<value>, e.g. -MemberCount:$false. You might already be using this syntax when avoiding having to confirm certain commands, e.g. Set-Mailbox … -Confirm:$False
  • By putting the code performing the actual task in a Process script block {}, we make the function work for objects passed through the pipeline. If we omit this and leave the code as-is, it will not support pipelining, and the code will only execute once for the last object received through the pipeline. Note that the current object in the pipeline is available through the automatic variable $_, if needed, within the Process script block.
:/>  Как почистить реестр на Windows 10 – инструкция

When we put the code for this function in a script file, for example, MyDemo.ps1, it becomes available within our PowerShell session. To accomplish this, we need to dot source it to define it in our session. We can then call it – provided the Exchange Online Management Shell is loaded and connected – and inspect its definition by calling Get-Help, which also includes documentation.

PS❯ . .\MyDemo.ps1

PS❯ Get-DistributionGroupInfo -Identity MyDG -MemberCount -Verbose
VERBOSE: Fetching Distribution Group MyDG
Identity PrimarySmtpAddress MemberCount
-------- ------------------ -----------
MyDG     MyDG@contoso.com             2

PS❯ Get-DistributionGroup | Get-DistributionGroupInfo -MemberCount

Identity              PrimarySmtpAddress          MemberCount
--------              ------------------          -----------
MyDG                  MyDG@contoso.com                      2
OtherDG               OtherDG@contoso.com                   8

PS❯ Get-Help Get-DistributionGroupInfo -Full

NAME
    Get-DistributionGroupInfo

SYNTAX

    Get-DistributionGroupInfo [-Identity] <string> [-MemberCount] [<CommonParameters>]

PARAMETERS

    -Identity <string>
        Please provide a Distribution Group.

        Required?                    True
        Position?                    0
        Accept pipeline input?       true (ByValue)
        Parameter set name           (All)
        Aliases                      None
        Dynamic?                     False
        Accept wildcard characters?  False

    -MemberCount
        Output member count

        Required?                    False
        Position?                    Named
        Accept pipeline input?       False
        Parameter set name           (All)
        Aliases                      None
        Dynamic?                     False
        Accept wildcard characters?  False

    <CommonParameters>
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see
        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).

Begin, Process, End

Begin {
        # Initialize
        $Items=0
    }
    Process {
        # Do Something
        $Items++
    }
    End {
        # Cleanup
        Write-Host ('We processed {0} object(s)' -f $Items)
    }

An example is when you want to count how many objects you have processed, as the number of objects passed through a pipeline is unknown upfront. Another example of this would be the Sort-Object command, which can only sort objects when all objects have been passed to it.

Script Parameters

[CmdletBinding()]
Param(
    [parameter( Mandatory= $true)
    [ValidateScript({ Test-Path -Path $_ -PathType Leaf})]
    [String]$CSVFile,
    [ValidateSet(',', ';')]
    [string]$Delimiter=',',
    [System.Security.SecureString]$Password
)

Function X {
    # …
}
#etc.
  • Ask to provide a value for $CSVFile when one has not been given (Mandatory= $true). You will notice a ValidateScript line as part of the CSVFile parameter definition. When specifying parameters, you can have PowerShell perform certain validations against the values provided. Some of the possible tests are:
    • ValidateScript is used to execute a script block that needs to result in $true for the parameter value to be accepted. In the example, we check if the filename is valid using Test-Path specifying the automatic variable $_ (the actual filename).
    • ValidateSet to test the value against a set of predefined values. In the example, we use ValidateSet only to allow a comma or semi-colon for the $Delimiter parameter.
  • The delimiter parameter can be specified. If it is not specified (not mandatory), we set it to a default value of ‘,.’
  • A $Password parameter can be provided. When specified, it needs to be of the type [System.Security.SecureString]. You are not limited to PowerShell’s built-in types; you can also use other (.NET) types, such as SecureString or a credential of the type [PSCredential].

Обновление переменных среды сеанса

Make PowerShell Work for You

It is ambitious to discuss functions and parameters in PowerShell in one article. I have not touched on other subjects, such as command sets and dynamic parameters. These might be topics for another article.

I hope that I have encouraged you to write reusable code, not only to leverage scripts and functions but also to correctly define code. Make PowerShell work for you when possible, letting it handle parameter validation and checking other constraints such as types. This enables you to focus on the task while making code less complex and improving readability.

If you have questions or comments, feel free to reach out in the comments. If not, wait until the next article, where I will discuss flow control.

Member/Get-MemberType.ps1

Оставьте комментарий