Powershell - Loop through folder, Get Contents and post to SOAP - powershell

I am trying to loop through a folder, grab all files, read their contents then post each file content individually to SOAP.
This is how I would do it, but PowerShell returns an error.
Invoke-Webrequest : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
Below is my code:
$dataAPI = Get-ChildItem 'C:\Users\..\Output'
$uri = 'http://server-name.com:8080/name/name2'
ForEach ($Item in $dataAPI) {
Get-Content $Item.FullName | Invoke-Webrequest -Headers #{"Content-Type" = "text/xml;charset=UTF-8"; "SOAPAction" = "http://server-name.com:8080/name/name2"} -Method 'POST' -Body $dataAPI -Uri $uri -UseDefaultCredential
}
I am not really sure where I should place the Invoke-WebRequest...
Any help would be appreciated. Thanks.

Continuing from my comments,
Add switch -Raw to the Get-Content call to receive a single multiline string instead of an array of lines
Add switch -File to the Get-ChildItem call to ensure you will only deal with files in the loop, not directories too
Try
# if all files you need have a common extension, add `-Filter '*.xml'` to below line
# '*.xml' is just an example here..
$files = Get-ChildItem -Path 'C:\Users\Gabriel\Output' -File
$uri = 'http://server-name.com:8080/name/name2'
$header = #{"Content-Type" = "text/xml;charset=UTF-8"; "SOAPAction" = "http://server-name.com:8080/name/name2"}
foreach ($Item in $files) {
$content = Get-Content $Item.FullName -Raw
Invoke-Webrequest -Headers $header -Method 'POST' -Body $content -Uri $uri -UseDefaultCredential
}

Related

Trying to use the "SetDeviceName" action with Microsoft Graph

Trying to do a bulk rename of device when they haven't been logged on for a long time.
I have managed to gather the information I need it and pipe it, so it comes out correctly.
But for some reason, I get Bad request and my formating is some how wrong, but can't figure out what. Tried every type of modification to the URI, but no luck.
This should work according to Microsoft's Doc about SetDevicename action
$date = (Get-date (Get-date).adddays(-316) -format "yyy-MM-ddTHH:mm:ssZ")
$devices | where {$_.lastSyncDateTime -le $date} | ForEach-Object {
$newname = "Test-$($_.Devicename)"
$deviceID = "$($_.ID)"
$URI = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$deviceID/setDeviceName"
$Body = #{ "deviceName" = "$NewName" } | ConvertTo-Json
$Method = "POST"
Invoke-RestMethod -Uri $URI -Method $Method -Headers $appauthToken -body $body -ContentType "application/json"
}
Any Idea what I'm doing wrong?
There is another method of renaming of bulk devices:
Document reference: https://learn.microsoft.com/en-us/mem/intune/remote-actions/device-rename#bulk-rename-devices.

How to make a POST request with file content via Powershell

I want to make a post call with powershell which should contain the file content as body, so I try to use Invoke-Webrequest.
When I make the call like this, there is no data on the server side. I can see that on the server where the HttpServletRequest.getInputStream is null, any idea what is the problem?
$FilePath = '.\foobar.txt'
$fileContent = Get-Content -Path $FilePath -Encoding Byte
Write-host $fileContent
$Response = Invoke-WebRequest -Body $fileContent -Method 'POST' -Uri 'http://myAddress'
tldr: You need to add the Parameter -ContentType "application/octet-stream"
First of all you should replace Get-Content -Path $FilePath -Encoding Byte with [System.IO.File]::ReadAllBytes($FilePath) as it is way faster. This is also the reason why I do not suggest to use the -InFile Parameter as it internaly also uses that slow, inperformant Get-Content Method.
In combination you propably also need to add -ContentType "application/octet-stream" otherwise the Body is not serialised as the raw byte array.
So in the end it should look something like this:
$FilePath = '.\foobar.txt'
$fileContent = [System.IO.File]::ReadAllBytes($FilePath)
$Response = Invoke-WebRequest -Body $fileContent -Method 'POST' -Uri 'http://myAddress' -ContentType 'application/octet-stream'

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.

Adding Powershell jobs to retrieve in parallel from paginated rest API

