Running PowerShell code in powershell works, executing as .ps1 doesn't - powershell

I wrote some code which tries to Get a value from one Rest API and post it to another.
I have the code saves in a .ps1 file. If I edit it and run it (or just copy and paste it into an empty PowerShell terminal) it does what I expect. However when I try to run the same .ps1 file directly I get an error on the 2nd Invoke-RestMethod.
Don't understand why I'm getting a different result and the error message not giving me many clues.
What am I doing wrong?
The code I am using is (with modified API key):
$encoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($APIkey+":"))
$headers = #{"Content-Type" = "application/json"; "AUTHORIZATION" = "Basic $encoded"}
$APIkey = "123456789"
$metricId = "123"
$r = Invoke-RestMethod -Uri https://coinbase.com/api/v1/currencies/exchange_rates
$metric = [PSCustomObject]#{
value = [Math]::Round($r.btc_to_eur, 2)
}
$baseuri = "https://api.numerousapp.com/v1/metrics/$metricId/events"
$data = ConvertTo-Json $metric
Invoke-RestMethod -Uri $baseuri -Body $data -Headers $headers -Method Post
And the error message I get when running the .ps1 file is:
Invoke-RestMethod : :
At C:\NumerousBitcoinEur.ps1:13 char:1
+ Invoke-RestMethod -Uri $baseuri -Body $data -Headers $headers -Method Post
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I'm using PowerShell 4.0

$APIkey is being set after it is being used, which must be wrong. It probably works in the console because $APIkey happens to already be set.
If you like (I think it's a good idea), you can add the following to the top of your scripts to catch errors like this one.
Set-StrictMode -Version Latest

Related

Invoke-RestMethod The underlying connection was closed: An unexpected error occurred on a receive

To Introduce myself : Working as a Power BI Developer with PBI Admin access.
My Powershell script stoped working suddenly and prompting me an error saying the underlying connection was closed. This was all working fine few days back.
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a receive.
At line:25 char:7
Invoke-RestMethod -Method Post -uri $url1 -Headers $authHeader ...
CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExcepti on
FullyQualifiedErrorId:WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Login-PowerBI
$groupid = "Hidden"
$Reportid = "Hidden"
$Folder = "c:\temp\"
$Body = "{`”format`”:`”pdf`”}"
$filename = $Folder + "PowerBIMetrics.pdf"
$StatusCheck=0
$token = Get-PowerBIAccessToken -AsString
$authHeader = #{
"Authorization"= $token
"Content-Type" = "application/json"
}
$url1 = "https://api.powerbi.com/v1.0/myorg/groups/$groupid/reports/$Reportid/ExportTo"
Invoke-RestMethod -Method Post -uri $url1 -Headers $authHeader -body $Body'
I have also tried to look for solution and many of them (Power BI community/ DBA) is saying I need to add extra line of code below before I execute the Invoke-ResMethod command line,
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Unfortunately, I'm getting same error message if i add above line.
I passed in parameters groupId/reportid/body and click "run" but nothing happens, it doesn't give me any result, this was working fine before.
https://learn.microsoft.com/en-us/rest/api/power-bi/reports/export-to-file#code-try-0

Looping an invoke-RestMethod?

So I'm trying to automate a process at work which involves hitting SendGrid's API. For a short explanation.. with SendGrid you have Subusers and underneath those Teammates. There is no ready option to search all teammates, so you have to supply a subuser then display all teammates underneath. Rinse, repeat down the line. Well I'd like to automated as best as I can.
So the idea is to collect a teammate email address from then user then dump into a variable all the subusers then loop through those subusers looking for the $email variable.
I've never actually used loops in my scripts over the years so it's new territory for me and combining it with an invoke-restmethod just boggles me. heres what Ive got so far:
$token = 'xxxxxxxxxxxxxxxxxxx'
#First uri is to pull a list of subusers
$uri = "https://api.sendgrid.com/v3/subusers"
#Prompts for target email address
$email = Read-Host "Enter the users email"
$headers1 = #{"Authorization" = "Bearer $token"}
$headers2 = #{"Authorization" = "Bearer $token"
"on-behalf-of" = "$subuser"
}
$subs = Invoke-RestMethod -Method get -uri $uri -headers $headers1
$subarray = $subs | select-object username
foreach ($su in $subarray){
$teamarray = invoke-restmethod -method get -uri "https://api.sendgrid.com/v3/teammates?limit=500&offset=0" -headers $headers2
#$teamarray.gettype()
}
The last line is commented out.. i was trying to find teh type of the $teamarray data but it's giving this error for each loop through the subusers:
invoke-restmethod : {"errors":[{"field":null,"message":"authorization required"}]}
At line:18 char:18
+ ... teamarray = invoke-restmethod -method get -uri "https://api.sendgrid. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod],
WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodComma
nd
This should mean the invoke-restmethod is malformed somehow. Any pointers would be appreciated!

powershell invoke rest api toward AWX

