Desktop and Application Streaming

Create a PowerShell-Based dynamic app provider in Amazon AppStream 2.0

The Amazon AppStream 2.0 dynamic application framework provides API operations within an AppStream 2.0 streaming instance that you can use to build a dynamic app provider. Dynamic app providers use these API operations to modify the catalog of applications that your users can access in real time. For example, you can add applications to the catalog based on Active Directory domain group membership, or other business logic. AppStream 2.0 uses Apache Thrift (https://thrift.apache.org) to define the inter-process messages used in the API.

Apache Thrift lets you build clients and servers by defining the data types and service interfaces in a simple definition file. You can use those definitions to generate code files in any number of programing languages.

This post describes how to create .NET dynamic-link libraries (DLLs) from the AppStream 2.0 dynamic application framework Thrift definition files. After you create the DLLs, you can use it with a PowerShell dynamic application framework client script.

Walkthrough

This post shows you how to perform the following tasks:

  1. Download the Apache Thrift compiler and prepare the AppStream 2.0 Thrift definition files.
  2. Generate the C# code files from the Thrift definition files.
  3. Create a new Visual Studio project with the generated C# code files.
  4. Compile the dynamic application framework .NET DLLs.
  5. Use the .NET DLLs with the example PowerShell dynamic application framework client script.

Download the Apache Thrift compiler and prepare the AppStream 2.0 Thrift definition files

Go to https://thrift.apache.org/download and download the latest version of the Thrift compiler.

After you download the Thrift compiler, create the AppStreamServer.thrift and AppStreamServerMessages.thrift definition files in the same directory where you downloaded the Thrift compiler. The syntax for both thrift definition files is in Dynamic Application Framework Thrift Definitions and Named Pipe Name in the AppStream 2.0 Administration Guide.

Generate C# code files from the Thrift definitions

With the compiler downloaded and the Thrift definition files created, we can now generate the C# code files we will need to compile our DLLs.

From a Command or PowerShell prompt run the following:

thrift-<version>.exe -r --gen csharp AppStreamServer.thrift

That command will output a gen-csharp directory in the same folder as your definition files.

In the Model sub-folder (gen-csharp→AppStream→ApplicationCatalogService→Model) there should be the following C# code files:

Create a new Visual Studio project with the generated C# code files

Now that you have the necessary code files, you can begin compiling your DLLs. Although this post shows you how to use Visual Studio 2019, any recent version of Visual Studio should work.

Open Visual Studio, and launch the wizard for Create a New Project from Existing Code Files.

On the welcome page, for the project type, choose Visual C#.

On the Specify Project Details page, do the following:

  • Browse to the location of the C# code files that were just generated.
  • For Name, type a name for your project.
  • For Output type, choose Class Library.

Choose Finish.

Now it’s time to add the Thrift .NET library to your project solution. This post shows you how to use NuGet to do so. NuGet is a Visual Studio extension used for package management.

In Solution Explorer, right-click your solution and choose Manage NuGet Packages for Solution.

On the Browse tab, in the search box, type thrift. In the results list, select ApacheThrift (published by the Apache Thrift Developers).

Compile the dynamic application framework .NET DLLs

You’re now ready to compile the DLLs. Right-click your solution, and choose Build Solution.

If the build is successful, two DLL files display in the debug folder for your project. Both are required for the client script:

  • AS2DAF.dll
  • Thrift.dll

Use the .NET DLLs with an example PowerShell dynamic application framework client script

The following PowerShell script is a simple dynamic application framework client. This client takes in application data from a CSV that was separately generated and adds them to the AppStream 2.0 application catalog that is displayed to the user.

For a complete list of the dynamic application framework API actions that you can use, see API Actions for Managing App Entitlement for AppStream 2.0.

Add-Type -Path C:\Path\To\AS2DAF.dll #Define the full path to the DAF DLL
Add-Type -Path C:\Path\To\Thrift.dll #Define the full path to the Thrift DLL

#Logging Function
Function Write-Log {
    Param ([string]$message)
    $stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
    $logoutput = "$stamp $message"
    Add-content $logfile -value $logoutput
}

#Create Log file
$currentuser = (get-wmiobject Win32_ComputerSystem).UserName.Split('\')[1]
$logfile = "C:\Users\$currentuser\Documents\Logs\DAFClient\$currentuser-$(get-date -f MM-dd-yyyy_HH_mm_ss)-dafupdate.log"
New-Item -path $logfile -ItemType File -Force | Out-Null

$csvpath = "<Path to CSV>" #Define the CSV path

#If the CSV does not exist, exit the script
if (!(Test-Path -Path $csvpath)) {

    Write-Log "No application catalog update file. Exiting..."
    Exit

}

#Establish a connection to the Thirft server, exposed via Named Pipes
Write-Log "Opening connection to AS2 Thrift server..."
$transport = New-Object -TypeName Thrift.Transport.TNamedPipeClientTransport('D56C0258-2173-48D5-B0E6-1EC85AC67893')
$protocol = New-Object -TypeName Thrift.Protocol.TBinaryProtocol($transport)
$client = New-Object -TypeName AppStream.ApplicationCatalogService.Model.ApplicationCatalogService+Client($protocol)
$transport.open()
Write-Log "Connected..."

#Get the current user's SID
$usersid = (New-Object System.Security.Principal.NTAccount(($currentuser))).Translate([System.Security.Principal.SecurityIdentifier]).value

Write-Log "Getting applist for $currentuser, SID: $usersid..."

#Get the content of the CSV and add each application to dynamic application catalog 
foreach ($app in (Import-Csv -path $csvpath)) {

    $appId = $app.Id
    $appdname = $app.DisplayName
    $apppath = $app.LaunchPath
    $appicon = $app.IconData

    Write-Log "Adding $appdname to the dynamic application catalog..."

    $applist = New-Object -TypeName AppStream.ApplicationCatalogService.Model.Application("$appId", "$appdname", "$apppath", "$appicon") 
    $getappreq = New-Object -TypeName Appstream.ApplicationCatalogService.Model.AddApplicationsRequest($usersid, $applist)
    $client.AddApplications($getappreq)
}

#Close the connection to the Thrift server
Write-Log "Closing connection..."
$transport.close()

Exit

For a successful connection to the Thrift server to occur, this client script must be run in the SYSTEM context. Use a Windows scheduled task or the AppStream 2.0 Session Scripts feature.

Regardless of the method, the script should be triggered at the login (or session start) of the user. This ensures that the user sees any dynamically provided apps shortly after login to their AppStream 2.0 instance.

The CSV file that the client reads contains the following information for each application:

  • An ID number.
  • The application name.
  • The full path to the executable file (can be on– or off-instance).
  • The icon image (in base64). Images can be converted to base64 with PowerShell by using the .NET method Convert.ToBase64String.

$icondata = [convert]::ToBase64String((get-content "Path\to\image.png" -Encoding byte))

In a production deployment of the dynamic application framework client, you would dynamically generate the CSV file. You would do so based on your users’ application entitlements as determined by your business logic. However, while testing your client script, use a static CSV with application metadata to validate that the script works as expected.

After you have validated the script adds applications from the CSV successfully, you must add or create the business logic for generating the application entitlements and metadata to be added to the AppStream 2.0 catalog.

Conclusion

And that’s it! You now have the .NET DLLs required for a dynamic application framework client PowerShell script. You also have an example dynamic application framework client PowerShell script that you can use to develop your client script.