[PowerShell] How to Create Simple Class

As a C# developer, I think that I should need to know how to create a class in PowerShell. Since Windows PowerShell 5.0, it adds the ability to create a class. With a class, we could do the coding more like C# (this is a good news to a C# developer like me, lol). We could create methods properties, enums, and other things to Class in PowerShell.

The first thing we need is, use the Class keyword. This is a sample on it,

Class Vehicle {

}

Within the brace, we could add our items in it. Be careful when we create object in PowerShell. The Windows PowerShell automatic type system works remarkably. it allow us create any variable without specify its type. Everything will simply be a System.Object. if you have a string, an int, or a DataTime object, the best practice (or you must) is to specify that type so that things will work well.

Because I am creating a class for a vehicle, I could create something like, Vehicle Registration Plate, Model, Year, Number of Doors, Number of Wheels, Seating Capacity, Engine Displacement, Engine Max Torque….etc

[String]$RegPlate
[int]$NoOfDoors
[datetime]$Year
[String]$Model
[int]$numberOfWheels = 4
[int]$numberOfDoors = 5

I can then use the New-Object cmdlet to create an instance of the Vehicle class,
$myVehicle = New-Object Vehicle

I can now get the default values of all variables (class properties) in $myVehicle.

Now I can simply assign values to $myVehicle,

Now I could see all the updated values,

That is how you create a simple class in Windows PowerShell 5.0. Let’s talk about adding more stuff to the class later. Hope you enjoy and learn the PowerShell with me.

 

Next version of Visual Studio, “VS2022”, Public Preview will be released this summer

Amanda Silver, CVP of Product-Developer Division announce that the next version of Visual Studio will be called VS2022. And its Public Preview will be available to download this summer. Let me do a short summary about the changes and share with you.

  • IDE will be running faster
    • VS2022 will be in 64-bit
  • New Design
    • Better clarity, legibility, and contrast
    • Cascadia Code
    • Personalization, you could make your own “IDE” just right for you.
  • Develop Modern Apps
    • Azure, better integration with GitHub for CI/CD, and with Azure
    • VS2022 will have full support for .NET 6.
    • .NET Multi-platform App UI (MAUI) will be included. You could build client apps on Windows, Android, macOS, iOS. You could also use ASP.NET Blazor for Web App.
  • Innovation 
    • Performance improved for Diagnostics and Debugging
    • Using Live Share to enable Real-Time Collaboration
    • AI IntelliCode engine provide more and deeper integrations into your daily workflows.
    • New support for Git and GitHub.
    • Improved Code Search
    • refreshing VS for Mac

Well, let’s wait and test this new VS2022 in the coming summer time.  Meanwhile, you could read from the original post here.

[PowerShell] How to Join Data in faster way?

Last week, one of Hong Kong ex-MVP asked a question to our ex-MVPs private group. He has a PowerShell script and 2 csv data files. Both csv data file has a common column and he could like to join them and combine into a single csv data file. his code  like this,

Get csv1 | ForEach-Object -Parallel Where-Object $_.id -match $csv2.id

He complaints that it will take a very long time to handle large amount of data. And there are some comments,

  • change from -match to -eq
  • try to use hash
  • something about add-member
    …etc

From me, I just say, why not do it with LINQ? So I try to write 2 PowerShell scripts, one will be using traditional PowerShell command and another one will be using LINQ.

First, in my testing code, I will try to create 2 arrays and then generate some data into it. Here is my code,

#Create empty arrays
$datasetA = @()
$datasetB = @()
#Initialize "status" arrays to pull random values from
$genderArray = @('Male','Female','Decline to Answer')
#Loop 10 times to populate our separate datasets
1..10 | Foreach-Object {
    #Set the name with the current iteration attached
    $thisName = "Person_$_" 
    #Create an object with the name property and a random gender
    $rowA = @{
        Name = $thisName
        Gender = $genderArray[(Get-Random -Minimum 0 -Maximum 3)]
    }
    $datasetA += New-Object -Type PSObject -Property $rowA
    #Create a second object with the same name and a random age
    $rowB = @{
        Name = $thisName
        Age = Get-Random -Minimum 1 -Maximum 120
    }
    $datasetB += New-Object -Type PSObject -Property $rowB
}

It will create 2 array, each contains 10 rows. The common column will be the Name column.  One array contains a Gender column, another array contains Age column. Simple data, right?

In traditional PowerShell, we might iterate through one of the arrays while doing a filter on the second array. And then either add property members to the first array or create a new objects with a combination of properties from both arrays. My code then will be something like this:

$joinedDataset =@()
foreach($rowA in $datasetA) {
    $rowB = $datasetB | Where-Object Name -eq $rowA.Name
    $joinedRow = @{
        Name = $rowA.Name
        Gender = $rowA.Gender
        Age = $rowB.Age
    }
    $joinedDataset += New-Object -Type PSObject -Property $joinedRow
}

