I have this powershell example that does not throw any error or exception.
However, NOTHING is printed on the output.
I am not able to find the reason
Maybe I don't call the Add-Values function correctly?
<#
.Synopsis
To add two integer values
.DESCRIPTION
Windows PowerShell Script Demo to add two values
This accepts pipeline values
.EXAMPLE
Add-Values -Param1 20 -Param2 30
.EXAMPLE
12,23 | Add-Values
#>
function Add-Values
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
#Accepts Only Integer
[int]$Param1,
#Accepts only interger
[Parameter(Mandatory=$true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[int]$Param2
)
Begin
{
"Script Begins"
}
Process
{
$result = $Param1 + $Param2
}
End
{
$result
}
}
pause
Remove the pause? Then paste your whole function into powershell. After that, try your function.
It kinda works for me.
PS ~>Add-Values -Param1 1 -Param2 2
Script Begins
3
parameter binding by datatype will give you the wrong result (it will use the last value for both parameters.
PS ~>1, 2 | Add-Values
Script Begins
4
Related
Sometimes I invoke powershell scripts from Linux bash/shell scripts like so:
pwsh MyScript.ps1 win-x64 false
And in my MyScript.ps1 file, I set up parameters like so:
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string] $runtime,
[Parameter()]
[bool] $singleFile = $true
)
I get an error for the second parameter:
Cannot process argument transformation on parameter 'singleFile'. Cannot convert value "System.String" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.
I tried passing '$false' as well as 0 but it treats everything as a string. When invoking powershell scripts from outside of a PWSH terminal, how do I get it to coerce my string-boolean value into an actual Powershell boolean type?
I propose to use [switch]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string] $runtime,
[Parameter()]
[switch] $singleFile
)
Write-Host $runtime
It works for me with :
pwsh ".\MyScript.ps1" "toto" -singlefile
In fact your code is working with :
pwsh ".\MyScript.ps1" toto -singleFile 1
I am implementing a function in Powershell which will perform REST calls. One of the parameters may differ in contents, depending on given scenarios. For instance, the body of the REST call may be a string or a hash table. How do you implement this within the CmdletBinding() declaration?
For instance
Function doRESTcall(){
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[Hashtable]$headers
[Parameter(Mandatory=$true)]
[???????]$body # what type here??
)
.
.
.
}
To declare parameters where any type is allowed you can either not type-constrain the parameter at all or use type constraint [object] (System.Object), by doing so, no type conversion will be needed, since all objects in PowerShell inherit from this type.
It's worth mentioning that unconstrained parameters will allow $null as argument, to avoid this, [ValidateNotNull()] and / or [parameter(Mandatory)] can be used.
function Test-Type {
param(
[parameter(ValueFromPipeline, Mandatory)]
[object]$Value
)
process
{
[pscustomobject]#{
Type = $Value.GetType().FullName
IsObject = $Value -is [object]
}
}
}
PS /> 1, 'foo', (Get-Date) | Test-Type
Type IsObject
---- --------
System.Int32 True
System.String True
System.DateTime True
The correct way to tackel this is to create a ParameterSet:
Function doRESTcall(){
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ParameterSetName = 'StringBody', Position = 0)]
[Parameter(Mandatory=$true, ParameterSetName = 'HashBody', Position = 0)]
[Hashtable]$headers,
[Parameter(Mandatory=$true, ParameterSetName = 'StringBody', Position = 1)]
[String]$Stringbody,
[Parameter(Mandatory=$true, ParameterSetName = 'HashBody', Position = 1)]
[Hashtable]$Hashbody
)
Write-Host 'Parameter set:' $PSCmdlet.ParameterSetName
Write-Host 'StringBody:' $StringBody
Write-Host 'HashBody:' $HashBody
}
doRESTcall -?
NAME
doRESTcall
SYNTAX
doRESTcall [-headers] <hashtable> [-Hashbody] <hashtable> [<CommonParameters>]
doRESTcall [-headers] <hashtable> [-Stringbody] <string> [<CommonParameters>]
ALIASES
None
REMARKS
None
doRESTcall #{a = 1} 'Test'
Parameter set: StringBody
StringBody: Test
HashBody:
Note: to accept a larger variety of dictionaries (like [Ordered]), I would use a [System.Collections.Specialized.OrderedDictionary] (rather than [Hashtable]) type for the concerned parameters.
I am building an Azure Runbook helper function, that ultimately executes on a Hybrid Runbook Worker.
To generalize my code as much as possible I came up with the idea to have a function dynamically build a scriptblock that defines the Exchange Cmdlet name and parameter.This is what I have so far - the comments are experiments that reveal some of the steps I tried before posting this thread.
function Invoke-BSExchangeCommand{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$CmdletName,
[Parameter(Mandatory = $false)]
[hashtable]
$ArgumentList,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Runspaces.PSSession]
$Session
)
$scriptBlock = {
param ($invokeParams)
# Get-DistributionGroup #invokeParams
# $_::$CmdletName.Invoke($invokeParams)
$cmd = Get-Command -Name $CmdletName
& $cmd #invokeParams
}
$params = #{
Session = $Session
ArgumentList = $ArgumentList
ScriptBlock = $scriptBlock
}
Invoke-Command #params
}
Edit: I have found that the "Get-Command" cmdlet is exposed/not restricted on the Exchange endpoint.
The error I am getting is a generic one and gives many different (irrelevant) Google search results: A Begin statement block, Process statement block, or parameter statement is not allowed in a Data section
Edit: My starting point that I am trying to improve is that this scriptblock with the defined Cmdlet name works:
$scriptBlock = {
param ($invokeParams)
Get-DistributionGroup #invokeParams
}
Thank you!
-Anders
I am editing a function which it will invoke a command directly on the VM. The issue I keep running into is if someone passes a function declaration as a scriptblock, I get and error when calling create, because params() is not at the top of the scriptblock.
Trying to figure out how I can still set-fulllanguage first then execute a function with params.
function Invoke-DirectOnVM
{
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[CloudEngine.Configurations.EceInterfaceParameters]
$Parameters,
[Parameter(Mandatory = $true)]
[String[]]$VMNames,
[Parameter(Mandatory = $true)]
[Object]$VMCredential,
[Parameter(Mandatory = $true)]
[ScriptBlock]$ScriptBlock,
[Object[]]$ArgumentList = $null
)
{
Invoke-Command -VMName $localVMs -Credential $using:VMCredential -ScriptBlock ([ScriptBlock]::Create($("Import-Module OpenUpSession; Set-FullLanguage; `r`n" + $using:ScriptBlock)))
}
Remove the $using: from the scriptblock and it should work properly. I took the liberty of cleaning up the code a bit. The result looks like:
function Invoke-DirectOnVM
{
[CmdletBinding()]
Param (
[Parameter(Mandatory)]
[CloudEngine.Configurations.EceInterfaceParameters]
$Parameters,
[Parameter(Mandatory)]
[String[]]
$VMNames,
[Parameter(Mandatory)]
$VMCredential,
[Parameter(Mandatory)]
[ScriptBlock]
$ScriptBlock,
[Parameter()]
[Object[]]
$ArgumentList = $null
)
$PSBoundParameters.Remove("ScriptBlock")
Invoke-Command #PSBoundParameters -ScriptBlock ([ScriptBlock]::Create( "Import-Module OpenUpSession; Set-FullLanguage; `r`n" + $ScriptBlock ))
}
I am trying to find the way to create values for parameters that can be auto completed or show all available options with tab, like the value "allsigned" in the cmdlet
Set-ExecutionPolicy -ExecutionPolicy AllSigned
¿Any ideas about how this is called in programation or how can I achieve this ?
yes its called validateset
Param
(
[parameter(Mandatory=$true)]
[ValidateSet("Low", "Average", "High")]
[String[]]
$Detail
)
advanced functions/cmdlets or just parameter validation, parameter sets, etc
snippet from the ISE:
function Verb-Noun
{
[CmdletBinding(DefaultParameterSetName='Parameter Set 1',
SupportsShouldProcess=$true,
PositionalBinding=$false,
HelpUri = 'http://www.microsoft.com/',
ConfirmImpact='Medium')]
[Alias()]
[OutputType([String])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='Parameter Set 1')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateCount(0,5)]
[ValidateSet("sun", "moon", "earth")]
[Alias("p1")]
$Param1,
# Param2 help description
[Parameter(ParameterSetName='Parameter Set 1')]
[AllowNull()]
[AllowEmptyCollection()]
[AllowEmptyString()]
[ValidateScript({$true})]
[ValidateRange(0,5)]
[int]
$Param2,
# Param3 help description
[Parameter(ParameterSetName='Another Parameter Set')]
[ValidatePattern("[a-z]*")]
[ValidateLength(0,15)]
[String]
$Param3
)
Begin
{
}
Process
{
if ($pscmdlet.ShouldProcess("Target", "Operation"))
{
}
}
End
{
}
}