Add the WinRT assembly, and load the appropriate WinRT types
February 21, 2021 · View on GitHub
using namespace Windows.Storage using namespace Windows.Graphics.Imaging using namespace System.IO.WindowsRuntimeStreamExtensions using namespace System.IO.WindowsRuntimeStreamExtensions using namespace System.Text using namespace System.Text.Json
Add the WinRT assembly, and load the appropriate WinRT types
Add-Type -AssemblyName System.Runtime.WindowsRuntime Add-Type -AssemblyName System.Runtime.Serialization
null = [Windows.Media.Ocr.OcrEngine, Windows.Foundation, ContentType = WindowsRuntime] null = [Windows.Graphics.Imaging.SoftwareBitmap, Windows.Foundation, ContentType = WindowsRuntime] $null = [Windows.Storage.Streams.RandomAccessStream, Windows.Storage.Streams, ContentType = WindowsRuntime]
[Windows.Media.Ocr.OcrEngine]::AvailableRecognizerLanguages
$ocrEngine = [Windows.Media.Ocr.OcrEngine]::TryCreateFromLanguage("en")
PowerShell doesn't have built-in support for Async operations,
but all the WinRT methods are Async.
This function wraps a way to call those methods, and wait for their results.
getAwaiterBaseMethod = [WindowsRuntimeSystemExtensions].GetMember('GetAwaiter'). Where({ PSItem.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' }, 'First')[0]
Function Await { param(ResultType)
$getAwaiterBaseMethod.
MakeGenericMethod($ResultType).
Invoke($null, @($AsyncTask)).
GetResult()
}
$http = [System.Net.HttpListener]::new()
Hostname and port to listen on
$http.Prefixes.Add("http://+:80/")
Start the Http Server
$http.Start()
Add-Type -AssemblyName System.Web
Log ready message to terminal
if (http.IsListening) { write-host "HTTP Server Ready! " -f 'black' -b 'gre' write-host "($http.Prefixes)" -f 'y' }
while (http.IsListening) { # Get Request Url # When a request is made in a web browser the GetContext() method will return a request object # Our route examples below will use the request object properties to decide how to respond context = context.Request.HttpMethod -eq 'GET') { buffer = [System.Text.Encoding]::UTF8.GetBytes("<input type=file onchange=""fetch('', {method: 'POST', body: this.files[0]}).then(r=>r.json()).then(console.log)"">") buffer, 0, Context.Response.Close() }
if ($context.Request.HttpMethod -eq 'POST') {
# We can log the request to the terminal
write-host "$($context.Request.UserHostAddress) => $($context.Request.Url)" -f 'mag'
$memStream = [System.IO.MemoryStream]::new()
$context.Request.InputStream.CopyTo($memStream)
$params = @{
AsyncTask = [BitmapDecoder]::CreateAsync([System.IO.WindowsRuntimeStreamExtensions]::AsRandomAccessStream($memStream))
ResultType = [BitmapDecoder]
}
$bitmapDecoder = Await @params
$params = @{
AsyncTask = $bitmapDecoder.GetSoftwareBitmapAsync()
ResultType = [SoftwareBitmap]
}
$softwareBitmap = Await @params
# Run the OCR
$result = Await $ocrEngine.RecognizeAsync($softwareBitmap) ([Windows.Media.Ocr.OcrResult])
$Context.Response.ContentType = "application/json"
$serialized = $result | ConvertTo-Json -Depth 5 -Compress
$buffer = [System.Text.Encoding]::UTF8.GetBytes($serialized)
$context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
$Context.Response.Close()
}
}