I have read in different sources that the SWITCH statement yields better performance than multiple IF statements. I have the following blocks of IF statements which have parallel conditions. Is it possible to do this in a SWITCH block?
if (($statusCode -eq "OK:") -and ($messageOutput)) {
$returnValue = 0
return $returnValue
}
if (($statusCode -eq "WARNING:") -and ($messageOutput)) {
$returnValue = 1
return $returnValue
}
Thanks in advance,
You have a constant here which is $messageOutput, so the conditions aren't really parallel. You could do:
if($messageOutput) {
switch ($statusCode) {
"OK:" { 0 }
"WARNING:" { 1 }
default { 1 }
}
}
This would be more efficient as you don't need to recheck each variable for each condition.
Arco444 has the best answer for this particular case. However it is worth noting that it is possible to have multiple conditions in a switch block. In case another SO user finds their way here:
Switch($true){
(($statusCode -eq "OK:") -and ($messageOutput)){"Alright"}
(($statusCode -eq "WARNING:") -and ($messageOutput)){"Not Alright"}
default{"Something Wrong"}
}
The conditions are all evalutaed based on if the are $true. The default would catch if none of the other conditions are true.
Here's one way to approach multiple conditions with a Switch:
Switch ([string][int[]]($Condition1,$Condition2))
{
'1 1' { 'Both conditions are true' }
'1 0' { 'Condition1 is true and Condition2 is false' }
'0 1' { 'Condition1 is false and Condition2 is true' }
'0 0' { 'Both conditions are false' }
}
Related
How do I call methods within workflow?
I am trying to call "Task" from within a workflow and it seems to be getting ignored? I have provided a watered down nonsense code to illustrate what I'm trying to do. basically call a method within the class in parallel and return the results.
Sample Code
Class Something {
[string]Task($item) {
Start-sleep -Seconds 10
Return "Result"
}
[System.Array]GetSomething($list) {
workflow GetWF {
param($listarr)
ForEach -parallel ($item in $listarr) {
$res = InlineScript {
Write-Host("Starting.." + $using:item)
$this.Task($using:item)
}
}
$res
}
Return GetWF -listarr $list
}
}
$list = #('host1','host2','host3','host4')
$Something = [Something]::New()
$Something.GetSomething($list)
Output :
Starting..host1
Starting..host4
Starting..host2
Starting..host3
Desired Result from Example
The issue is how do I get my results back as an array ? In this example above I would like to see the final result to be this:
$Result = #("Result","Result","Result","Result")
I am working on implementing a singleton class to store some regularly accessed status information for my script, including hacking around the issue of $myInvocation only being populated in the main script. All working as planned with this.
class pxStatus {
static [pxStatus] $singleton = $null
[string]$Context = 'machine'
[string]$Path = $null
[datetime]$StartTime = (Get-Date)
pxStatus ([string]$path) {
if ([pxStatus]::singleton -eq $null) {
$this.Path = $path
[pxStatus]::singleton = $this
} else {
Throw "Singleton already initialized"
}
}
static [pxStatus] Get() {
if ([pxStatus]::singleton -eq $null) {
Throw "Singleton not yet initialized"
} else {
return [pxStatus]::singleton
}
}
}
CLS
[void]([pxStatus]::New((Split-Path ($myInvocation.myCommand.path) -parent)))
([pxStatus]::Get()).StartTime
([pxStatus]::Get()).Context
([pxStatus]::Get()).Path
With one exception. Even with that [void] on the [pxStatus]::New() line, I am getting a blank line in the console. Even $null = ([pxStatus]::New((Split-Path ($myInvocation.myCommand.path) -parent))) is echoing a blank line to the console. And for the life of me I can't see what is causing it.
It's not new that causes a blank line but ([pxStatus]::Get()).StartTime.
To fix the issue, you may output it as string, i.e. not formatted, e.g. ([pxStatus]::Get()).StartTime.ToString()
You problem has already been diagnosed, but I wanted to take a second to show how to actually implement a singleton-like type in PowerShell (see inline comments):
class pxStatus {
# hide backing field from user
hidden static [pxStatus] $singleton = $null
[string]$Context = 'machine'
[string]$Path = $null
[datetime]$StartTime = (Get-Date)
# hide instance constructor, no one should call this directly
hidden pxStatus ([string]$path) {
# Only allow to run if singleton instance doesn't exist already
if ($null -eq [pxStatus]::singleton) {
$this.Path = $path
} else {
Throw "Singleton already initialized - use [pxStatus]::Get()"
}
}
# Use a static constructor to initialize singleton
# guaranteed to only run once, before [pxStatus]::Get() or [pxStatus]::singleton
static pxStatus () {
# grab the path from context, don't rely on user input
if(-not $PSScriptRoot){
throw "[pxStatus] can only be used in scripts!"
}
# this will only succeed once anyway
[pxStatus]::singleton = [pxStatus]::new($PSScriptRoot)
}
static [pxStatus] Get() {
# No need to (double-)check ::singleton, static ctor will have run already
return [pxStatus]::singleton
}
}
[pxStatus]::Get().StartTime
Pardon me if this question has already been answered on this site. I haven't been able to find it through my research thus far.
Question:
As I step through each row of formatted table , I'm trying to determine if a column (CompletionDate) is missing it's value
Below is an example table:
DueDate, StartDate, CompletionDate
2017-06-10T22:00:29.08, 2017-05-30T20:38:37.913, 2017-05-30T20:44:05.517
2017-06-09T16:00:21.38, 2017-06-07T15:55:14.627,
Below is some of my code thus far:
foreach ($row in $tableData) {
if ($row.CompletionDate -eq ''){
write-host 'no value'
}
else {
Write-Host 'has value'
}
}
Thanks in advance for your help. If this question has been answered before, please just let me know where it is, and I'll take this question down.
}
You can use the IsNullOrEmpty method:
foreach ($row in $tableData) {
if ([string]::IsNullOrEmpty($row.CompletionDate)){
write-host 'no value'
}
else {
Write-Host 'has value'
}
}
try this
foreach ($row in $tableData)
{
if ($row.CompletionDate)
{
'has value'
}
else
{
'no value'
}
}
I have a quick powershell syntax question. I have following loop in powershell. I would like to know which value exists (which is easy). I can use either "Read" or "Visitor" to assign permission. I can do 2 if statements but if there is a smarter way i would rather use that.
if(($listRA.Member.Name) -ne $authUsers)
{
foreach($spRoleDefinition in $rc)
{
if(($spRoleDefinition.Name -eq "Read") -OR ($spRoleDefinition.Name -eq "SP Visitor"))
{
Need to determine which one exists
Adding a user code....
write-host $spRoleDefinition.Name
}
}
}
Use a switch statement:
if(($listRA.Member.Name) -ne $authUsers)
{
foreach($spRoleDefinition in $rc)
{
switch($spRoleDefinition.Name)
{
'Read' {
# do Read stuff
break;
}
'SP Visitor' {
# do SP Visitor stuff
break;
}
}
}
}
I have some piece of code for multiple conditions in Perl
if (/abc/ && !/def/ && !/ghi/ && jkl) {
#### do something
}
Will every condition will be evaluated at once on every line?
I can prioritize the conditions using nested ifs
if (/abc/){
if (!/def/){
....so on
}
&& short-circuits. It only evaluates its RHS operand if needed. If it's LHS operand returns something false, && will that value.
For example,
use feature qw( say );
sub f1 { say "1"; 1 }
sub f2 { say "2"; 0 }
sub f3 { say "3"; 0 }
sub f4 { say "4"; 0 }
1 if f1() && f2() && f3() && f4();
Output:
1
2
So the following two lines are basically the same:
if (/abc/) { if (!/def/) { ... } }
if (/abc/ && !/def/) { ... }
In fact, if compiles into an and operator, so the above are very close to
(/abc/ and !/def/) and do { ... };
(/abc/ && !/def/) and do { ... };
No.
Think of it like this, if I said
"is the moon bigger than the sun?"
AND "is the pacific bigger than the mediterraan?"
AND "is russia bigger than england?"
AND ... many more AND ....
You could answer "no" very quickly, not having to figure out the answer to anything beyond the first question. It's called "short circuiting"
So in your case, unless an input line matches
/abc/ && !/def/ && !/ghi/
You won't need to evaluate whether it matches /jkl/.