Compare Patch Levels across Multiple servers - arrays

Hi all I was working on a script to compare a list of patch levels between multiple servers and show the list of patches missing on either of server. The script should compare between each server within the array and give the output i was trying using Get-Hotfix and also using compare-object to compare and get the server name evaluating $_.sideindicator -match "=>" and $_.sideindicator -match "<=".
can anyone please help further?
here's the code till now for four servers, if there are n number of servers i wanted the logic on how to proceed.
$array=#()
$serd1 = Get-HotFix -ComputerName serd1 | select -ExpandProperty hotfixid
$serd2 = Get-HotFix -ComputerName serd2 | select -ExpandProperty hotfixid
$serd3 = Get-HotFix -ComputerName serd3 | select -ExpandProperty hotfixid
$serd4 = Get-HotFix -ComputerName serd4 | select -ExpandProperty hotfixid
$check1 = Compare-Object -ReferenceObject $serd1 -DifferenceObject $serd2 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check1 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd1"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check1 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd2"}},#{l="MissingPatches";e={$_.inputobject}}
$check2 = Compare-Object -ReferenceObject $serd1 -DifferenceObject $serd3 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check2 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd1"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check2 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd3"}},#{l="MissingPatches";e={$_.inputobject}}
$check3 = Compare-Object -ReferenceObject $serd1 -DifferenceObject $serd4 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check3 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd1"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check3 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd4"}},#{l="MissingPatches";e={$_.inputobject}}
$check4 = Compare-Object -ReferenceObject $serd2 -DifferenceObject $serd3 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check4 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd2"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check4 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd3"}},#{l="MissingPatches";e={$_.inputobject}}
$check5 = Compare-Object -ReferenceObject $serd2 -DifferenceObject $serd4 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check5 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd2"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check5 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd4"}},#{l="MissingPatches";e={$_.inputobject}}
$check6 = Compare-Object -ReferenceObject $serd3 -DifferenceObject $serd4 -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$array += $check6 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd3"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check6 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd4"}},#{l="MissingPatches";e={$_.inputobject}}
$array
The question is how to make this script work for random number of servers

This question is old but thought this might help out if anyone else finds this and thinks it is something they'd want to give a go.
Anyway, to meet the requirements stated here, see if this helps - let me know if anyone finds problems:
$Servers = "SERVER1", "SERVER2", "SERVER3", "SERVER4"
$MissingPatches=#()
$ServerPatches = New-Object 'object[]' $($Servers.Length)
for($i=0; $i -lt $($Servers.Length); $i++)
{
$ServerPatches[$i] = Get-HotFix -ComputerName $Servers[$i] | select -ExpandProperty hotfixid
}
for($i=0; $i -lt $($Servers.Length); $i++)
{
for($j=($i+1); $j -lt $($Servers.Length); $j++)
{
$Compare = Compare-Object -ReferenceObject $ServerPatches[$i] -DifferenceObject $ServerPatches[$j] -IncludeEqual | ?{$_.sideindicator -notmatch '=='}
$MissingPatches += $Compare | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={$Servers[$i]}},#{l="MissingPatches";e={$_.inputobject}}
$MissingPatches += $Compare | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={$Servers[$j]}},#{l="MissingPatches";e={$_.inputobject}}
}
}
$MissingPatches = foreach($MissingPatch in $MissingPatches) {
if($($MissingPatch.MissingPatches) -ne "File 1")
{
$MissingPatch
}
}
$MissingPatches | ft -AutoSize
Going down this path I started thinking of potential improvements. So, if I have time I might rewrite and create a patch object that indicates on what server it is present and where it is missing for more detail of why a patch is indicated as "Missing".
When a patch is found on any server it is added to that array. A property of PresentOn will be updated with the server name it was found and the servers so far that didn't contain the patch can be added to a property of MissingOn, then checked continuously going forward. Then, a table of all patches can be displayed by these statuses vs. printing out only a "Missing" array. Could take some doing but might be worth the work. I'm also seeing this being a potentially costly script based on the number of patches in play and servers. But, if anyone else gets to it first (or finds flaws in the approach) let me know here!

