Pretend to write in C #, but only in Powershell



Powershell is a handy API built on .net. Powershell allows users to write scripts without the need for programming while getting similar results. What happens at the KDVP, the author will explain later in the text. Now we urgently need to pretend that we are programming in C #.



TL; DR: Postman is not needed if Powershell is available. But first you need to go from afar.



Making a simple class



I heard that cool programmers do everything through classes and their methods.

Since PowerShell allows it, let me show you how you can add 1 + 1 while pretending to be programming.



class ClassName {
 
    [string] Sum ($A, $B) {
       
        $Result = $A + $B
        return $Result
    }
}


Here is our ClassName class and its Sum method. An instance of a class can be called in exactly the same way as in real programming languages.



$NewClass = [ClassName]::new()
$NewClass.Sum(1, 1)


We create a new instance of the class and call the method, everything is simple.



Is there a Void in Powershell



When writing complex scripts, the same question arose from the author. How do I make a function that will be Void?



They say that you can do this:



Get-Date | Out-Null


However, | Out-Null also suppresses all Verbose, ErrorAction and does not work with Invoke-Command.



If you need a function with [Void] - make a new class, there is no other way out.



class ClassName {
 
    # 
    [void] Start () {
        #       .
        $q = [ClassName]::new()
        $q.GetDate()
    }
 
    #    
    [void] GetDate () {
        #        .Net
	  # ,   
        $Result = [DateTime]::UtcNow.ToString()
        Write-Host $Result
    }
}


It is impossible to make a method private inside one class, or call one of the class methods inside the same class in PowerShell, so you have to sculpt such calls.

A class constructor was added to the example to understand the limitations of the language, and such code should not be generally written.



This is how we managed to avoid drowning Verbose, while making a function with Void.



List of class methods



Let's say you need to make a program, perhaps even in a language that you don't know. You know there is a class, but its methods are poorly documented.



You can list all the methods of the class of interest as follows:



# ,   
$Love = [ClassName]::new()
 
#        .
foreach ($i in $Love | Get-Member -MemberType Method | Select-Object name) {
    [array]$array += $i.Name
}
 
#  ,  .
$Array | ForEach-Object {
    $Love.$_()
}


We send HTTP requests with a script (we justify KDPV)



With classes, we can represent data and convert this data into different formats. For example, we need to send a POST request to a website in JSON format.



First, we make a data model and populate the data into a new instance.



#      
class DataModel {
    $Data
    $TimeStamp
}
 
#  
$i = [DataModel]::new()
 
# 
$i.Data = "My Message in string"
$i.TimeStamp = Get-Date


This is what the class instance looks like after filling:



PS C:\> $i
 
Data                 TimeStamp
----                 ---------
My Message in string 30.07.2020 5:51:56


Then this instance can be converted to XML or JSON or even a SQL query. Let's dwell on JSON:



#   JSON
$Request = $i | ConvertTo-Json


This is what the JSON looks like after converting it:



PS C:\> $Request
{
  "Data": "My Message in string",
  "TimeStamp": "2020-07-30T05:51:56.6588729+03:00"
}


And we send:



# JSON
Invoke-WebRequest localhost -Body $Request -Method Post -UseBasicParsing


If you need to send the same JSON file 24/7, you can save it as a file and send it from the file. For example, let's take this same $ Request.



#     JSON  
$Request | Set-Content C:\Users\User\Desktop\YourRequest.json
 
#     JSON
Invoke-WebRequest localhost -Body (Get-Content C:\Users\User\Desktop\YourRequest.json) -Method Post -UseBasicParsing


We receive HTTP requests with a script (we justify KDPV 2)



The author hates Postman, why would anyone need Postman when they have hands and PowerShell? (The author is biased towards this program and his dislike is not justified by anything.)

We will do our alternative using System.Net.HttpListener, that is, we will now start a real web server from a script.



#   
$http = [System.Net.HttpListener]::new()
 
# HTTP .     
$http.Prefixes.Add("http:/localhost/")
$http.Prefixes.Add("http://127.0.0.1/")
 
#  
$http.Start()
 
 
$http.Close()


This is how the class starts.



An instance of the class was created and its process started, we can listen to its output. The output is presented as System.Net.HttpListener.GetContext. In this example, we only accept and convert a POST request.



while ($http.IsListening) {
 
    #GetContext       HttpListener
    $context = $http.GetContext()
 
    #     Request.HttpMethod 
    if ($context.Request.HttpMethod -eq 'POST') {
 
        #    GetContext
        #      
        [System.IO.StreamReader]::new($context.Request.InputStream).ReadToEnd() | ForEach-Object {
            
            #  System.Web.HttpUtility  urlDecore,     
            $DecodedContent = [System.Web.HttpUtility]::UrlDecode($_)
 
            #      
            $ConvertedForm = $DecodedContent | ConvertFrom-Json -ErrorAction SilentlyContinue
 
            #C   
            $ConvertedForm | Format-Table
           
        }
    }
} 


Ready script



With this script, you can accept requests:



#   
$http = [System.Net.HttpListener]::new()
 
# HTTP .     
$http.Prefixes.Add("http://localhost/")
$http.Prefixes.Add("http://127.0.0.1/")



#  
$http.Start()
 
if ($http.IsListening) {
    Write-Host " "
}
 
while ($http.IsListening) {
 
    #GetContext       HttpListener
    $context = $http.GetContext()
 
    #     Request.HttpMethod 
    if ($context.Request.HttpMethod -eq 'POST') {
 
        #    GetContext
        #      
        [System.IO.StreamReader]::new($context.Request.InputStream).ReadToEnd() | ForEach-Object {
            
            #  System.Web.HttpUtility  urlDecore,     
            $DecodedContent = [System.Web.HttpUtility]::UrlDecode($_)
 
            #      
            $ConvertedForm = $DecodedContent | ConvertFrom-Json -ErrorAction SilentlyContinue
 
            #C   
            $ConvertedForm | Format-Table
           
        }
 
        #  200 OK   .
        $context.Response.Headers.Add("Content-Type", "text/plain")
        $context.Response.StatusCode = 200
        $ResponseBuffer = [System.Text.Encoding]::UTF8.GetBytes("")
        $context.Response.ContentLength64 = $ResponseBuffer.Length
        $context.Response.OutputStream.Write($ResponseBuffer, 0, $ResponseBuffer.Length)
        $context.Response.Close()
 
    }
    #C   
    $http.Close()
    break
}


The data will be automatically converted from JSON and output to the terminal.



The author hopes that you throw out Postman, as well as GIT with a GUI.






All Articles