Need to sort value from web request response - powershell

I need to sort specific value of BuildName: from web request response.
How can I store a particular response in a variable?
Trying with following command
Invoke-WebRequest -Uri https://s3.amazonaws.com/$url/env.js | select-object Content
I am getting the following response. I need to sort the values from there
Response will be like this
window.env = {
// Hardcode environment variables in here but tokenize customer specific ones with #{}#
BuildName: 'AppClient-develop-0716.4'
GRAPH_QL_HOST: 'https://xyz.google.com/graphql'
};
From her need to get value of BuildName:

You can convert the content to individual strings and parse those to get the individual values.
Example
# $Content = (Invoke-WebRequest -Uri https://s3.amazonaws.com/$url/env.js).Content
$Content = #'
window.env = {
// Hardcode environment variables in here but tokenize customer specific ones with #{}#
BuildName: 'AppClient-develop-0716.4'
GRAPH_QL_HOST: 'xyz.google.com/graphql'
};
'#
$Content -split "`r`n" | Select-String "\w+:" | % { ($_ -split ": ")[1]}

Related

How to change a powershell Invoke-RestMethod body from its original format into something else

I have a param section of a Invoke-RestMethod that i have to keep as is, but also add parameters:
$param = #{
...
Body = '{"entry":[{"#name":SOMETEXT,"static":{"member":[ANOTHERTEXT]}}]}'
...
}
Since the entire Body is in single quotes, any $parameter added will be treated like a string instead of a normal PowerShell parameter
In this case SOMETEXT and ANOTHERTEXT will be $HubAddressObject and $ArrayList, respectivly.
How do i make that Body entry work with parameters, and keeping the same structure (this is part of a Panorama box)?
What i would need would be:
Body = '{"entry":[{"#name":$HubAddressObject,"static":{"member":[$ArrayList]}}]}'
Thanks.
I'd recommend using ConvertFrom-Json / ConvertTo-Json for that kind of thing.
To keep it one 1 line, you can use the -Compress switch.
$params = #{
Body = '{"entry":[{"#name":"SOMETEXT","static":{"member":"[ANOTHERTEXT]"}}]}'
}
# Create a PSObject representation of your JSON
$jsonObj = $Params.body | ConvertFrom-Json
#Modify whatever you want
$jsonObj.entry[0].'#name' = 'NewText'
# Convert the Object back to Json.
$Params.Body = $JsonObj | Convertto-Json -Compress -Depth 4
Json comparison
# Starting off Json
{"entry":[{"#name":"SOMETEXT","static":{"member":"[ANOTHERTEXT]"}}]}
# Modified JSON
{"entry":[{"#name":"NewText","static":{"member":"[ANOTHERTEXT]"}}]}

Is the object empty?