I've spent perhaps over 30 hours trying to add various methods to implement parallel processing to my API call. The most obvious would be to place the code into a job, but I'm having no luck. Any ideas?
Start-Transcript -Path "$PSScriptRoot\Errorlog.txt"
$WondeObjectsArray = Import-CSV $PSScriptRoot\WondeID.csv
$EndpointObjectArray = Import-CSV $PSScriptRoot\Endpoints.csv
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("REDACTED", "REDACTED")
# School loop
Foreach ($object in $WondeObjectsArray) {
$SchoolName = $object.School
$TrustName = $object.Trust
$WondeID = $object."Wonde ID"
# Create data structure
If(!(test-path "$PSScriptRoot\$TrustName"))
{New-Item -Path "$PSScriptRoot\$TrustName" -ItemType Directory}
If(!(test-path "$PSScriptRoot\$TrustName\$SchoolName"))
{New-Item -Path "$PSScriptRoot\$TrustName\$SchoolName" -ItemType Directory}
# Endpoint request loop
foreach($Eobject in $EndpointObjectArray){
$JsonName = $Eobject.JsonName
$Table = $Eobject.Table
$Method = $Eobject.Url_Method
# First response
$response = Invoke-RestMethod "https://api.wonde.com/v1.0/schools/$WondeID/$Table$Method&$Page" -Method 'GET' -Headers $headers -Body $body
$concat = $response.data
#Pagination loop
While ($response.meta.pagination.next){
$response = Invoke-RestMethod $response.meta.Pagination.next -Method 'GET' -Headers $headers -Body $Body
$concat = $concat + $response.data
} #pagination loop end
# Concatenate completed request
$concat | ConvertTo-Json | Out-File "$PSScriptRoot\$TrustName\$SchoolName\$JsonName.json"
} # Endpoint request loop end
} # School loop end
Stop-Transcript
Never mind, I figured it out. I turned the code that I wanted to run in parallel into a scriptblock, Passed it the parameters by using param () And in the start job line I included my variables in -ArgumentList.
My issue was actually that when you start a new job it changes the script file path to C:/, when I was passing $PSScriptRoot rather than the default file location.
Start-Transcript -Path "$PSScriptRoot\Errorlog.txt"
$PathRoot = $PSScriptRoot
$WondeObjectsArray = Import-CSV $PSScriptRoot\WondeID.csv
$EndpointObjectArray = Import-CSV $PSScriptRoot\Endpoints.csv
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("REDACTED", "REDACTED")
# School loop
Foreach ($object in $WondeObjectsArray) {
$SchoolName = $object.School
$TrustName = $object.Trust
$WondeID = $object."Wonde ID"
# Create data structure
If(!(test-path "$PSScriptRoot\$TrustName"))
{New-Item -Path "$PSScriptRoot\$TrustName" -ItemType Directory}
If(!(test-path "$PSScriptRoot\$TrustName\$SchoolName"))
{New-Item -Path "$PSScriptRoot\$TrustName\$SchoolName" -ItemType Directory}
# Endpoint request loop
foreach ($Eobject in $EndpointObjectArray){
$JsonName = $Eobject.JsonName
$Table = $Eobject.Table
$Method = $Eobject.Url_Method
$scriptblock = {
param ($WondeID, $Table, $Method, $headers, $trustName, $SchoolName, $JsonName, $PathRoot)
write-host "$TrustName : $SchoolName : $JsonName is complete!"
# First response
$response = Invoke-RestMethod "https://api.wonde.com/v1.0/schools/$WondeID/$Table$Method&$Page" -Method 'GET' -Headers $headers -Body $body
$concat = $response.data
#Pagination loop
While ($response.meta.pagination.next){
$response = Invoke-RestMethod $response.meta.Pagination.next -Method 'GET' -Headers $headers -Body $Body
$concat = $concat + $response.data
} #pagination loop end
# Concatenate completed request
$concat | ConvertTo-Json | Out-File "$PathRoot\$TrustName\$SchoolName\$JsonName.json"
}
Start-Job $scriptblock -Name "$SchoolName&$JsonName" -ArgumentList $WondeID, $Table, $Method, $headers, $trustName, $SchoolName, $JsonName, $PathRoot
} # Endpoint request loop end
Get-Job | Wait-Job | Receive-Job
Get-Job | Remove-Job
} # School loop end
Stop-Transcript

Make Invoke-WebRequest loop through each URL it finds

I'm new to PowerShell and I'm trying to make the Invoke-WebRequest cmdlet loop through each url the webscrape finds. All I have so far is this :
$site = Invoke-WebRequest -UseBasicParsing -Uri www.example.com/examples
$site.Links | Out-GridView
Any help would be appreciated!
Add your links to a comma separated list.
Split the list and loop each item.
Request each item.
As below:
$option = [System.StringSplitOptions]::RemoveEmptyEntries
$urlCollection = "link1,link2,link3"
$separator = ","
$urlList = $urlCollection.Split($separator, $option)
foreach ($url in $urlList) {
Invoke-WebRequest $url
# Give feedback on how far we are
Write-Host ("Initiated request for {0}" -f $url)
}