This should work:
$servers = "one", "two", "three"
$array = #()
for ($i = 0; $i -lt ($servers.Count - 1); $i++)
{
$serd1 = Get-HotFix -ComputerName $servers[$i] | select -ExpandProperty hotfixid
$serd2 = Get-HotFix -ComputerName $servers[$i+1] | select -ExpandProperty hotfixid
$array += $check1 | ?{$_.sideindicator -match "=>"} | Select-Object #{l="HostName";e={"serd1"}},#{l="MissingPatches";e={$_.inputobject}}
$array += $check1 | ?{$_.sideindicator -match "<="} | Select-Object #{l="HostName";e={"serd2"}},#{l="MissingPatches";e={$_.inputobject}}
}
$array

Related

Array causing 'system.outofmemoryexception'

I am running the below script and it is causing exception of type 'system.outofmemoryexception' was thrown
I believe that it is due to the #Results array growing past the 2gb allocated to windows shell. Is there possibly a way to iterate through the results, or am I stuck with allocating more memory (which could ultimately be a lot...)?
$Path = "path to output"
### Get all PF
$publicFolders = Get-PublicFolder "Public Folder Name" -Recurse -resultsize unlimited | Select-Object *
### Array to contain results
$results = #()
###Begin looping through each PF and grab each user/group with AccessRights to that folder
$final = ForEach($pf in $publicFolders){
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
Foreach($perm in $perms){
$temp = [PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
$results += $temp
}
}
$final | Export-Csv $path -NoTypeInformation
Am I barking up the wrong tree?
Thanks in advance.
Use the ForEach-Object cmdlet instead of a foreach(){} loop statement for the outer loop - this way you can start piping the output to Export-Csv immediately instead of buffering it in an array:
$publicFolders |ForEach-Object {
$pf = $_
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
Foreach($perm in $perms){
[PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
}
} | Export-Csv $path -NoTypeInformation
Alternatively, flush the partial set of results to file after enumerating the permissions for each folder:
ForEach($pf in $publicFolders){
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
$results = Foreach($perm in $perms){
[PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
}
# flush the buffer before moving to the next set of permissions
$results |Export-Csv $path -NoTypeInformation -Append
}

Parsing an array of ojects into strings in PowerShell

I am calling Get-AdComputer like this:
[string[]] $computer = Get-ADComputer -properties * -filter {(operatingsystem -like "*Windows 7*")} |
Where-Object {$_.name -like "*-*"} |
Where-Object {$_.name -NotLike "V7-*"} |
Where-Object {$_.name -NotLike "*-NONE"} |
Where-Object {$_.name -NotLike "*-ONCALL"} |
Where-Object {$_.name -NotLike "*-BLACKBAUD"} |
Where-Object {$_.name -NotLike "SC-WIN7-1"} |
Where-Object {$_.name -NotLike "UT-SWCLIENT-01"} |
Select-Object Name, LastLogonDate
This creates a string array and I can access it like this:
$computer[1]
which returns
#{Name=W7-9HQPR3J; LastLogonDate=05/08/2017 09:45:13}
I need to output the data to a csv file in two columns Name, LastLogonDate
Unfortunately when I call $Computer | out-file -filepath $ServiceTagsPath -Force -Width 200 -Encoding ascii
I get one column with the headings on each line:
My other requirement is to be able to use the Name column in web-service calls to get warranty information...
so how could I do that?
I would not cast the output to array of strings [string[]] but leave the casting to powershell.
Then you can use command Export-Csv which works better with array of objects.
$computer = Get-ADComputer -properties * -filter {(operatingsystem -like "*Windows 7*")} |
Where-Object {$_.name -like "*-*"} |
Where-Object {$_.name -NotLike "V7-*"} |
Where-Object {$_.name -NotLike "*-NONE"} |
Where-Object {$_.name -NotLike "*-ONCALL"} |
Where-Object {$_.name -NotLike "*-BLACKBAUD"} |
Where-Object {$_.name -NotLike "SC-WIN7-1"} |
Where-Object {$_.name -NotLike "UT-SWCLIENT-01"} |
Select-Object Name, LastLogonDate
$computer | Export-Csv "test.csv" -NoTypeInformation

Find items which are in array1 but NOT in array2

I extracted two lists of computers from two different tools, Array1 and Array2.
Now I need to extract the ones which are in Array1, but not in Array2.
I managed to get all the matching ones by doing this:
$matchingComp = #()
foreach ($SCCMcomputer in $SCCMcomputers) {
foreach ($eWPTcomputer in $eWPTcomputers) {
if ($SCCMcomputer.Computername -eq $eWPTComputer.Computername) {
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $SCCMcomputer.Computername
$matchingComp +=$obj
}
}
}
$matchingComp | Export-Csv $inEWPT -Delimiter "," -NoTypeInformation
But I still need the ones that are in $SCCMcomputer but NOT in $eWPTcomputers...
I've found some solutions on SO with other languages (e.g. Perl) but not for PowerShell.
UPDATE
I still don't get the correct output, in Excel with this formula:
the output looks like:
means some are here, some not. The output in powershell is like this
means 0KB is emtpy.
$SCCMcomputers | Export-Csv $sccmexport -Delimiter "," -NoTypeInformation
$eWPTcomputers | Export-Csv $ewptexport -Delimiter "," -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=>"} |select inputobject | Export-Csv $inEWPT -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=="} |select inputobject | Export-Csv $inBoth -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "<="} |select inputobject | Export-Csv $inSCCM -NoTypeInformation
And both Column Name (or what it's called) from SCCMcomptuers/eWPTcomputers is "Computername"
Any idea what I could be doing wrong? Both computer arrays are generated from SQL and in hashtables (I think it's called): #{Computername=......}#{Computername...., something like this.
Update 2
foreach ($t in $sccmComputers) {
$Test1 += $t.computername
}
$Test2 = #()
foreach ($t in $ewptComputers) {
$Test2 += $t.computername
}
By removing the Header of the Hashtable and just having arrays full of strings works fantasctic..... even -Property computername did not work... :S
use compare-object cmdlet
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt | ?{$_.sideIndicator -eq "<="} |select inputobject
example :
$sccm=#(1,2,3)
$wpt=#(2,4)
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -IncludeEqual
will output :
InputObject SideIndicator
2 ==
4 =>
1 <=
3 <=
that means value "2" is on both objects, "1" and "3" only on "the left side" (ie the reference object), while "4" is only on the difference object
Use compare-object as follows
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -passthru
This should give you just the objects in $sccm but not in $wpt.
CORRECTION:
The above code WILL work for the case where DifferenceObject is guaranteed to be a subset of ReferenceObject. It will FAIL, though, if there are additional objects in DifferenceObject that are not also present in ReferenceObject. The above code returns any objects which are present in EITHER ReferenceObject OR DifferenceObject but NOT in both.
To properly return ONLY objects in ReferenceObject that are not also present in DifferenceObject, the following code is required:
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { Write-Output $_.InputObject }
The where-object clause ensures only objects that are present in ReferenceObject are passed down the pipeline.
The foreach-object clause forces the output back to a simple array (ref: Converting Custom Object arrays to String arrays in Powershell - thanks Keith)
You can use -contains and -notcontains
$A1 ="asd","zxc","qwe",'a'
$A2 = "asd","zxc","bqwe",'b'
$A1,$A2 |
%{
$_|
%{
If ($A1 -contains $_ -and $A2 -notcontains $_) {$_}
}
}
The Compare-Object method is indeed the best. What hasn't been addressed yet is clean output to your Excel file.
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Export-Csv sccm-only.csv -NoTypeInformation
will produce two columns. One with "InputObject" and your computer names, and another column with "SideIndicator" and a bunch of rows with "<=".
The easy fix is to select only the column you want:
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object InputObject | Export-Csv sccm-only.csv -NoTypeInformation
This will give you a single column labeled "InputObject" and your computer names.
If you want to change the column label, use the method from another thread, Windows Powershell Rename Column Heading CSV file:
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object #{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation
Also, simply change the SideIndicator comparison to get those computers in both systems, or only in eWPT:
# Only in eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '=>' | Select-Object #{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation
# In both SCCM and eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '==' | Select-Object #{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation
$sccm=#(1,2,2,3)
$wpt=#(2,4)
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { Write-Output $_.InputObject }
This will return 1,2,3, this method is not correct

Use Powershell to insert data into multiple columns in SQL Server

I'm trying to insert data collected from VMware vCenter into a database using Powershell and SQL Server.
This is what I have for now:
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=.\sqlexpress;Initial Catalog=Computer;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn
$val = 0
$clusterinf = foreach($cluster in Get-Cluster){
$esx = $cluster | Get-VMHost
$ds = Get-Datastore -VMHost $esx | where {$_.Type -eq "VMFS"}
$cluster | Select #{N="VCname";E={$cluster.Uid.Split(':#')[1]}},
#{N="DCname";E={(Get-Datacenter -Cluster $cluster).Name}},
#{N="Clustername";E={$cluster.Name}},
#{N="TotalPhysicalMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryTotalMB -Sum).Sum /1KB)}},
#{N="TotalUsedMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryUsageMB -Sum).Sum /1KB)}},
#{N="AvailableMemroy";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.MemoryTotalMB - $_.MemoryUsageMB} -Sum).Sum /1KB)}},
#{N="TotalCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum /1KB)}},
#{N="TotalUsedCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum /1KB)}},
#{N="AvailableCPU";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.CpuTotalMhz - $_.CpuUsageMhz} -Sum).Sum /1KB)}},
#{N="TotalDiskSpace";E={[Math]::Round(($ds | where {$_.Type -eq "VMFS"} | Measure-Object -Property CapacityMB -Sum).Sum /1KB)}},
#{N="ConfiguredDiskSpace";E={[Math]::Round(($ds | Measure-Object -InputObject {$_.CapacityMB - $_.FreeSpaceMB} -Sum).Sum /1KB)}},
#{N="AvailableDiskSpace";E={[Math]::Round(($ds | Measure-Object -Property FreeSpaceMB -Sum).Sum /1KB)}},
#{N="Total Configured Memory GB For Powered on VMs";E={[Math]::Round(($_ | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | %{$_.MemoryMB} | Measure-Object -Sum | Select -ExpandProperty Sum)/1KB) }}
$cmd.commandtext = "INSERT INTO Clusterinfo (VCname) VALUES('{$val}')" -f $clusterinf.VCname
$cmd.ExecuteNonQuery()
$val++
}
$conn.close()
And this is working as intended i believe. Now my question is, how do I continue with the next column? So that I can add DCname, Clustername, TotalPhysicalMemory and so on?
I have been trying with this insert statement:
$cmd.commandtext = "INSERT INTO Clusterinfo (VCname, DCname, CLustername) VALUES('$($clusterinf.VCname)','$($clusterinf.DCname)','$($clusterinf.Clustername)')"
But its not realy giving the wanted result, as it will insert every VCname, DCname and so on, into one row, and not into different rows.
I have been looking at this question: Powershell How to query multiple classes and write in to SQL Table
But I can't seem to get my head around a solution to my own question.
Anybody got an idea on how to solve this?
$clusterinf needs to be the object with the data of the current cluster, not the result of the entire foreach-loop.
I would try something like this:
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=.\sqlexpress;Initial Catalog=Computer;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn
foreach($cluster in (Get-Cluster)){
$esx = $cluster | Get-VMHost
$ds = Get-Datastore -VMHost $esx | where {$_.Type -eq "VMFS"}
$clusterinf = $cluster | Select #{N="VCname";E={$cluster.Uid.Split(':#')[1]}},
#{N="DCname";E={(Get-Datacenter -Cluster $cluster).Name}},
#{N="Clustername";E={$cluster.Name}},
#{N="TotalPhysicalMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryTotalMB -Sum).Sum /1KB)}},
#{N="TotalUsedMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryUsageMB -Sum).Sum /1KB)}},
#{N="AvailableMemroy";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.MemoryTotalMB - $_.MemoryUsageMB} -Sum).Sum /1KB)}},
#{N="TotalCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum /1KB)}},
#{N="TotalUsedCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum /1KB)}},
#{N="AvailableCPU";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.CpuTotalMhz - $_.CpuUsageMhz} -Sum).Sum /1KB)}},
#{N="TotalDiskSpace";E={[Math]::Round(($ds | where {$_.Type -eq "VMFS"} | Measure-Object -Property CapacityMB -Sum).Sum /1KB)}},
#{N="ConfiguredDiskSpace";E={[Math]::Round(($ds | Measure-Object -InputObject {$_.CapacityMB - $_.FreeSpaceMB} -Sum).Sum /1KB)}},
#{N="AvailableDiskSpace";E={[Math]::Round(($ds | Measure-Object -Property FreeSpaceMB -Sum).Sum /1KB)}},
#{N="Total Configured Memory GB For Powered on VMs";E={[Math]::Round(($_ | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | %{$_.MemoryMB} | Measure-Object -Sum | Select -ExpandProperty Sum)/1KB) } }
$cmd.commandtext = "INSERT INTO Clusterinfo (VCname, Clustername, TotalPhysicalMemory, TotalUsedMemory, AvailableMemroy, TotalCPU, TotalUsedCPU, AvailableCPU, TotalDiskSpace, ConfiguredDiskSpace, AvailableDiskSpace) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}')" -f $clusterinf.VCname, $clusterinf.Clustername, $clusterinf.TotalPhysicalMemory, $clusterinf.TotalUsedMemory, $clusterinf.AvailableMemroy, $clusterinf.TotalCPU, $clusterinf.TotalUsedCPU, $clusterinf.AvailableCPU, $clusterinf.TotalDiskSpace, $clusterinf.ConfiguredDiskSpace, $clusterinf.AvailableDiskSpace
$cmd.ExecuteNonQuery()
}
$conn.close()
As a side note, you should replace commandtext with values with parameters. It's less prone to SQL injection and is alot cleaner in my opinon. See this link

Powershell Where-Object inserting array

I'm trying to build a Powershell script that can filter the information from a CSV file. But I'm having problems when using an array as one of parameters.
This command works when I import the CSV file and type it in manually:
$data |
where-object {
(
$_.PackageAffected -eq "BslEqipWebPkg" -or
$_.PackageAffected -eq "BslIDealAdminPkg" -or
$_.PackageAffected -eq "ALL"
) -and (
$_.ENV -eq "PROD" -or $_.ENV -eq "ALL"
)
} |
select-object -property 'major step id','minor step id','PackageAffected',ENV,detail |
format-table -autosize
I am trying to build the $_.PackageAffected line up using an array.
Here is the code so far (that isn't working):
$packageList = "`$_.PackageAffected -eq `"" + $package[0] + "`" -or"
for ($element=1; $element -lt $package.count; $element++) {
$packageList = $packageList + " `$_.PackageAffected -eq `"" + $package[$element] + "`" -or"
}
$packageList = $packageList + " `$_.PackageAffected -eq `"ALL`""
$data |
where-object{($packageList) -and ($_.ENV -eq $environment -or $_.ENV -eq "ALL")} |
select-object -property 'major step id','minor step id','PackageAffected',ENV,detail |
format-table -autosize
$packageList
At the bottom where I've put $packageList it displays onscreen the string I would expect to see, which is:
$_.PackageAffected -eq "pkgName1" -or $_.PackageAffected -eq "pkgName2" -or $_.PackageAffected -eq "ALL"
But when I view the table after it's been run, there are no filters on it for the PackageAffected.
My suspicions are that I've converted the command into a string and when it runs, Powershell doesn't recognise it as a command.
You need to evaluate the expression. This can be done with Invoke-Expression, e.g.
Invoke-Expression $packageList
In the context of your code, this would be:
$data |
where-object{(Invoke-Expression $packageList) -and ($_.ENV -eq $environment -or $_.ENV -eq "ALL")} |
select-object -property 'major step id','minor step id','PackageAffected',ENV,detail |
format-table -autosize

Resources