Variable in Invoke-WebRequest -Uri path - powershell

I am trying to pass a MAC Address and code (1,2,3,4) to Invoke-WebRequest.
Manually the command is working fine, but I am not able to do it via command.
The manual command that works is:
Invoke-WebRequest -Uri https://mywebsite.org/pcconfig/setstate.php?mac=F832E3A2503B"&"state=4
Now when I break this up into variable to use with the mac from the machine I do the following.
$LiveMAC = Get-NetAdapter -Physical |
where Status -eq "Up" |
Select-Object -ExpandProperty PermanentAddress
$Str1 = "https://mywebsite.org/pcconfig/setstate.php?mac=$LiveMAC"
$Str2 = $Str1 + '"&"' + 'state=4'
Invoke-WebRequest -Uri $Str2
When I run the above code I do not see errors in red, it seems to process but does not work.
Looking at $Str2 I see the below output, which seems correct, but when passing it as above it fails to work.
https://mywebsite.org/pcconfig/setstate.php?mac=F832E3A2503B"&"state=4

The double quotes in a statement like
Invoke-WebRequest -Uri https://example.org/some/sit.php?foo=x"&"bar=y
mask the ampersand for PowerShell, because otherwise otherwise PowerShell would throw an error that a bare & is reserved for future use. A more canonical way of avoiding this is to put the entire URI in quotes:
Invoke-WebRequest -Uri "https://example.org/some/sit.php?foo=x&bar=y"
Either way the actual URI that is passed to Invoke-WebRequest is
https://example.org/some/sit.php?foo=x&bar=y
without the quotes.
However, in a code snippet like this:
$Str1 = "https://example.org/some/site.php?foo=$foo"
$Str2 = $Str1 + '"&"' + 'state=4'
you're including literal double quotes as part of the URI, so the actual URI passed to the cmdlet would be
https://example.org/some/sit.php?foo=x"&"bar=y
which is invalid.
With that said, you don't need string concatenation for building your URI anyway. Simply put your variable in the double-quoted string:
$uri = "https://example.org/some/sit.php?foo=${foo}&bar=y"
If you need to insert the value of an object property or array element use either a subexpression
$uri = "https://example.org/some/sit.php?foo=$($foo[2])&bar=y"
or the format operator
$uri = 'https://example.org/some/sit.php?foo={0}&bar=y' -f $foo[2]

Related

How do I access PowerShell object values? [duplicate]

This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 1 year ago.
I currently have an Azure DevOps pipeline that makes a REST API call which returns an object of parameters:
#{location=eastus2; envName=sandbox; ...}
My PowerShell script looks like:
steps:
- powershell: |
$uri = "https://dev.azure.com/{org}/{proj}/_apis/build/latest/{buildId}?branchName={name}&api-version=6.0-preview.1"
$token = [System.Text.Encoding]::UTF8.GetBytes("$(System.AccessToken)" + ":")
$base64 = [System.Convert]::ToBase64String($token)
$basicAuth = [string]::Format("Basic {0}", $base64)
$headers = #{ Authorization = $basicAuth }
$result = Invoke-RestMethod -Method Get -Uri $uri -Headers $headers -ContentType application/json
$params = $result.templateParameters
Write-Host "##vso[task.setvariable variable=paramObj]$params"
- powershell: |
Write-Host $(paramObj)
In this first PS task I can use $params.location which will return eastus2. However, in the second PS task I get an error saying:
Line |
2 | Write-Host #{location=eastus2; envName=Sandbox; sqlDBAutoPauseDatabas …
| ~~~~~~~
| The term 'eastus2' is not recognized as a name of a cmdlet,
| function, script file, or executable program. Check the
| spelling of the name, or if a path was included, verify that
| the path is correct and try again.
Since my API call has an object of parameters, I'm trying to pass that parameter object to another task where I can then use those values. In the second task seen above I can't log the result, so of course trying to use dot notation, or Select-Object all results in the same error.
I was also attempting to iterate over the parameters object so I could do something like:
steps:
- powershell: |
...
$params = $result.templateParameters
foreach ($param in $params) {
Write-Host "##vso[task.setvariable variable=test]$param.Value"
}
- powershell: |
Write-Host $(location)
But I haven't been able to figure this out either as I keep getting the same error listed above. How do I access the parameter values in a second script without hardcoding it?
You've encountered the magic of expandable string parsing in PowerShell.
When you place a variable expression, like $param, inside an expandable string (a string literal bounded with " double quotes), PowerShell will attempt to resolve it's value for you - but nothing more than that - it's not going to attempt to evaluate member invocation, like $param.Value, for example.
So a string literal like this:
"$param.Value"
Will expand to:
"#{location=eastus2;...}.Value"
Notice that $params was evaluated and it's value substituted in the string, and the .Value-part is completely ignored.
To force PowerShell to evaluate expressions more complicated than simple variable references, use the $() subexpression operator:
Write-Host "##vso[task.setvariable variable=test]$($param.Value)"

Azure devops rest api returns only 100 projects

I am trying to retrieve all projects from my organizations
I have 300 projects but api call returns only 100
I tried using $top with api then it returns nothing
Here is my script which works for getting 100 projects and converting to csv file but I need details of all 300 projects in this csv file -
connectionToken = ""
$BaseUrl = "https://dev.azure.com/{organization_name}/_apis/projects?api-
versions=5.0"
$base64AuthInfo =
[System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes
(":$($connectionToken)"))
$ProjectInfo = Invoke-RestMethod -Uri $BaseUrl -Headers #{authorization =
"Basic $base64AuthInfo"} - Method Get
$ProjectDetails = $ProjectInfo | ConvertTo-Json -Depth 100 | out-file
"/list.json"
$ProjectList = Get-Content "/list.json" -Raw | ConvertFromJson | select -
Expand value | Export-CSV "list.csv"
I also tried using invoke-webrequest it also returns nothing
Thank you
Azure devops rest api returns only 100 projects
The answer is use a specify $top parameter.
But when using this parameter in powershell, we need to be careful to escape the $ by ` instead of &.
That's because in powershell, single quotation '' marks only represent the characters within the quotation marks in any case. In other words, the content within single quotes will not be substituted for variables and escaped characters. In double quotes "", variable substitution and character escaping are allowed.
When you use the double quotes with the BaseUrl:
$BaseUrl = "https://dev.azure.com/{organization_name}/_apis/projects?api-versions=5.0"
We need escape character $ if we add $top=300 instead of & in that URL.
So, the BaseUrl should be:
$BaseUrl = "https://dev.azure.com/{organization_name}/_apis/projects?`$top=300&api-version=5.0"
Or you could use single quotation for the URL:
$BaseUrl = 'https://dev.azure.com/{organization_name}/_apis/projects?$top=300&api-version=5.0'
Check the document Escaping in PowerShell:
The PowerShell escape character is the backtick "`" character.
Below is my test result:

