Exclude terminating error from try/catch PowerShell - powershell

I am having difficulty in checking if a group exists or not via a Rest API.
Call the Api to check if the Group exists. My logic: Use the 'Invoke-RestMethod' to call the API. If the API call is successful (Group exists) it will store the result in '$reader_response_success', if the group does not exist, the cmdlet will fail, the error details are stored in the Error Variable '$reader_response_failure'.
Depending on which variable has values, I can conclude whether group exists or not. However, our framework has a Try/Catch implementation. So, in case if the group does not exist, the entire script will STOP executing.
How can I make sure that the script will continue execution even if the API call fails. (As I know that the API call will fail if the group does not exist). I have given $errorAction as 'SilentlyContinue' but still it STOPS the script execution.
function Test-CoeAzureInstancePowerBI{
param
(
[Parameter (Mandatory = $true, ValueFromPipeline = $true)]
$ServiceConfiguration
)
## TODO: Check if the Reader and Creator Group exists in dwgm
# Checking if ReaderGroup exists
$Group = #{
GroupName = "ITGA_" + $ServiceConfiguration.ReaderGroup
}
$json = $Group | ConvertTo-Json
$reader_response_success = Invoke-RestMethod 'https://api.corpinter.net/dwgm/v1/lookup/' -Headers $ServiceConfiguration.Headers -Method POST -Body $json -ContentType 'application/json' -ErrorVariable $reader_response_failure -ErrorAction SilentlyContinue
# In the above api call,
# $reader_response_success contains data if the group exists
# $reader_response_failure contains data if the group does not exist
if($reader_response_success -eq $null) {$ServiceConfiguration.ReaderGroupExists = $False}
# Checking if ReaderGroup exists
$Group = #{
GroupName = "ITGA_" + $ServiceConfiguration.CreatorGroup
}
$json = $Group | ConvertTo-Json
$creator_response_success = Invoke-RestMethod 'https://api.corpinter.net/dwgm/v1/lookup/' -Headers $ServiceConfiguration.Headers -Method POST -Body $json -ContentType 'application/json' -ErrorVariable $creator_response_failure -ErrorAction SilentlyContinue
# In the above api call,
# $creator_response_success contains data if the group exists
# $creator_response_failure contains data if the group does not exist
if($creator_response_success -eq $null) {$ServiceConfiguration.CreatorGroupExists = $False}
## The instance should be SKIPPED only if both the ReaderGroup and CreatorGroup exist
if($ServiceConfiguration.CreatorGroupExists -eq $true -and $ServiceConfiguration.ReaderGroupExists -eq $true){
return $true
}else{
return $False
}
}

-ErrorAction SilentlyContinue will continue on non-terminating errors only. So you probably get a terminating error. You can just do your own error handling for that particular cmdlet:
try {
$reader_response_success = Invoke-RestMethod 'https://api.corpinter.net/dwgm/v1/lookup/' -Headers $ServiceConfiguration.Headers -Method POST -Body $json -ContentType 'application/json'
} catch {
# Do some error handling here (probably nothing according to your code so far)
}
Do the same for the second Invoke-RestMethod call.

Related

Why do two files viewed through the Dropbox API have the same id?

I'm querying the Dropbox API using PowerShell successfully and getting all the files and folders using https://api.dropboxapi.com/2/files/list_folder. I'm putting the files and folders in separate arrays, but when trying to pull a single file by id out of them, there are a couple ids that reference two different files. Why is this?
Here's the snippet where it's happening:
try {
$request = Invoke-RestMethod -Uri $list_folder_url -Method Post -Headers $headers -ContentType "application/json" -Body (ConvertTo-Json -InputObject $body)
} catch {
$_.Exception.Response
}
$folders += $request.entries[0]
while ($request.has_more) {
$cursor = $request.cursor
$body = #{
cursor="$cursor"
}
$request = Invoke-RestMethod -Uri $folder_continue_url -Method Post -Headers $headers -ContentType "application/json" -Body (ConvertTo-Json -InputObject $body)
$folders += $request.entries | ? { $_.'.tag' -eq "folder"}
$files += $request.entries | ? { $_.'.tag' -eq "file"}
}
$file = $files | ? { $_.id -eq "id:**************" } ## Returns two very different files with the same id
Dropbox files IDs are case-sensitive, and some Dropbox file IDs may vary only by case.
In this code, you're using PowerShell's -eq operator, but according to the PowerShell documentation:
By default, all comparison operators are case-insensitive.
So, you may be getting multiple entries where the file IDs are only different by case. Try using -ceq instead of -eq:
To make a comparison operator case-sensitive, add a c after the -. For example, -ceq is the case-sensitive version of -eq.

