Passing bool parameters to my script always results in the same output - powershell

So I'm working on a script and I would like to add an optional parameter. For some reason it doesn't work the way I thought it should, so clearly I'm not getting something here.
I tried 2 methods:
Method 1
function Thing {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)][bool]$StartThing
)
if ($StartThing -eq $true) {
Write-Host "Thing started" -ForegroundColor Green
}
else {
Write-Host "Thing didn't start" -ForegroundColor Red
}
}
Thing
Then, I'm running: .\test.ps1 -StartThing $true
The output I'm getting is always Thing didn't start. No matter what value I pass in.
Method 2
I tried using switch instead in this form:
function Thing {
param (
[switch] $StartThing
)
switch ($StartThing) {
$true { Write-Host "Thing started" -ForegroundColor Green }
Default { Write-Host "Thing didn't start" -ForegroundColor Red }
}
}
Thing -StartThing
This one doesn't work for me either. When I run .\test.ps1 -StartThing the output is always Thing started. I tried adding $true or $false inputs but the output is the same no matter what.
I'm not sure what I'm doing wrong.
Any help would be great :)

StartThing is not being passed to your function. You always run is without any params (example from method 1, for method 2 the issue is similar):
Thing
If you want to run the file in the form provided, you need to add param block to the script file itself.
NOTE: Only relevant parts of code were added, I haven't changed the working parts. Please see Olaf's helpful answer to improve the script even better:
# Param block for script
param (
[Parameter(Mandatory=$false)][bool]$StartThing
)
function Thing {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)][bool]$StartThing
)
if ($StartThing -eq $true) {
Write-Host "Thing started" -ForegroundColor Green
}
else {
Write-Host "Thing didn't start" -ForegroundColor Red
}
}
# Function runs with the parameter provided
Thing -StartThing $StartThing

This might clear it up a little:
function Thing {
param (
[switch] $StartThing
)
if ($StartThing) {
"You provided the parameter 'StartThing'"
}
else {
"You did not provide the parameter 'StartThing'"
}
}
Now you simply run your function with
Thing -StartThing
And the result would be:
You provided the parameter 'StartThing'

Related

Second function inside an if with an -And doesn't get executed (Powershell)

I have the following functions
function checkA {
Write-Host "Checking A"
return $true
}
function checkB {
Write-Host "Checking B"
return $true
}
Now, in the main program I use both functions like:
if(checkA -And checkB){
Write-Host "Checks are ok"
return
}
I'm not getting the checkB Write-Host output and the IDE says the function is not even referenced when used like this.
Can someone tell me what's going on?
PowerShell is treating the -And as a parameter to checkA and checkB as the value of the parameter. Since checkB is not recognised as a function here, it is never called.
If you wrap the function calls in brackets, it should work as expected:
if((checkA) -And (checkB)){
Write-Host "Checks are ok"
return
}

PowerShell Modify cmdlet in function

I want to create a Function to run couple of cmdlets.
For Example:
Test-AcctDBConnection -DBConnection $CTXDBString
Test-AdminDBConnection -DBConnection $CTXDBString
All Commands are basicly the same. Just modified after Test-$someParam
I want to create a simple function like this
function CTX-Check {
Param([string]$Check_Service)
Write-Host $Check_Service
try {
Test-$Check_Service -DBConnection $CTXDBString
} catch {
Write-Host -ForegroundColor Yellow $_.Exception.Message
}
}
Some Ideas to solve this issue? If I do the same with Set-$someParam that works fine.
If all of your commands take the same parameters, you can do something like this:
function Test-Citrix {
[CmdletBinding()]
param(
[string]
$Service,
[string]
$DBConnection
)
$PSBoundParameters.Remove('Service')
foreach ($cmd in (Get-Command -Verb Test | ? Source -like Citrix*)) {
& $cmd.Definition #PSBoundParameters
}
}
Note: this will only work with functions, not cmdlets to my knowledge. There are some extra steps involved there.

powershell parameters command line menu

