Extract Response Data from Invoke-RestMethod - powershell

I have this piece of code which creates a new ticket in ServiceNow
$Response = Invoke-RestMethod -Uri $URI -Credential $SNowCreds -Method Post -Body $body -ContentType 'application/xml'
Write-IntoLog $Response.result
The output is stored in $Response and is as below
#{parent=; made_sla=true; caused_by=; watch_list=; upon_reject=Cancel all future Tasks; sys_updated_on=2018-01-11 08:49:50; child_incidents=0; hold_reason=; approval_history=; number=INC0010079; resolved_by=; sys_updated_by=Admin; opened_by=; user_input=; sys_created_on=2018-01-11 08:49:50; sys_domain=; state=In Progress; sys_created_by=Admin; knowledge=false; order=; calendar_stc=; closed_at=; cmdb_ci=; delivery_plan=; impact=2 - Medium; active=true; work_notes_list=; business_service=; priority=2 - High; sys_domain_path=/; rfc=; time_worked=; expected_start=; opened_at=2018-01-11 08:49:50; business_duration=; group_list=; work_end=; caller_id=; reopened_time=; resolved_at=; approval_set=; subcategory=Internal Application; work_notes=; short_description=Issues with Accessing Web URL; close_code=; correlation_display=; delivery_task=; work_start=; assignment_group=; additional_assignee_list=; business_stc=; description=We are facing issues with accessing the portal https://www.inmotion.com. The error Received is a 403 Error and Access to the same; calendar_duration=; close_notes=; notify=Do Not Notify; sys_class_name=Incident; closed_by=; follow_up=; parent_incident=; sys_id=2c40df9edb234300479a7e7dbf96198f; contact_type=; reopened_by=; incident_state=In Progress; urgency=1 - High; problem_id=; company=; reassignment_count=0; activity_due=UNKNOWN; assigned_to=; severity=3 - Low; comments=; approval=Not Yet Requested; sla_due=UNKNOWN; comments_and_work_notes=; due_date=; sys_mod_count=0; reopen_count=0; sys_tags=; escalation=Normal; upon_approval=Proceed to Next Task; correlation_id=; location=; category=Network}
From the output I want to extract the number(Incident ID) and also generate a link to the ServiceNow Incident.
However I am unable to extract the number(Incident ID). I tried converting the piece of output to JSON
$Response = Invoke-RestMethod -Uri $URI -Credential $SNowCreds -Method Post -Body $body -ContentType 'application/xml' | ConvertTo-Json
I tried to navigate it through the nodes. I am still not able to retrieve the IncidentID
Request your assistance in the above issue.

Without using the 'ConvertTo-Json'
Write-host "The number is $($response.result.number)"
This works.
Other useful reference:
Powershell ServiceNow API

Related

Teams Webhook error: Invoke-RestMethod: Bad payload received by generic incoming webhook

I'm using configured Teams webhook in my Powershell script and keep encountering the mentioned error message. What's strange, is that this exact method of configuring Webhook worked a few months ago on a different script.
Here's what I'm trying to do:
#Set URI of the Teams channel Webhook
$URI = 'https:....'
#Define Rest Method Parameters for the Teams Webhook sending
$RestMethodParameters = #{
"URI" = $URI
"Method" = 'POST'
"Body" = $null
"ContentType" = 'application/json'
}
$JSONBody = #{
"#type" = "MessageCard"
"#context" = "http://schema.org/extensions"
"themeColor" = '0078D7'
}
#Adding text to title and body
$JSONBody += #{
"title" = "'costReport-func' Function for connecting AzAccount has failed"
"text" = "Function failed at connection to AzAccount step."
}
#Sending the message to Teams
($RestMethodParameters).Body += ConvertTo-Json $JSONBody
Invoke-RestMethod #RestMethodParameters
And with this I'm getting "Bad payload received by generic incoming webhook." error message. What is causing the issue here?
Update: Microsoft has released a preview version (2.1.0) of the Teams PowerShell module which works properly with modern authentication. It’s likely that this version will be pushed through to general availability quite quickly.
Please go through this link for more information.

How to using powershell, download and save the recieved user photo from microsoft Graph API