How do I get return values from Invoke-WebRequest

I am trying to figure out how to get results from a Invoke-WebRequest to download a file from the internet. I wrote a function but it doesn't seem to get the results. StatusCode and StatusDescription never change even if it works:
function DownloadUpgradeTool()
{
##download upgrade tools from MS
Write-Host "Downloading Upgrade Tool from MS."
$url = "https://download.microsoft.com/download/3/d/c/3dcc9642-d3a0-459c-86fd-128f5a0c3cc5/Windows10Upgrade9252.exe"
$output = "c:\Temp\upgrade.exe"
$StatusCode = 1
$StatusDescription = "Error downloading file"
try
{
$response = Invoke-WebRequest -Uri $url -OutFile $output -ErrorAction Stop
}
catch
{
$StatusCode = $_.Exception.Response.StatusCode.value__
$StatusDescription = $_.Exception.Response.StatusDescription
}
Write-Host " Download Status Code: " $StatusCode
Write-Host "Download Status Description: " $StatusDescription
if ($StatusCode)
{
return $False
}
else
{
return $True
}
}
function RunUpgrade()
{
##run silent upgrade
##c:\Temp\upgrade.exe /quietinstall /skipeula /auto upgrade /copylogs c:\Temp
}
You get the status code when you evaluate the object that is returned by Invoke-WebRequest
$response = Invoke-WebRequest -URI $url -OutFile $output -ErrorAction Stop
Write-Host $response.StatusCode
$r = Invoke-WebRequest -URI https://stackoverflow.com/questions/20259251/
Write-Host $r.StatusCode
https://davidhamann.de/2019/04/12/powershell-invoke-webrequest-by-example/
Powershell implements the OOP (object-oriented programming) design paradigms and semantics i.e. when writing object-oriented code each class has to have a constructor (new()) and a destructor and it should have get() and set() methods to access (read and write) the fields (or attributes) of a class. In ps this is straighlty implemented
Return values of cmdlets are often objects (in the sense of OOP) and you can access the fields of the objects to gather the data ...
It is also possible to use object-oriented design patterns in ps scripting https://dfinke.github.io/powershell,%20design%20patterns/2018/04/13/PowerShell-And-Design-Patterns.html
You need to include -PassThru when you are using -OutFile if you want something in your $response variable.
The exact purpose of PassThru from the PowerShell docs.
Indicates that the cmdlet returns the results, in addition to writing
them to a file. This parameter is valid only when the OutFile
parameter is also used in the command.
For example,
$response = Invoke-WebRequest -Uri 'www.google.com'
if ( $response.StatusCode -eq 200 )
{
#This bit runs for HTTP success
}
$response = Invoke-WebRequest -Uri 'www.google.com' -OutFile 'googleHome.html'
if ( $response.StatusCode -eq 200 )
{
#This never runs as $response never has a value even though the googleHome.html file gets created
}
$response = Invoke-WebRequest -Uri 'www.google.com' -OutFile 'googleHome.html' -PassThru
if ( $response.StatusCode -eq 200 )
{
#This bit runs for HTTP success and the file gets created
}

Azure Automation Runbook unable to parse the webhookdata as a JSON object