It works fine and it only takes 32.6 milliseconds to complete. But if I increase the iterate number from 10 to 100, it then takes 174.1 milliseconds. And then 7025.7 milliseconds for 1000 records, 638429.8 milliseconds (10 min 38 sec) for 10000 records.
(P.S., it include the time it take to generate iteration arrays)

Now, let’s do the same with using LINQ:

$linqJoinedDataset = [System.Linq.Enumerable]::Join(
    $datasetA,
    $datasetB,
    [System.Func[Object,string]] {param ($x);$x.Name},
    [System.Func[Object,string]]{param ($y);$y.Name},
    [System.Func[Object,Object,Object]]{
        param ($x,$y);
        New-Object -TypeName PSObject -Property @{
        Name = $x.Name;
        Gender = $x.Gender;
        Age = $y.Age}
    }
)

$OutputArray = [System.Linq.Enumerable]::ToArray($linqJoinedDataset)

The time it takes will be as following,

  • 37.8 milliseconds for 10 records
  • 79.8 milliseconds for 100 records
  • 809.4 milliseconds for 1000 records
  • 16026.2 milliseconds for 10000 records

In this code, I am calling the Join method on System.Linq.Enumerable and then passing it with 5 parameters,

  1. The first dataset that it is going to join
  2. The second dataset that it joins
  3. The delegate which defines the key to compare against on the first dataset
  4. The delegate which defines the key to compare against on the second dataset
  5. Finally, we pass in the delegate which defines what the output should be

Because the Join method is a Deferred Execution. it is not actually joining the data at that time. It is just building an expression tree which defines the relational algebra needed to perform the join. So the above example code, I will need to call “ToArray()”, so that the execution could start. If you have any further codes that you will handle with the result data, you could skip the “ToArray()” code. For example, calling like this,

$linqJoinedDataset.Where({($_.Age -gt 20) -and ($_.Gender -eq "Male")})

Then the join query would execute at that time and then “Where()” would filter down to just the objects that matching the conditions.

Here is the table on the execution time on each way,

# iterate Traditional PS LINQ
10 32.6 37.8
100 174.1 79.8
1000 7025.7 809.4
1000 638429.8 16026.2

So I can say, LINQ saved more than 40 times of timing to complete the join. With this figure, I am sure that you will love to update and use LINQ if you need a join operation on data.

Hope this blog could help you to get a faster execution script in PowerShell.

Enable TLS 1.2 or above on your ASP.NET Web App or WebAPI

The Transport Layer Security (TLS) 1.2 is a stadnard that provides security improvements over previous versions. More and more thrid-party APIs were configured to disable any requests from clients that were using TLS 1.0/1.1. So if your ASP.NET Web App or WebAPI Services Web Site will need to update to TLS 1.2 as well if your ASP.NET Web App or WebAPI Services Web Site has some calls to the third-party APIs, otherwise they will only return empty responses.

You could disable TLS 1.0/1.1 and only enable TLS 1.2 in your Web Server or in Azure, so that your hosting environments will no longer accept requests from earlier version of TLS.

But what happens on your application (ASP.NET Web App or WebAPI Services)? Depend on what version of .NET framework your project usrs will dicate the possible solutions available to you.

  1. If your project compiles against .NET Framework 4.7 or above, then you don’t have to do anything.
  2. If your project has been developed in a earlier version of .NET Framework, then you could either
    1. Recompile your project using .NET Framework 4.7 or above
    2. If recompiling is not an option, then you will have to update your .config file as below,
<configuration>
  <runtime>
    <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"/>
  </runtime>
  <system.web>
    <compilation targetFramework="x.y.z" />
    <httpRuntime targetFramework="x.y.z" /> 
  </system.web>
</configuration>

It is preferred that x.y.z are the same. So if your application is 4.6.2, then replacing x.y.z into 4.6.2.

Microsoft also has post a useful document on describing the best pratices to TLS 1.2. It will be great if you could read them all and understand them in order to fully secure your application(ASP.NET Web App or WebAPI Services).
https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls

 

Bot Framework Composer helps you build bot with GUI and “No Code”

Do you know that Microsoft has released a Bot Framework Composer. Using the Bot Framework Composer presents some advantages when compared to creating a bot with the SDK and coding.

  • Use of Adaptive Dialogs allow for Language Generation (LG), which can simplify interruption handling and give bots character.
  • Visual design surface in Composer eliminates the need for boilerplate code and makes bot development more accessible.
  • Time saved with fewer steps to set up your environment.
  • The Composer bot projects contain reusable assets in the form of JSON and Markdown files that can be bundled and packaged with a bot’s source code. The files can be checked into source control systems and deployed along with code updates, such as dialogs, language understanding (LU) training data, and message templates.

It is available as a Desktop application as well as a web-based component. You will also need to install the Bot Framework Emulator and ensure that you have .NET Core SDK 3.1 or later installed as well.

And this Bot Framework Composer is also one of the key components in the exam if you are going to take AI-102: Designing and Implementing a Microsoft Azure AI Solution (the replacement exam of AI-100 after 30th June 2021).

BotComposer_home