Access PSObject Properties Values - powershell

I have a PSObject that looks like this:
IsGettable : True
Value : {#{friority=Medium;removedDate=;etc..}
What I want to do is extract the friority that are medium and get a count of them.
I've tried a couple of different things using select-object and get-member with no luck.
Thanks in advance!
Update:
So, as suggested I converted the object into a JSON object and wrote it to the file.
{
"data": [
{
"id": 487777,
"proVersion": null,
"proName": null,
"revision": 0,
"folderId": 4555,
"friority": "Medium"}],
"count": 567,
"responseCode": 200
}
To save space I have removed some of the values of the object.
I have since changed the suggested solution to below:
($projIssues | Where-Object { $_.data.friority -eq "Medium" })
Now, If I add .count I am receiving the count value of the object
567

First off, Thanks to Santiago and mklement0 for the help.
I ended up using this statement:
$issues = $projIssues.data.friority | WHERE { $_ -eq "Medium"}
then checking the count like so:
$issues.count

Related

Using Powershell Dictionary

I struggle with very basic powershell scripting.
I have an object "ids" (I cant tell exactly what type it is) that translates to json like this
[{"id": "3ccbfe7a-e381-ed11-81ad-000d3aba6139","RowKey": "204640","PartitionKey": "ppm"},
{"id": "7339255d-e381-ed11-81ad-000d3aba6139","RowKey": "205269","PartitionKey": "ppm"}]
I simply want to get the "ids" by "rowkey". e.g.
$ids["204640"] shall resolve to "3ccbfe7a-e381-ed11-81ad-000d3aba6139".
It is obvious that this should be very easy - but I fail ... My understanding is, that it is a list or array of objects with named properties. I assume some simple casting magic is necessary...
(my debugging skills are very limited because I am a Powershell newbie and I do the scripting in the azure portal, trying to write an Azure Function using a table binding. actually "ids" comes from that binding.)
It is unclear if your Json string has already been converted into objects or not, for that you can use ConvertFrom-Json. Then you can use Group-Object -AsHashtable grouping on RowKey property:
$string = '
[
{"id": "3ccbfe7a-e381-ed11-81ad-000d3aba6139","RowKey": "204640","PartitionKey": "ppm"},
{"id": "7339255d-e381-ed11-81ad-000d3aba6139","RowKey": "205269","PartitionKey": "ppm"}
]
'
$hash = (ConvertFrom-Json $string) | Group-Object RowKey -AsHashTable
$hash['205269'].id # => 7339255d-e381-ed11-81ad-000d3aba6139

Escape charaters in JSON causing issue while retrieving attribute in ForEach activity

I have below JSON
{
"id": " https://xxx.vault.azure.net/secrets/xxx ",
"attributes": {
"enabled": true,
"nbf": 1632075242,
"created": 1632075247,
"updated": 1632075247,
"recoveryLevel": "Recoverable+Purgeable"
},
"tags": {}
}
The above JSON is the output of a web activity and I am using this output into a ForEach activity. The above output when goes to ForEach activity as input, all the values are coming with escape characters.
{
{"id":" https://xxx.vault.azure.net/secrets/xxx ","attributes":{"enabled":true,"nbf":1632075242,"created":1632075247,"updated":1632075247,"recoveryLevel":"Recoverable+Purgeable"},"tags":{}}
From this JSON, I am trying to get only xxx value from the id attribute. How can I do this in Dynamic expression.
Any help is much appreciated.
Thanks
Use the built-in functions lastIndexOf (to find the last occurence of backslash), length (to determine the length of a string), add (to add numbers), sub (to subtract numbers) and substring to do this. For example:
#substring(item().id,add(lastIndexOf(item().id,'/'),1),sub(length(item().id),add(lastIndexOf(item().id,'/'),1)))

Excluding or selectively including subproperties when serializing a complex class in powershell

I'm looking for an efficient way to selectively serialize certain subproperties of a complex class.
For example, below is the output of the specified command
Get-Date | Select -Property Ticks, TimeOfDay | ConvertTo-Json
{
"Ticks": 637590063235806354,
"TimeOfDay": {
"Ticks": 399235806354,
"Days": 0,
"Hours": 11,
"Milliseconds": 580,
"Minutes": 5,
"Seconds": 23,
"TotalDays": 0.46207847957638887,
"TotalHours": 11.089883509833333,
"TotalMilliseconds": 39923580.635400005,
"TotalMinutes": 665.39301059,
"TotalSeconds": 39923.5806354
}
}
I want my serialized class to look like this:
{
"Ticks": 637590063235806354,
"TimeOfDay": {
"TotalMinutes": 665.39301059,
"TotalSeconds": 39923.5806354
}
}
Rebuilding the class with the required properties is not the desired solution as for the real usecase, the class is more complex and contains many more levels.
The following does not work, but might give a better sense for what I'm looking for.
Get-Date | Select -Property Ticks, TimeOfDay.TotalMinutes,
TimeOfDay.TotalSeconds | ConvertTo-Json
You can do this kind of thing:
Get-Date | Select-Object Ticks, #{N="TimeofDay";e={[pscustomobject]#{TotalMinutes=$_.TimeOfDay.TotalMinutes;TotalSeconds=$_.TimeofDay.TotalSeconds}}} | ConvertTo-Json

Powershell singleton array

I need to create a singleton complex array. Background: I am trying to automate Let's Encrypt DNS challenge with GoDaddy. But the question is just about PS objects.
Suppose I have the following JSON object, which is my target notation
[
{
"data": "string",
"port": 0,
"priority": 0,
"protocol": "string",
"service": "string",
"ttl": 0,
"weight": 0
}
]
I try to initialize the variable via Powershell as follows
$goDaddyDnsBody=#(
#{
"data"= $dnsChallenge;
"port"= 1;
"priority"= 0;
"ttl"= 600;
"weight"= 0
}
)
The above code is supposed to create an array containing only one item
But when I try to Write-Host ($goDaddyDnsBody |ConvertTo-Json) I get only the first element, not the whole array
{
"weight": 0,
"priority": 0,
"data": ".................",
"ttl": 600,
"port": 1
}
The question is obvious: how can I make sure, without necessarily using string manipulation, that the object created is an array?
Great work with the self answer!
I wanted to point out two things:
the -AsArray parameter to ConvertTo-Json was not always available. It's in the current supported versions of PowerShell that are cross-platform. However, it is not available in Windows PowerShell (versions 5.1 and earlier) which many are still using.
The original issue stems from using the pipeline with an array that contains a single object. Because the pipeline is "unrolling" the array and passing each object into the cmdlet, with a single object array the cmdlet only ever sees the single object. For more on that, see mklement0's excellent and detailed explanation in another answer.
You can instead produce an array by passing the array directly to the parameter:
ConvertTo-Json -InputObject #(#{a=1})
Result:
[
{
"a": 1
}
]
Also worth noting that with the newer -AsArray option you don't need the wrapping array at all, in either the direct parameter or pipeline invocations:
ConvertTo-Json -InputObject #{a=1} -AsArray
#{a=1}|ConvertTo-Json -AsArray
I found the solution myself.
The problem is in with the serialization, not with the initialization of the singleton array. I just needed to add the following -AsArray switch
Write-Host ($goDaddyDnsBody |ConvertTo-Json -AsArray)
Sharing for posterity