I am badly struck by this problem. I request you to answer or give a hint. I am running out of options.
I am calling an azure runbook upon high CPU utilization via a WebHook. My problem is inside runbook data is not getting decoded properly. For example, the below line is not printing anything.
Write-Output $WebHookData.RequestHeader
Wheras IF i try to explictly convert the data to JSON, like this
*$WebhookData = ConvertFrom-Json $WebhookData*
then it is a throwing error.
ConvertFrom-Json : Invalid JSON primitive: . At line:6 char:31 +
$WebhookData = $WebhookData | ConvertFrom-Json
By the way, I am trying to use the runbook available on Azure gallery {Vertically scale up an Azure Resource Manager VM with Azure Automation}
My Webhook is called from alert created on VM.
A very strange observation:
Working WebHood Example (found in an example) {"WebhookName":"test1","RequestBody":" [\r\n {\r\n \"Message\": \"Test Message\"\r\n }\r\n****]****"
Not Working(the data sent upon calling runbook from VM):
{"WebhookName":"test2","RequestBody":" {\"schemaId\":\"AzureMonitorMetricAlert\"}}
Thanks
I was getting the same error. From my testing, it appears that when performing a "Test" of the runbook, the Webhook data is received as plain text, but when invoked remotely it comes through already formatted as JSON. Here was my solution to cover both scenarios and so far has been working well...
Param (
[object] $WebhookData
)
# Structure Webhook Input Data
If ($WebhookData.WebhookName) {
$WebhookName = $WebhookData.WebhookName
$WebhookHeaders = $WebhookData.RequestHeader
$WebhookBody = $WebhookData.RequestBody
} ElseIf ($WebhookData) {
$WebhookJSON = ConvertFrom-Json -InputObject $WebhookData
$WebhookName = $WebhookJSON.WebhookName
$WebhookHeaders = $WebhookJSON.RequestHeader
$WebhookBody = $WebhookJSON.RequestBody
} Else {
Write-Error -Message 'Runbook was not started from Webhook' -ErrorAction stop
}
I tried with a webhook, the script Write-Output $WebHookData.RequestHeader should work fine.
And if I use ConvertFrom-Json $WebhookData, I can reproduce your issue, not sure why it occurred, according to the doc, the $WebhookData is also in a JSON format, if it is accepted, you could use ConvertFrom-Json -InputObject $WebhookData.RequestBody, it will work fine.
My runbook:
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
if ($WebhookData) {
Write-Output $WebhookData.RequestHeader
$Body = ConvertFrom-Json -InputObject $WebhookData.RequestBody
Write-Output $Body
} else
{
Write-Output "Missing information";
exit;
}
The powershell script I used to send a webhook:
$uri = "https://s5events.azure-automation.net/webhooks?token=xxxxxxxxxxxx"
$vms = #(
#{ Name="vm01";ResourceGroup="vm01"},
#{ Name="vm02";ResourceGroup="vm02"}
)
$body = ConvertTo-Json -InputObject $vms
$header = #{ message="StartedbyContoso"}
$response = Invoke-WebRequest -Method Post -Uri $uri -Body $body -Headers $header
$jobid = (ConvertFrom-Json ($response.Content)).jobids[0]
Output:
I had the same problem use following to get webhookdata if using test pane with Alert json as input
if(-Not $WebhookData.RequestBody){
$WebhookData = (ConvertFrom-Json -InputObject $WebhookData)
}
$RequestBody = ConvertFrom-JSON -InputObject $WebhookData.RequestBody

Using powershell's Invoke-RestMethod cmdlet is only returning the word "success" as a result

I have written 2 scripts. One in python and one in powershell. Python is able to call a rest api and is returned the string "JSESSIONID=8kfv0fi1bc84gtw2xvnqsrt4;Path=/;Secure;HttpOnly ". When I use the following code in powershell, it returns "success". What am I doing wrong?
$getEncCode = "Er6TmdhXn09Y9C1I"
$dataPart1 = #{EncCode=$getEncCode}
$dataPart = $dataPart1 | ConvertTo-Json
$uri = "https://10.164.42.77:8092/getEnc/2252953/login"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$result = Invoke-RestMethod -Method Post -Body $dataPart -uri $uri -ContentType "application/json"
Write-Host $result
Write-Host $result uses the $result.ToString() method to display that object as a string.
Likely there is more data there to show. Simply remove Write-Host to see it. Or do something like Get-Member -InputObject $result to see all immediate properties, methods etc.
Have a look at Printing object properties in Powershell to see other ways to deal with this.

Azure Automation Account: How to Pass Webhook data to a runbook?

I have an Azure Runbook in an Azure Automation account, which I would like to trigger with a webhook which contains some parameters.
The runbook looks like this
workflow do-something
{
param
(
[object]$WebhookData
)
inlinescript {
if ($WebhookData -ne $null) {
$WebhookName = $WebhookData.WebhookName
$WebhookBody = $WebhookData.RequestBody
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
$customerEmail = $webhookBodyObject.customerEmail
$customerName = $webhookBodyObject.customerName
$dataLocation = $webhookBodyObject.dataLocation
} else {
"The WebhookData is totally and completely null"
exit (0)
}
$webhookjson = $WebhookData | ConvertTo-JSON
"The webhookdata is $webhookjson"
"The webhook name is $WebhookName"
"The customer email is $customerEmail"
"The body s $WebhookBody"
}
}
I then saved it and published it, and then got a webhook for it. As per instructions, i wrote a little Powershell script to trigger the webhook:
#Not the real URI, but similar in structure
$uri = "https://s10events.azure-automation.net/webhooks?token=Qt%xyxyxyxyxyxyxyxyxyxyxyxy%ababababab%3d"
$headers = #{"From"="babu#bhatt.com";"Date"="05/28/2015 15:47:00"}
$params = #{"customerName"="Jay Godse"; "customerEmail"="jaygodse#exmple.com"; "dataLocation"="Canada"}
$body = ConvertTo-Json -InputObject $params
#$response = Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -Body $body
$webresp = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body -Verbose
When I invoked the request, i got a 202 response code which suggested that the request was successfully queued.
Then I went to the Jobs section in the Runbook, and and looked at the input and output of the job. The input looked like this:
{"WebhookName":"test1","RequestBody":"{\r\n \"customerEmail\": \"jaygodse#exmple.com\",\r\n \"customerName\": \"Jay Godse\",\r\n \"dataLocation\": \"Canada\"\r\n}","RequestHeader":{"Connection":"Keep-Alive","Date":"Thu, 28 May 2015 19:47:00 GMT","From":"babu#bhatt.com","Host":"s10events.azure-automation.net","User-Agent":"Mozilla/5.0","x-ms-request-id":"d8995f98-1344-4822-af69-ababababababa"}}
The output looked like this:
The WebhookData is totally and completely null
What do I have to do to pass data successfully from the webhook to the my Azure Automation runbook? I couldn't find any examples on the web which actually worked.
You should use $using: scope inside the inlinescript {} block like that:
workflow do-something
{
param
(
[object]$WebhookData
)
inlinescript {
if ($using:WebhookData -ne $null) {
$WebhookName = $using:WebhookData.WebhookName
$WebhookBody = $using:WebhookData.RequestBody
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
$customerEmail = $webhookBodyObject.customerEmail
$customerName = $webhookBodyObject.customerName
$dataLocation = $webhookBodyObject.dataLocation
} else {
"The WebhookData is totally and completely null"
exit (0)
}
$webhookjson = $using:WebhookData | ConvertTo-JSON
"The webhookdata is $webhookjson"
"The webhook name is $WebhookName"
"The customer email is $customerEmail"
"The body s $WebhookBody"
}
}
See the explanation here: https://technet.microsoft.com/en-us/library/jj574197(v=ws.11).aspx ("Variables in InlineScript" section).