$output = $data | Where-Object {$_.Name -eq "$serverName"} | Select-Object -Property Description1,Version | Where-Object {$_.Description1 -eq "Power controller Firmware"} | Select-Object -Property Version
Write-Host $output
Gives me the following output:
#{Version=3.4}
So $data is an array and I select what I want form it and assign it to a variable to eventually be inputted into a excel file but no matter what I seem to try I cant just select "3.4" Instead it selects like the above (#{Version=3.4}). Doesn't anybody know how to just select the "3.4" within my command?
Just replace last line with:
foreach( $out in $output )
{
Write-Host $out.Version
}
In fact your $output variable contains an array so you need to go through it with a foreach loop.
Then you can Write-Host or do anything with the Version property.
As stated by #okaram, if you want to make the same kind of looping but after a pipe you can do it this way:
$output | ForEach-Object {Write-Host $_.Version}
or
$output | %{Write-Host $_.Version}
Your last expression of
Select-Object -Property Version
Keeps the entire object in the pipeline, but filters down the properties to only Version. However, the -ExpandProperty will put the property value itself in the pipeline.
Select-Object -ExpandProperty Version
That should return the "3.4" result you expect.
Please try the following code:
$data | Where-Object {$_.Name -eq "$serverName"} | Select-Object -Property
Description1, Version | Where-Object {$_.Description1 -eq "Power controller
Firmware"} | write-Host $_.Version
Related
Really pulling my hair out on this one. I'm a bit of a beginner so apologies in advance.
I'm having trouble using the Where-Object cmdlet to basically remove external contacts from a Get-Group query in Exchange Online.
group#domain.com contains 4 members - InternalUser1, InternalUser2, ExternalUser1, ExternalUser2
This is what I have so far, and I've tried numerous different comparators (-notmatch, -notlike, -ne etc.) to no avail:
Input
$x = Get-Contact | Select-Object -ExpandProperty Identity
$y = Get-Group -Identity "group#domain.com" | Select-Object -ExpandProperty Members | Where-Object {$_ -notcontains $x}
Outputs
$x
ExternalUser1
ExternalUser2
$y
ExternalUser1
ExternalUser2
InternalUser1
InternalUser2
Desired Output
$y
InternalUser1
InternalUser2
Excluding the Where-Object part, the outputs are correct so the issue must lie with my use of the Where-Object cmdlet. Any help with this would be greatly appreciated!
Assuming your expanded variables contains a list of string, the following worked.
$y | Where-object {$_ -notin $x}
Applied to your example
$x = Get-Contact | Select-Object -ExpandProperty Identity
$y = Get-Group -Identity "group#domain.com" | Select-Object -ExpandProperty Members | Where-Object {$_ -notin $x}
Complete reproducible standalone example .
$x = #(
'ExternalUser1',
'ExternalUser2'
)
$y = #(
'ExternalUser1',
'ExternalUser2',
'InternalUser1',
'InternalUser2'
)
$y | Where-object {$_ -notin $x}
If this does not work, do a :
$x[0].GetType()
$Y[0].GetType()
If either Member or Identity is a complex object rather than a string, you might need to get the actual string value out of there before using the -notin
I have an empty array that's storing all my windows services that start with certain strings such as OPS-AmazonServer,not included in the code I provided is where I parse the service to just say it's application name.
I then have a CSV file with a list of service names labeled under 'Application Name'. It looks like this
ApplicationName,Instance,Priority
AuthBridge,,1
AmazonServer,,1
AmexEC,,1
What I want to do is compare the service stored in the array to the CSV list but I can't seem to figure out how the logic flows.
$services = get-service Centinel* -ComputerName $serverName | select -expand name
$centinelServices = #()
$services = get-service OPS* -ComputerName $serverName | select -expand name
$opsServices = #()
$services = #()
foreach($service in $centinelServices) {
$services += $service
}
foreach($service in $opsServices) {
$services += $service
}
$csvLocation = "\\logserver\Cardinal\OPS\QA\Task\conf\Centinel\app-restart.csv"
$masterList = import-csv $csvLocation
$applications = #()
$masterList | ForEach-Object {$applications += $_.ApplicationName}
forEach($service in $services){
forEach($application in $applications){
if($service -eq $application){
"$service match found"
}
else {
"$service match not found"
}
}
Ok, easiest way to do this is to use Compare-Object, and a little magic with Select.
I'm going to assume that the ApplicationName column in your CSV is a list of strings that match up with the Name property in your Windows Services list. So let's start by importing that CSV, and changing the property name of ApplicationName to just Name, so that it matches the related property on your Windows Service objects.
$masterList = Import-Csv $csvLocation | Select #{l='Name';e={$_.ApplicationName}}
Then we simply use Compare-Object to see what's in both lists:
Compare-Object (Get-Service) -DifferenceObject $masterList -Property Name -IncludeEqual
If you wanted to parse that you can always pipe it to a Where clause, or use combinations of -IncludeEqual and -ExcludeDifferent parameters:
$masterList = Import-Csv $csvLocation | Select #{l='Name';e={$_.ApplicationName}}
$myServices = Get-Service
$foundServices = Compare-Object $myServices -DifferenceObject $masterList -Property Name -IncludeEqual -ExcludeDifferent
$servicesNotInMaster = Compare-Object $myServices -DifferenceObject $masterList -Property Name | Where {$_.SideIndicator -eq '<='}
$servicesNotFoundLocally = Compare-Object $myServices -DifferenceObject $masterList -Property Name | Where {$_.SideIndicator -eq '=>'}
Or using the Switch cmdlet to do it all in one go:
$masterList = Import-Csv $csvLocation | Select #{l='Name';e={$_.ApplicationName}}
$myServices = Get-Service
Switch(Compare-Object $myServices -dif $masterList -prop Name -includeequal -PassThru){
{$_.SideIndicator -eq '<='} {[array]$servicesNotInMaster += $_}
{$_.SideIndicator -eq '=>'} {[array]$servicesNotFoundLocally += $_}
{$_.SideIndicator -eq '=='} {[array]$foundServices += $_}
}
Edit: Ok, updating from your addition to the OP. Looks like you could be well served by simply using a Where clause rather than getting services over and over.
$services = Get-Service -ComputerName $serverName | Where{$_.Name -like 'ops*' -or $_.Name -like 'Centinel*'} | Select -Expand Name
Then you import your CSV, and use Select -Expand again to get the value of the property, rather than looping through it like you were before.
$masterList = Import-Csv $csvLocation | Select -Expand ApplicationName
Now you just have two arrays of strings, so this actually gets even simpler than comparing objects... You can use the -in operator in a Where statement like this:
$services | Where{$_ -in $masterList} | ForEach{"$_ match found"}
That basically filters the $services array to look for any strings that are in the $masterList array. This will only work for exact matches though! So if the service is listed as 'OPS-AmazonServer', but in your CSV file it is listed at just 'AmazonServer' it will not work! I use that example specifically because you have that in your example in your question. You specifically call out the service named 'OPS-AmazonServer' and then in your CSV sample you list just 'AmazonServer'.
If the listings in the CSV are partial strings that you want to match against you could use RegEx to do it. This will probably make less sense if you aren't familiar with RegEx, but this would work:
$services = Get-Service -ComputerName $serverName | Where{$_.Name -like 'ops*' -or $_.Name -like 'Centinel*'} | Select -Expand Name
$masterList = (Import-Csv $csvLocation | ForEach{[regex]::escape($_.ApplicationName)}) -join '|'
$services | Where{ $_ -match $masterList } | ForEach{"$_ match found"}
I am still new to powershell. I have been trying to get only the Nic properties that have been set to false.
So when I run:
Get-NetAdapter | fl * it brings up all the results for each property of the Nic. I only want to see the properties that have been set to false.
I have tried Get-NetAdapter | where {$_ -like $false} and Get-NetAdapter | where {$_ -like "*false*"}. Have also tried sorting but also cant get working
Much Appreciated
(Get-NetAdapter).PSObject.Properties | Where-Object Value -eq $false | Select-Object Name
If you want the results as string array instead of an object array, use Select-Object -ExpandProperty Name
Note: This only works as intended if you have a single NetAdapter. The code in the comment from PetSerAl will give you all properties from all adapters, but you don't see from which adapter.
If you want to test multiple adapters, you should write an additional loop for example like this
$adapters = Get-NetAdapter
foreach ($adapter in $adapters)
{
Write-Host -ForegroundColor Green "$($adapter.Name)"
$adapter.PSObject.Properties | Where-Object Value -eq $false | Select-Object -ExpandProperty Name
Write-Host ""
}
I'm running this powershell command from a perl script and parsing the output.
powershell "Get-WinEvent -EA SilentlyContinue -FilterHashtable #{Logname='System';ID=7001,10,12,13,41,42,1129,5060,5719,6008,7045}| SELECT-Object ID,TimeCreated,MACHINENAME,MESSAGE|ConvertTo-Csv -NoTypeInformation | %{ $_ -replace """`r`n""",',' } | select -Skip 1"
Is there a way to change the format of the TimeGenerated field in the oputput to 2014-08-5 16:09:54 from 8/5/2014 4:09:54 PM
You can create values from hashtables at the Select portion of the pipe. This should do what you want:
powershell "Get-WinEvent -EA SilentlyContinue -FilterHashtable #{Logname='System';ID=7001,10,12,13,41,42,1129,5060,5719,6008,7045}| SELECT-Object ID,#{label='TimeCreated';expression={$_.TimeCreated.ToString("yyyy-M-d HH:mm:ss")}},MACHINENAME,MESSAGE|ConvertTo-Csv -NoTypeInformation | %{ $_ -replace """`r`n""",',' } | select -Skip 1"
I replaced TimeCreated with #{label=TimeCreated;expression={$_.TimeCreated.ToString("yyyy-M-d HH:mm:ss")}}. Let me break that down for you.
label=TimeCreated is what the property name will be going further down the pipe. I simply reused the same name.
expression={ScriptBlock} tells the system what the value for that property will be for each record.
As for the actual scriptblock, in this case we were already working with a [DateTime] object so I used its ToString() method, and specified a format of your design to output it as. That changes it, so it is now a [String] instead of a [DateTime] object, but seeing as you are just converting the whole thing to a CSV a string should do just fine.
Edit: You can add a switch into the scriptblock of the hashtable described above, it just gets long and can be hard to follow. I would do something like:
powershell "Get-WinEvent -EA SilentlyContinue -FilterHashtable #{Logname='System';ID=7001,10,12,13,41,42,1129,5060,5719,6008,7045}| SELECT-Object ID,#{l='ID Description';e={Switch($_.ID){
"7001" {"Text1"}
"10" {"Text2"}
"12" {"Text3"}
"13" {"Text4"}
"41" {"Text5"}
"42" {"Text6"}
"1129" {"Text7"}
"5060" {"Text8"}
"5719" {"Text9"}
"6008" {"Text10"}
"7045" {"Text11"}
}
}},#{label='TimeCreated';expression={$_.TimeCreated.ToString("yyyy-M-d HH:mm:ss")}},MACHINENAME,MESSAGE|ConvertTo-Csv -NoTypeInformation | %{ $_ -replace """`r`n""",',' } | select -Skip 1"
l= is short for label= and e= is short for expression=
Edit2: More switch info... You could do things based on multiple fields, you would want to do Switch($_) and then on each line put your conditions in a scriptblock, so something like:
Switch($_){
{$_.ID -eq "7001" -and $_.Message -match "catastrophic"}{"The dog ate my NetBIOS"}
{$_.ID -eq "7001" -and $_.Message -match "Lex Luthor"}{"Superman stole my WiFi"}
{<more conditions>}{<and their resultant values>}
}
You can specify an expression in the Select-Object command to create a calculated property. Here, I called this new property "Time" and used the ToString() method with the InvariantCulture to make sure the output is consistent on different computers.
Get-WinEvent -EA SilentlyContinue -FilterHashtable #{Logname='System';ID=7001,10,12,13,41,42,1129,5060,5719,6008,7045} | `
SELECT-Object -Property ID,#{Name="Time"; Expression = {$_.TimeCreated.Tostring("yyyy-MM-d HH:mm:ss", [CultureInfo]::InvariantCulture)}},MACHINENAME,MESSAGE | `
ConvertTo-Csv -NoTypeInformation | %{ $_ -replace """`r`n""",',' } | select -first 5
So I have the following code to output all features and roles installed:
Import-Module ServerManager
$Arr = Get-WindowsFeature | Where-Object {$_.Installed -match “True”} | Select-Object -Property Name
$loopCount = $Arr.Count
For($i=0; $i -le $loopCount; $i++) {
Write-Host $Arr[$i]
}
However, the output is:
#{Name=Backup-Features}
#{Name=Backup}
#{Name=Backup-Tools}
How can I get rid of the # and {}'s ?
Use Select -ExpandProperty Name instead of Select -Property Name
Alternatively and also, I recommend using Foreach-Object instead of a C-style for loop.
Import-Module ServerManager
Get-WindowsFeature |
Where-Object {$_.Installed -match “True”} |
Select-Object -ExpandProperty Name |
Write-Host
Or
Import-Module ServerManager
Get-WindowsFeature |
Where-Object {$_.Installed -match “True”} |
ForEach-Object {
$_.Name | Write-Host
}
How about a nice one liner?
Get-WindowsFeature | ? {$_.Installed -match “True”} | Select -exp Name
If you can accept a totally static solution, this should work:
Write-Host $Arr[$i].Substring(2, $Arr[$i].Length-3)
If you're looking for a solution that looks specifically for those symbols and removes them, it would be a little different. Based on your question though, this should be just fine.