I'm using an Azure API > https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull%20request%20query/get?view=azure-devops-rest-5.1
I'm using this code:
$body = #"
{
"queries": [{
"items": [
"59c1c31397b266116ff6d735e5638ef5d1b598a0"
],
"type": "commit"
}]
}
"#
$x = Invoke-RestMethod -Uri $someLink -Headers #{Authorization = $pat } -Body $body -Method Post -ContentType 'application/json'
Write-Host $x
Write-Host $x | ConvertFrom-Json
Write-Host $x.results | ConvertFrom-Json
I've removed the link for security reasons.
When I run the code I get the following in my console:
2020-01-20T16:17:55.8600905Z #{queries=System.Object[]; results=System.Object[]}
2020-01-20T16:17:55.8637026Z #{queries=System.Object[]; results=System.Object[]}
2020-01-20T16:17:55.8674193Z
I'm not sure if the queries and results objects are empty or that I need some other way of reading them.
Write-Host writes to the host (which is typically the console / terminal), bypassing PowerShell's success output stream, which is why a command such as Write-Host $x | ConvertFrom-Json is pointless, because ConvertFrom-Json will receive no input.
Write-Host writes simple .ToString() stringifications of non-string input objects to the host, which means that you don't get PowerShell's rich, human-friendly output formatting that implicit output or - rarely needed - explicit Write-Output calls result in when ultimately printing to the host by default, due to the output neither getting captured in a variable or getting redirected with >).
Invoke-RestMethod automatically parses the JSON output it receives into PowerShell custom objects ([pscustomobject] instances, so there is also also no conceptual reason to pipe its property values to ConvertFrom-Json - unless the API truly returns nested JSON text as string values in the JSON it returns.
If you want to visually inspect the results, simply output them directly:
$x # output visualization of the whole object
$x.results # just the .results property
The above outputs to the success output stream, which means that an outside caller of your code would receive these values as part of the code's output.
If the resulting table- or list-like formatting (depending on the number of properties) doesn't tell you enough, you can convert the objects back to JSON, by piping to ConvertTo-Json.
Note that the latter's default serialization depth is limited to 2, so you may have to pass a higher -Depth value to see the object in full - see this post.
$x | ConvertTo-Json # use -Depth <n>, if needed.
$x.results | ConvertTo-Json
If you really want to just print the values as information for the user, without becoming part of the output, use Out-Host rather than Write-Host, because Out-Host does apply the rich formatting:
$x | Out-Host # print visualization of the whole object directly to the host
$x.results | Out-Host # just the .results property
# Ditto via ConvertTo-Json
$x | ConvertTo-Json | Out-Host
...

For-each loop unable to process all strings

I am trying to genrate URLs using a bunch of strings and an anchor URL
strings in s.txt are
123
234
345
anchor URL is https://testurl.com/prod/hostdetails.php?qs=
The code I am using
$ur = gc C:\temp\s.txt
foreach($u in $ur) {
$test = invoke-webrequest -uri "https://testurl.com/prod/hostdetails.php?qs=$u" -UseDefaultCredentials
}
$test
but it returns data only for
https://testurl.com/prod/hostdetails.php?qs=345
Its because you reassign $test each time within your loop. I suggest this solution:
$test = 'https://testurl.com/prod/hostdetails.php?{0}' -f ((C:\temp\s.txt) -join '&')
You edited your question. This is probably what you are looking for. Please notice the += operator to concat the results:
$result = #()
Get-Content C:\temp\s.txt | ForEach-Object {
$result += invoke-webrequest -uri "https://testurl.com/prod/hostdetails.php?qs=$($_)"
}

How do i add an unknown number of variables to a command

I have a script which I'm trying to modify, which adds objects to a firewall via powershell, using Invoke-RestMethod
The current script has the following code;
#Import CSV and set variables
$csv = import-csv C:\Powershell\groups.csv
# RESTful API Call
$csv | ForEach-Object {
$Name = $_.name
$Member1 =$_.member1
$Member2 =$_.member2
Invoke-RestMethod -Uri https://172.16.16.16:4444/webconsole/APIController?reqxml=<Request><Login><Username>admin</Username><Password>password</Password></Login><Set%20operation=%27add%27><IPHostGroup><Name>$Name</Name><IPFamily>IPv4</IPFamily><HostList><Host>$Member1</Host><Host>$Member2</Host></IPHostGroup></Set></Request>
}
I am wanting to import the hostgroups via groups.csv which (in my test) has 3 columns as follows;
Name,Member1,Member2
TestGroup,TestHost1,TestHost2
TestGroup2,TestHost3,TestHost4
etc.
My problem is that in the real data, there are varying amount of hosts in each group, some have hundreds. I'm not sure how to get these into the command without defining a variable for each possible member. Even then, say I created $Member(s) all the way to 200 (be gentle, I'm not a real coder!) and then imported them in manually one by one in the Invoke-Restmethod command (Might as well do it by hand at that point!) I'm not sure the command would handle the blank inputs in the cases where there were only a few hosts in the group.
(In other words if my csv had the following entries;)
Name,Member1,Member2,Member3,Member4
TestGroup,TestHost1,TestHost2,TestHost3,TestHost4
TestGroup2,TestHost5,TestHost6
TestGroup3,TestHost7
And I did;
# RESTful API Call
$csv | ForEach-Object {
$Name = $_.name
$Member1 =$_.member1
$Member2 =$_.member2
$Member3 =$_.member3
$Member4 =$_.member4
The Rest call for the third group would end up running as;
Invoke-RestMethod -Uri https://172.16.16.16:4444/webconsole/APIController?reqxml=<Request><Login><Username>admin</Username><Password>password</Password></Login><Set%20operation=%27add%27><IPHostGroup><Name>TestGroup3</Name><IPFamily>IPv4</IPFamily><HostList><Host>TestHost7</Host><Host></Host><Host></Host><Host></Host></IPHostGroup></Set></Request>
Can anyone point me in the direction of a better way of doing this?
You can get all member names using .PSObject.Properties.Name
Example:
$Csv = Import-Csv -Path 'C:\Powershell\groups.csv'
# Request XML template
$RequestTpl = #'
<Request>
<Login>
<Username>admin</Username>
<Password>password</Password>
</Login>
<Set%20operation=%27add%27>
<IPHostGroup>
<Name>{0}</Name>
<IPFamily>IPv4</IPFamily>
<HostList>
{1}
</HostList>
</IPHostGroup>
</Set>
</Request>
'#
# Host list XML template
$RequestHostListTpl = '<Host>{0}</Host>'
$Csv | ForEach-Object {
<#
Get names of all the properties in the current object
Leave only those that don't match '^Name$' regex.
-match, when operates on collections, returns matched items
You can use
$_.PSObject.Properties.Name | Where-Object {$_ -ne 'Name'}
but it's a bit slower.
#>
$Members = #($_.PSObject.Properties.Name) -notmatch '^Name$'
# Build list of hosts
$RequestHostList = foreach ($item in $Members) {
# Only add item if it's not empty
if ($_.$item) {
$RequestHostListTpl -f $_.$item
}
}
# Build request XML
$Request = $RequestTpl -f $_.Name, -join $RequestHostList
# Remove newlines to make it one long string
$Request = $Request -replace '\r|\n'
# Show resulting url
"Invoke-RestMethod -Uri https://172.16.16.16:4444/webconsole/APIController?reqxml=$Request"
# Uncomment to actually invoke API call
#Invoke-RestMethod -Uri "https://172.16.16.16:4444/webconsole/APIController?reqxml=$Request"
}

Formatting Output of an Array

I've encountered a situation that I cannot seem to find a solution to. I am scraping a website using Invoke-WebRequest and when I look at my output from my array, several of the properties are System.Objects. I need to find a way to have them be strings so that when I Export-Csv I can actually see the values. Here is my code:
$params = #{api_id='';api_key='';page_size='100';site_id=''}
$stats = Invoke-WebRequest https://my.incapsula.com/api/visits/v1 -Method Post -Body $params
$s = $stats
$s = $s | ConvertFrom-Json
$s = $s.visits
Here are what my results look like:
My solution was to create a new custom object and use the following syntax on the properties that were an object themselves:
($_ | select -expandproperty 'propertyname')