check if an string exists in a list of strings, using powershell

I have Powershell version 3,4 and 5 in my environment. When I write below code it continously gave me false, though $CompatiableOS contains output of $OSverions.
[string] $CompatiableOS = '2016','2012','2008'
$OSVersion=[regex]::Matches(((Get-WmiObject -class Win32_OperatingSystem).caption), "([0-9]{4})")
if ( $CompatiableOS -contains $OSVersion)
{
return $TRUE
}
else
{
return $FALSE
}
but when I changed above code to below, it worked. What could be the issue?
[string] $CompatiableOS = '2016','2012','2008'
$OSVersion=[regex]::Matches(((Get-WmiObject -class Win32_OperatingSystem).caption), "([0-9]{4})")
if ( $CompatiableOS.contains($OSVersion))
{
return $TRUE
}
else
{
return $FALSE
}
This comes up a lot. -contains vs .contains(). They're very different. -contains has to match exactly. But the left side can be an array of strings. You actually joined everything into one string on the left with the [string] cast.
$compatibleos
'2016 2012 2008'
'2016 2012 2008' -contains '2016'
False
'2016 2012 2008'.contains('2016')
True
'2016','2012','2008' -contains '2016'
True
('2016','2012','2008').contains('2016')
True
From the MS documentation
-Contains
Description: Containment operator. Tells whether a collection of reference
values includes a single test value. Always returns a Boolean value. Returns TRUE
only when the test value exactly matches at least one of the reference values.
The important part is here is "only when the test value exactly matches". In your case you try to compare the string "2016 2012 2008" with as an example 2016, this doese't match exactly. In this case you should use the -like operator. Or you define your compatibleOS variable as an string array like that [String[]], then you can use the -contains.
Additonal, check whats inside the OSVersion variable. It is a machtcollection not a string. If you define your compatibleOS variable as a string array and you use $OSVersion.Value both of your examples will work.
Although the $CompatiableOS contains output of $OSverions, however the -contains is only used against a single test value, and return true when the test value exactly matches at least one of the reference values.
However When the test value is a collection, the Contains operator uses reference equality. It returns TRUE only when one of the reference values is the same instance of the test value object. What is of importance is that they have to be of the same instance in this case.
For eg:
PS> "abc", "def", "ghi" -contains "abc", "def"
->False
PS> $a = "abc", "def"
PS> "abc", "def", "ghi" -contains $a
->False
PS> $a, "ghi" -contains $a
->True
Note, how the last one returns true due to the same instance, and the rest were false. Thus while using -contains, you received False.
However when you use the contains(..) format, it does not check for the same instance and thus returned True, in your case.
for me below syntax worked
ForEach ($content in $logFileContent) {
if( $content.contains("MainClass")){
echo "MainClass: $content" >> $log
}
}