I wish to create a script which accepts input from the command line and based on the first value, it then determines the next parameters on offer.
Such as to determine if you are to do a single Run or a Batch run for a Password change operation:
./script.ps1 -singleMODE -UserName -Password
./script.ps1 -batchMODE -filename
What i am confused about whilst learning Powershell is what this is? I have looked at Parameters and can read them into variables from command line...but what i want as above has some logic and i am a bit lost. Can someone give me a nudge as to what this is called....and then i can continue my googling! :)
I am thinking somehow i combine Params and Functions so it flicks to different blocks...but i am guessing
any help appreciated! :)
cheers
What you need are Parameter Sets
This is a demo with a function but it works just as well with a script (just put the param block at the top.)
function Demo {
param(
[Parameter(ParameterSetName='Funk')][switch]$Funk,
[Parameter(ParameterSetName='Rock')][switch]$Rock,
[Parameter(ParameterSetName='Funk')][string]$WriteFunk,
[Parameter(ParameterSetName='Rock')][string]$WriteRock
)
if($Funk){
foreach ($C in $WriteFunk.ToCharArray()){
$N = 0..15 | Get-Random
Write-Host $C -ForegroundColor $N -BackgroundColor $(15-$N) -NoNewline
}
Write-Host ''
}
if($Rock){
Write-Host $WriteRock -ForegroundColor Gray -BackgroundColor DarkGray
}
}
Demo -Funk -WriteFunk "Melt your brain"
Demo -Rock -WriteRock "Riders on the storm"

Write-Output not working inside a callback

I have the following code inside a PowerShell function:
$client.List($target, {
param ($sender, $e)
Write-Host "Here it is: $e"
Write-Output $e
})
(client is a SharpSvn.SvnClient, and $target is some repository URL)
When I run it (just calling my function in console), I get a list of "Here it is: SharpSvn.SvnListEventArgs" for each of the item in repository, so I know the callback is executed.
However actual items are not put into the output (either pipeline or console).
If I put Write-Output outside the callback, the item is processed correctly, so I assume it has something with being in a callback block.
How do I make callback block process Write-Output correctly?
What's happening is that the ScriptBlock is getting converted into a delegate (EventHandler<SvnListEventArgs>) which returns void so Write-Output doesn't have anywhere to send the output. It's a bit like this:
[Action]$action = { Write-Host "Test"; Write-Output "Test" }
$action.Invoke()
Since Action doesn't return anything there is no where for the result of Write-Output to go. Now if the delegate returned an object it would work:
[Func[object]]$func = { Write-Host "Test"; Write-Output "Test"; Write-Output "Test2" }
$func.Invoke()
I guessing the way Write-Output works under the hood is that it sends the output somewhere which will cause all the outputs to be returned, if possible, when execution exits the script block. It doesn't have a reference the "current pipeline" or "currently executing function", so it can't write there directly.
I think the way to go about capturing the output is to do something like this:
$list = new-object System.Collections.Generic.List[Object]
$client.List($target, {
param ($sender, $e)
Write-Host "Here it is: $e"
$list.Add($e)
})
Write-Output $list
You could try to use:
$PSCmdlet.WriteObject("Here it is: $e")

Debugging PowerShell

I'm not certain what is wrong with this scriptlet.
I'm trying to break out functionality into several other functions (I have a programming background not a scripting one per se) and to me LOGICALLY the following should execute starting at the "main" function Test-SgnedMpsPackage, accepting the various optional parameters (the script is not yet complete) then when the function Check-Path is called, that is run, then work would resume in the original calling function.
Am I missing something here?
On a side note, how does one return a value to the calling function? a simple return?
function CheckPath($path)
{
if ( test-path -Path $path )
{ Write-Host "{0} confirmed to exist." -f $path }
else
{ Write-Host "{0} DOES NOT exis.\nPlease check and run the script again" -f $path }
exit { exit }
}
function Test-SignedMpsPackage
{
Param(
[string] $PkgSource,
[string] $SigSource,
[string] $Destination
)
Process
{
#Check that both files exist
Write-Host "Check for file existence..."
CheckPath($PkgSource)
CheckPath($SigSource)
#retrieve signatures from file
}
}
Unlike C, C++ or C# there is no "main" entry point function. Any script at the top level - outside of a function - executes. You have defined two functions above but you haven't called either one. You need to do something like this:
function Test-SignedMpsPackage
{
...
}
Test-SignedMpsPackage params
Also as mentioned by #Bill_Stewart, you call your defined functions just like you call PowerShell commands - arguments are space separated and you don't use parens except to evaluate an expression inside the parens.
As for returning a value from a function, any output (Output stream) not captured by assigning to a variable or being redirected to a file is automatically part of the function's output. So I would modify your CheckPath function to this:
function CheckPath($path)
{
if (Test-Path -Path $path) {
Write-Verbose "{0} confirmed to exist." -f $path
$true
}
else {
Write-Verbose "{0} DOES NOT exist.\nPlease check and run the script again" -f $path
$false
}
}
You can use Write-Host as you had before but sometimes, perhaps in a script, you don't want to see the extra output. That is where Write-Verbose comes in handy. Set $VerbosePreference = 'Continue' to see the verbose output.