store and call variable in Powershell script

Below is the HTML DOM, I want to store DatePlannedStartTimeStamp value "01/24/2017 18:00" in a variable, print and call later
<TD class=dbData><SPAN onmouseover="ShowDay(this.innerHTML, 231320)"
onmouseout=nd() id=DatePlannedStartTimeStamp>01/24/2017 18:00</SPAN></TD>
I tried below but it does not return any value
$HTML = Invoke-WebRequest -Uri $URL -UseDefaultCredential
$WebPageText = ($HTML.ParsedHtml.getElementsByTagName("a") | Where-
Object{$_.ID -match "DatePlannedStartTimeStamp"}).innerText
echo $WebPageText
Not sure if my tagname is correct. I'm still learning powershell script, it would be great help if there is a way to it.

PowerShell Cannot get element from HTML

I encountered a problem today while trying to get a value from a website using PowerShell.
This is the website.
I am trying to get the number "90" here, that in the webpage itself is the value of "Downloaded" (this number might be a little bigger when you look at it if there are more downloads):Screenshot of the element i am trying to return
<span title="Downloads" class="mod-card-info-tag" data-reactid=".0.0.0.2.0.0.2.2">
<div class="mod-card-info-tag-label" data-reactid=".0.0.0.2.0.0.2.2.0">90</div>
This is the PowerShell code i used to try and get the number "90" from the element above (i know i should use ".innertext" in the end, i just used the get-member to see if any object was found):
$URI = "https://mods.factorio.com/mods/TpTheGreat/TpTheGreats%20Large%20Roboport%20Logistics%20Area"
$HTML = Invoke-WebRequest -Uri $URI
($HTML.ParsedHtml.getElementsByTagName("div") | Where{ $_.className -eq ‘mod-card-info-tag-label’ }) | Get-Member
When calling for the element by tag name like in my code above, I get an empty object.
I tried lots of things without any success.
It'll be really great if any of you could take a look and check if you are able to solve my problem.
Thanks a lot!!!
How about another approach:
$URI = "https://mods.factorio.com/mods/TpTheGreat/TpTheGreats%20Large%20Roboport%20Logistics%20Area"
$HTML = Invoke-WebRequest -Uri $URI
$arr = $HTML.AllElements.Item(9).innerHTML -split ' = '
$myObj = $arr[1].replace("`n"," ")
$myObj = $myObj.replace(";","") | ConvertFrom-Json
$myObj.mod.mod.downloads_count

Powershell Custom Object toString value is used as a Note Property

I'm working with the JIRA API with the Issue changelog. The API call returns JSON key/value pairs. One of the keys is toString which is represented in the PS Custom Object as a NoteProperty. (Other keys are "to" "from" "fromString", etc.) When I reference the toString NoteProperty, PS thinks I'm calling the ToString() string method and it gives an OverLoadDefinition error.
$response is the variable I use to store the API call output.
$response.changelog.histories.items.to # this works fine
$response.changelog.histories.items.fromString # this works fine
$response.changelog.histories.items.toString # This fails.
PS thinks I want to call the toString() method.
Is there a way to force PS to use the NoteProperty value stored in the toString key?
Try to put it into single brakets like this:
$response.changelog.histories.items.'toString'
By trying some options I found something that works:
$JiraIssue = "https://jira/rest/api/2/issue/DAA-2662?fields=key,id,reporter&expand=changelog"
$response = Invoke-RestMethod -Method GET -Uri $JiraIssue -Headers #{"Authorization"="Basic $myCreds"} -ContentType application/json
$response.changelog.histories.items.tostring # FAILS
$response.changelog.histories.items[0].tostring # WORKS
foreach ($i in $response.changelog.histories.items ) {$i.tostring } # WORKS
When I reference items.toString it looks like PS is confused between the toString method and the NoteProperty with the same name. But when I reference a single array value within the items array items[0].toString, PS knows that I want the NoteProperty.
Any further comments or insight on this is most welcome!