$apiUrl = "https://graph.microsoft.com/v1.0/me/photo/$value"
Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $apiUrl -Method Get
This gets me a response like below:
#odata.context : https://graph.microsoft.com/v1.0/$metadata#users('48db12f7-f809-4ff0-a55c-ab05e135c092')/photo/$entity
#odata.mediaContentType : image/jpeg
#odata.mediaEtag : "D4976167"
id : 360X360
height : 360
width : 360
i am not getting a way on how to go for next step.
my objective is to:
1. Save the photo to a variable ( i believe as a byte array). or
2. Or get the photo directly downloaded to a .jpeg file.
Finally from another question in here i could figure out the problem with my code.
The solution was to escape the $value at the end of the url with `$value

Powershell handling of System.Net.WebException

Having almost mastered using Powershell Invoke-WebRequest I'm now embarking on trying to get control of exception errors
In this first piece of code I've got to handle the exceptions returned from the web service ok. You can see a 400 code is returned along with a Message description and a detailed message.
Try {
$what = Invoke-WebRequest -Uri $GOODURL -Method Post -Body $RequestBody -ContentType $ContentType
}
catch [System.Net.WebException] {
$Request = $_.Exception
Write-host "Exception caught: $Request"
$crap = ($_.Exception.Response.StatusCode.value__ ).ToString().Trim();
Write-Output $crap;
$crapMessage = ($_.Exception.Message).ToString().Trim();
Write-Output $crapMessage;
$crapdescription = ($_.ErrorDetails.Message).ToString().Trim();
Write-Output $crapdescription;
}
Output returned. Nice!
Exception caught: System.Net.WebException: The remote server returned an error: (400) Bad Request.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
400
The remote server returned an error: (400) Bad Request.
Modus.queueFailed Could not queue message http://schemas.xmlsoap.org/soap/actor/next
That's very cool, however as part of my testing I wanted simulate connection errors, so I fed the script an invalid URI and immediately my error handling in the above code crashed.
Specifically, the invalid URI fell over on the "$_.Exception.Response.StatusCode.value__" and "$_.ErrorDetails.Message" presumably because they don't exist in the System.Net.WebException object returned
So, I took them out as a test and sure enough it works with the invalid URL as expected as below
Try {
$what = Invoke-WebRequest -Uri $BADURL -Method Post -Body $RequestBody -ContentType $ContentType
}
catch [System.Net.WebException] {
$Request = $_.Exception
Write-host "Exception caught: $Request"
$crapMessage = ($_.Exception.Message).ToString().Trim();
Write-Output $crapMessage;
}
And I get this (also nice)
Exception caught: System.Net.WebException: The remote name could not be resolved: 'gateway.zzzzsonicmobile.com'
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.SetRequestContent(WebRequest request, String content)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
The remote name could not be resolved: 'gateway.zzzzsonybile.com'
Trouble is, the first example gets everything I want from the exception object but won't work with an invalid URL. The second example handles the invalid URL (connection errors), but I can't figure out how to get hold of the 400 StatusCode and the ErrorDetails.Message
I would really like to do that, if at all possible.
Is there a way of setting this up to handle all exception handling..?
Any help, much appreciated..!
I think you're probably only seeing an issue because you're trying to do the .ToString().Trim() methods on those properties when they don't exist. I'm not sure doing those methods even adds a lot of value, so I'd be tempted to just remove them.
Alternatively, you could put If blocks around them so that they are only output if they have value:
If ($_.Exception.Response.StatusCode.value__) {
$crap = ($_.Exception.Response.StatusCode.value__ ).ToString().Trim();
Write-Output $crap;
}
If ($_.Exception.Message) {
$crapMessage = ($_.Exception.Message).ToString().Trim();
Write-Output $crapMessage;
}

Can ExtensionDataService be used from a PowerShell-based VSTS build task?

I have created a PowerShell-based build task for Visual Studio Team Services (formerly Visual Studio Online). I have implemented the majority of the functionality I need, but for the last bit of functionality I need to be able to persist a small amount of data between builds.
The ExtensionDataService seems like exactly what I want (in particular, the setValue and getValue methods), but the documentation and examples I have found are for node.js-based build tasks:
VSS.getService(VSS.ServiceIds.ExtensionData).then(function(dataService) {
// Set a user-scoped preference
dataService.setValue("pref1", 12345, {scopeType: "User"}).then(function(value) {
console.log("User preference value is " + value);
});
The previous page also has a partial example of calling the REST API, but I have gotten 404 errors when trying to use it to either save or retrieve values:
GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents
{
"id": "myKey",
"__etag": -1,
"value": "myValue"
}
Can PowerShell be used to access the ExtensionDataService, either by using a library or by calling the REST API directly?
You can call REST API through PowerShell.
Set value (Put request):
https://[vsts name].extmgmt.visualstudio.com/_apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extension id}/Data/Scopes/User/Me/Collections/%24settings/Documents?api-version=3.1-preview.1
Body (Content-Type:application/json)
{
"id": "myKey",
"__etag": -1,
"value": "myValue"
}
Get value (Get request):
https://[vsts name].extmgmt.visualstudio.com/_apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extension id}/Data/Scopes/User/Me/Collections/%24settings/Documents/mykey?api-version=3.1-preview.1
The publisher name and extension id could be get in package json file (e.g. vss-extension.json)
Regarding call REST API through PowerShell, you can refer to this article: Calling VSTS APIs with PowerShell
Simple sample to call REST API:
Param(
[string]$vstsAccount = "<VSTS-ACCOUNT-NAME>",
[string]$projectName = "<PROJECT-NAME>",
[string]$buildNumber = "<BUILD-NUMBER>",
[string]$keepForever = "true",
[string]$user = "",
[string]$token = "<PERSONAL-ACCESS-TOKEN>"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$uri = "https://$($vstsAccount).visualstudio.com/DefaultCollection/$($projectName)/_apis/build/builds?api-version=2.0&buildNumber=$($buildNumber)"
$result = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
PowerShell script to get the base URL:
Function GetURL{
param([string]$url)
$regex=New-Object System.Text.RegularExpressions.Regex("https:\/\/(.*).visualstudio.com")
$match=$regex.Match($url)
if($match.Success)
{
$vstsAccount=$match.Groups[1]
$resultURL="https://$vstsAccount.extmgmt.visualstudio.com"
}
}
GetURL "https://codetiger.visualstudio.com/"

Can't turn curl into Invoke-WebRequest

I've got a curl command that works great and I'm trying to turn it into a PowerShell Invoke-WebRequest call.
Here's the working curl with the multipart POST data:
curl -X POST "http://domain.com/admin/batchOrder/processBatch"
-F "ordersFile=#c:\temp\Sample_Auto_Order_Input_File.xml"
-F "psid=3002010250764"
-F "recipients[0]=astraljack#example.com"
And here's where I'm trying to do it via Invoke-WebRequest. Based on what I've read, I need to create a hash table of name-value pairs. I feel like I should be creating the hash table just like I do the multipart POST data above.
$form.clear()
$form.Add("ordersFile", "c:\temp\Sample_Auto_Order_Input_File.xml")
$form.Add("psid", "3002010250764")
$form.Add("recipients[0]", "astraljack#example.com")
$form
Then I can call Invoke-WebRequest.
Invoke-WebRequest http://domain.com/admin/batchOrder/processBatch -Body $form -Method Post
This fails with a 400 Bad Request. To be clear, I've never gotten this Invoke-WebRequest to work so I could be way off base here. I'm not even sure where I can look for a better error msg.
If it helps, the contents of the exception are
IsMutuallyAuthenticated : False
Cookies : {}
Headers : {Connection, Transfer-Encoding, Content-Type, Date...}
SupportsHeaders : True
ContentLength : -1
ContentEncoding :
ContentType : application/json;charset=UTF-8
CharacterSet : UTF-8
Server : Apache
LastModified : 5/12/2014 10:23:19 AM
StatusCode : BadRequest
StatusDescription : Bad Request
ProtocolVersion : 1.1
ResponseUri : http://domain.com/admin/batchOrder/processBatch
Method : POST
IsFromCache : False
The best way to solve the problem is to go download Fiddler and then capture the CURL request. Inspect its RAW request. Then do the same for the Invoke-WebRequest command. See what is different and that should tell you what you need to tweak with Invoke-WebRequest.
The #filepath syntax in curl actually reads the contents of the file into the parameter, but in your PowerShell version you are just setting the value of ordersFile to the filename. Try:
$form.clear()
$form.Add("ordersFile", (get-content "c:\temp\Sample_Auto_Order_Input_File.xml"))
$form.Add("psid", "3002010250764")
$form.Add("recipients[0]", "astraljack#example.com")
$form
Also, you may need to add -ContentType "application/x-www-form-urlencoded" to your Invoke-WebRequest call.
`
I know this is an old question, but I figured since it was still unanswered, I'd throw in my two cents. Here's how I would do this:
$form = #{
'ordersFile' = 'c:\temp\Sample_Auto_Order_Input_File.xml'
'psid' = '3002010250764'
'recipients[0]' = 'astraljack#example.com'
}
Invoke-WebRequest -Uri "http://domain.com/admin/batchOrder/processBatch" -Body $form -Method Post