I'm struggling for last week or more with sending rest api command from powershell to add host in AWX(from curl is working). When I sent one parameter is worki but I need to send also variables
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic $VfAwxTokenX")
$Headers.Add('Content-Type', 'application/json')
$body = #{
name = '$vmname'
variables = 'test'
}| ConvertTo-Json
write-output $body
$response = Invoke-RestMethod 'https://awx/api/v2/inventories/2/hosts/' -Method 'POST' -Headers $headers -UseBasicParsing -Body $body
and error what i get:
{
"name": "wewewe",
"variables": "test" } Invoke-RestMethod : {"variables":["Cannot parse as JSON (error: Expecting value: line 1 column 1 (char 0)) or
YAML (error: Input type str is not a dictionary)."]} At line:32
char:13
$response = Invoke-RestMethod 'https://awx/api ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod],
WebException
FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Maybe any one of users had that issue and now how to overcome it?
According to my research, the parameter variables should be defined as JSON or YAML format. For more details, please refer to here.
For more details about how to call the API, please refer to the blog.
the problem was prosaic
variables = 'test'
if i put anything else then test is working :/

Powershell v5.1 Invoke-RestMethod Error Parsing Body

I'm a beginner with Powershell who's trying to send a PUT request to Microsoft Azure to create an Application Insights log query. I'm able to get this working in Postman, but not in a powershell script. This is the error that I'm getting when running the script:
Invoke-RestMethod : {"code":"Unexpected character encountered while parsing value: S. Path '', line 0, position 0.","message":"Unexpected character encountered while parsing value: S. Path '', line 0, position 0.","innererror":{"diagnosticcontext":"f2843c54-dad7-49b5-92ab-e1dadd40e145","time":"2020-07-24T19:59:45.7979293Z"}}
At C:\Users\thophan\source\Update-AiLogQueries.ps1:58 char:9
+ Invoke-RestMethod -Method Put -Uri $uri -Header $header -Body ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
From looking at the Microsoft documentation, it looks like it's supposed to be able to take in a hashtable for the body, and I'm quite certain my syntax looks exactly the same as the one from the exameple, so I'm not sure what's going on. Below is an excerpt from my script:
$scope = "shared"
$header = #{
"Authorization" = "Bearer $token"
}
$uri = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$rgName/providers/microsoft.insights/components/$aiName/analyticsItems/item?api-version=2020-02-02-preview"
$difference = Compare-Object -ReferenceObject $localQueryList.value -DifferenceObject $response
if ($difference -ne $null)
{
$difference.ForEach(
{
$body = #{
Scope = $scope
Type = "query"
Name = $_.InputObject.Name
Content = $_.InputObject.Content
}
Invoke-RestMethod -Method Put -Uri $uri -Header $header -Body $body
})
}
UPDATE: Here is the documentation that I was looking at, as requested.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-5.1
The API requires that the body be a JSON string. You can do a simple conversion (using ConvertTo-Json) in your Invoke-RestMethod command and set the content type accordingly.
Invoke-RestMethod -Method Put -Uri $uri -Header $header -Body ($body | ConvertTo-Json) -ContentType 'application/json'

PowerShell v3 Invoke-WebRequest: Troubles with forms

Since I upgraded to Windows 8 a lot of my PowerShell scripts relying on launching an invisible IE won’t quite work anymore, so I tried switching to the Invoke-WebRequest command. I did a lot of googling but still can’t get my script to work.
This is what it should do:
load up a website with a simple form (username, password, submit-button),
enter the credentials
and submit them.
The Microsoft tech-net examples were not very helpful for me, that is what I pieced together:
$myUrl = "http://some.url"
$response = Invoke-WebRequest -Uri $myUrl -Method Default -SessionVariable $rb
$form = $response.Forms[0]
$form.Fields["user"] = "username"
$form.Fields["password"] = "password"
$response = Invoke-WebRequest -Uri $form.Action -WebSession $rb -Method POST
$response.StatusDescriptionOK
I receive two errors, the first one when trying to write into the user field:
Cannot index into a null array.
$form.Fields["user"] = "username"
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
The second one has to do with the $form.Action which I have no idea what it should read:
Invoke-WebRequest : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
Again, I relied heavily on example #2 at Microsoft.
Try doing the post directly e.g.:
$formFields = #{username='john doe';password='123'}
Invoke-WebRequest -Uri $myUrl -Method Post -Body $formFields -ContentType "application/x-www-form-urlencoded"
To address your problem with the unsigned/untrusted certificate, add the line
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
before the Invoke-WebRequest statement
The example in the question works, but you have to use rb and not $rb in the first line:
$response = Invoke-WebRequest -Uri $myUrl -Method Default -SessionVariable rb
I also had to use ($myUrl + '/login') since this is my login address.
$response = Invoke-WebRequest -Uri ($myUrl + '/login') -Method Default -SessionVariable rb
And in the last line used ($myUrl + $form.Action):
$response = Invoke-WebRequest -Uri ($myUrl + $form.Action) -WebSession $rb -Method POST
If you're me and have been troubleshooting a bad Web Request, in my case a -Body that was becoming null at my API, then you will want to know about the gotcha that is about interleaving your line continuations with comments. This
$r = iwr -uri $url `
-method 'POST' `
-headers $headers `
# -contenttype 'application/x-www-form-urlencoded' ` # default
-Body $body
Notice the commented out line # -contenttype 'application/x-www-form-urlencoded' # default
Putting a comment truncates the remaining back-ticked line continuation. Therefore, in my case my web request ended up with a request having 0-byte payload.