Archives

Tag Archive for: ‘vdi’

Why to have detailed logon information from Citrix?
Sometimes anyone is asking you, the performance is not what we like. Within a Citrix environment it is easy to get into the director to see the overview of the logon times.
By default Citrix Director gives the following information about the logon:

citrix director

However average is a good indication, average is not always the best method to measure something. Digging in to the numbers can be needed to get the exceptions clear.
This blog will shortly explain how to get more detailed information from your database.

What kind of results do you get?
My final report shows the following:

graph

This gives more detailed information about how long users need to wait for a logon. The data in this graph is based on the field InteractiveDesktop from the query below.

But also any table with detailed information can be made. Or query on user, query on VDI name, e.g.

My baseline tools
I used the following tools to create this graph:

  • Microsoft Excel
  • SQL Server Management Studio

The results of the query in SQL Server Management Studio can easily copied into Excel. With Pivot tables you can create this kind of graphs.

SQL code
When you run the following query on the Monitoring Database it will give a lot of output.

/* Citrix Director only gives Average information about logon. 
This query gives detailed and calculated information about the logontimes. */

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT LogonDuration = DATEDIFF(Second, [LogOnStartDate], [LogOnEndDate])
      ,[BrokeringDuration]
      ,[AuthenticationDuration]
      ,GpoDuration = DATEDIFF(Second, [GpoStartDate], [GpoEndDate])
      ,InteractiveDesktop = DATEDIFF(Second, [BrokeringDate],[InteractiveEndDate])
      ,FORMAT([BrokeringDate] , 'dd-MM-yyyy') AS EasyDate
      ,FORMAT([BrokeringDate] , 'HH') AS EasyHour
      ,[Name] AS VM
      ,[ClientName]
      ,[ClientAddress]
      ,[ClientVersion]
      ,[ConnectedViaHostName]
      ,[ConnectedViaIPAddress]
      ,[LaunchedViaHostName]
      ,[LaunchedViaIPAddress]     
      ,[LogOnStartDate]
      ,[LogOnEndDate]
      ,[BrokeringDuration]
      ,[BrokeringDate]
      ,[DisconnectCode]
      ,[DisconnectDate]     
      ,[ClientSessionValidateDate]
      ,[ServerSessionValidateDate]
      ,[EstablishmentDate]     
      ,[AuthenticationDuration]
      ,[GpoStartDate]
      ,[GpoEndDate]
      ,[LogOnScriptsStartDate]
      ,[LogOnScriptsEndDate]
      ,[ProfileLoadStartDate]
      ,[ProfileLoadEndDate]
      ,[InteractiveStartDate]
      ,[InteractiveEndDate]     
  FROM [MonitorData].[Connection]
  LEFT JOIN [MonitorData].[Session]
  ON ([MonitorData].[Connection].[SessionKey] = [MonitorData].[Session].[SessionKey] )
  LEFT JOIN [MonitorData].[Machine]
  ON ([MonitorData].[Session].[MachineId] = [MonitorData].[Machine].[Id])
  
  
  WHERE Convert(date,[LogOnStartDate]) = Convert(date,GETDATE())
            AND [IsReconnect] = 0

Conclusion
Citrix is logging a lot of information in the database, but unfortunately the Director is not showing the information. With SQL query’s there are a lot of options to query this information.
All details about the values in the database can be found here: support.citrix.com
Depending on the Citrix license which is purchased, more or less information is stored in the database. Please keep in mind that old records in the database will be cleared automatically. So make you’re report on time, or create something to save the data.

Workplace & VDI Test-automation with Powershell

Why to do test automation with PowerShell?
I was involved in a project to implement a new Virtual Desktop Infrastructure (VDI) within a large company

To ensure the environment is stable and well-functioning all the time on the same way, I made a script to test the basic functionality of the virtual desktop image. The script also measures the time it takes to complete an action, so this can be used to set a baseline for performance measurement.

The basic functionality which is scripted is:

  • Start Outlook and Send an email
  • Can the user browse the internet
  • Open a Word document, Print Preview, Print, and save the document
  • Open an Excel sheet, Save it under a different name
  • Browse the AppV content store
  • Start an AppV application

Other actions can be scripted as well and added to the script.

When the script has run completely with success it will ensure you that the basic functionality is still working.

See the script in action
This video gives a quick overview what kind of actions are scripted and how it works.

Workplace and VDI test automation with PowerShell from EasternNL on Vimeo.

What kind of results do the script make?
When using the script a PDF document is generated which shows the following for each step:

2015-09-23_164405

An example PDF document can be found here: 2015-09-23 163927 Workplace and VDI test-automation with PowerShell.pdf

Also an .su file is generated which has the following content:

2015-08-26    07:23:13.439    07:23:14.48    0.6092069    Excel - start    C:\Users\Erik\AppData\Local\Temp\2015-08-26 07.23.13.439 Excel - start.png

This file is tab-separated and can be imported in Excel or other tools for further investigation.

An example SU file can be found here: test.su

My baseline tools
The script is tested on:

  • Windows 7 with Office 2010
  • Windows 10 with Office 2013

Powershell version 3 or higher is enough to run this script. I am sure this will work on other platforms like Windows 8 e.g. as well.

The iTextSharp module is needed to generate the PDF’s and can be found here: http://sourceforge.net/projects/itextsharp/

Boxcutter.exe is used to make screenshots during the test. Boxcutter can be found here: http://keepnote.org/boxcutter/

Script code
Basically the following code is needed to start Excel:

$excel = new-object -comobject Excel.Application
$excel.visible = $True

Other example is the code to start Internet Explorer:

$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $true

(In a second blog item I will explain how to do the automation of browsing on the internet.)

Basically it is simple, however in my coding some extra steps are involved to measure the start of Excel, and to make a screenshot to ensure everything went well. The Write-Transaction function is included in my module and will write the measured times to the .su file and take the screenshot as well.

$transactionname = "Excel - start"
Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $excel = new-object -comobject Excel.Application
            $excel.visible = $True
            } ) 

In the end of the script the complete .su file is converted to PDF format together with the screenshots.

Conclusion
Windows endpoint testing, for VDI but also for physical desktop can be done with scripts. When launching every day, and eventually on different times of a day the performance and functionality of an Windows desktop can be measured.

The complete script

# load the modules
Import-Module "$(Split-Path -parent $PSCommandPath)\Test-Availability.psm1" -Force
Import-Module "$(Split-Path -parent $PSCommandPath)\iTextSharp.psm1" -Force

# -------------------------------------------
# configure variabeles

$testdocument = "$(Split-Path -parent $PSCommandPath)\testdocument.docx"
$testworkbook = "$(Split-Path -parent $PSCommandPath)\testworkbook.xlsx"
$printer = "Bullzip PDF Printer"
$appvcontentstore = "C:\AppV"

# -------------------------------------------

# Stop if an error has occured, will be handled by the try/catch
$ErrorActionPreference = "Stop"

# Verbose messages on
#$VerbosePreference = "Continue"
# wait time between the steps
$sleepseconds = 1
# temporary path to log the output to
$outputfile = "$($env:temp)\test.su"
if (Test-Path $outputfile) { rm $outputfile }



try {

    # Start Outlook 
        $transactionname = "Outlook - Start"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $outlook = new-object -com "Outlook.Application"
            #$outlook.visible = $true
            $namespace = $outlook.GetNamespace("MAPI")
            $folder = $namespace.GetDefaultFolder(16)
            $folder.Display()
            } )

        # Write email
        # (not sending an email because that is blocked by default in Outlook)
        $transactionname = "Outlook - Write message in draft"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $mail = $outlook.CreateItem(0)
            $mail.Subject = "$(Get-Date -format "yyyy-MM-dd HH:mm:ss") VDI Test Script"
            $mail.To = "user@domain.com"
            $mail.Body = "Testing the VDI functionality with a script"
            $mail.save()
            } )

        # Close Outlook 
        $transactionname = "Outlook - Exit"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $outlook.Quit()
            } )
            
    # Internet Explorer - eastern.nl
        $transactionname = "Internet Explorer - Start"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $ie = new-object -com "InternetExplorer.Application"
            $ie.visible = $true
    
            Set-ForegroundWindow "Internet Explorer"
            } )
    
        # navigate
        $transactionname = "Internet Explorer - www.eastern.nl"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $ie.Navigate("http://www.eastern.nl/")
    
            # wait until the page is ready, all parameters okay and the text Erik van Oost is inside the document
            Wait-InternetExplorer -ie $ie -text "Erik van Oost"
            } )
        
        $transactionname = "Internet Explorer - Quit"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            # Internet Explorer Exit
            $ie.quit()
            } )
	
        # Word
        $transactionname = "Word - Start"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $word=new-object -ComObject "Word.Application"
            $word.visible = $true
            } )
    
        # Document open 
        $transactionname = "Word - Open testfile"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $doc = $word.Documents.Open($testdocument)
            } )

        # Document saven op temp
        $transactionname = "Word - Save testfile"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $filename = "$($env:temp)\test.docx"
            $file_formatcode = 12

            if (Test-Path filename) { rm $filename -Force -ErrorAction SilentlyContinue }
            $doc.SaveAs([ref]$filename, [ref]$file_formatcode)
        } )

        $transactionname = "Word - Print preview"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $doc.PrintPreview()        
            } )

        <#
        $transactionname = "Word - Print"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            # set active printer             
            $word.activeprinter = $printer
            
            # Document afdrukken
            $doc.PrintOut([ref]$false)
            } )
        #>

        $transactionname = "Word - Quit"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            # Close document
            $doc.Close()
            # Exit Word
            $word.Quit()
                } )

    # Start Excel 
        $transactionname = "Excel - start"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $excel = new-object -comobject Excel.Application
            $excel.visible = $True
            } )
    
        # Open workbook
        $transactionname = "Excel - Open testfile"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $wb = $excel.Workbooks.Open($testworkbook)
            } )
    
        # Save workbook
        $transactionname = "Excel - Save testfile"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $filename = "$($env:temp)\test.xlsx"        
            $excel.displayalerts = $false
            $wb.SaveAs($filename)
            } )
    	
    # Close Excel
        $transactionname = "Excel - Quit"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $excel.quit()
        } )

    # Visit AppV Content Store
        $transactionname = "AppV - ContentStore"
        Write-Transaction -transactionname $transactionname -sleepseconds $sleepseconds -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $app = Start-Process cmd.exe -PassThru -ArgumentList " /k dir `"$($appvcontentstore)`" /ogneds" -WorkingDirectory "C:\" 

            } )
        
            # Content store Sluiten
            Stop-Process -Id $app.Id 

    # AppV Application
    # %ALLUSERSPROFILE%\Microsoft\AppV\Client\Integration\4C39F850-61B3-4ED5-95E0-0F21C0B6D0BB\Root\DLS.exe
        $transactionname = "AppV Application Dymo Label Writer"
        Write-Transaction -transactionname $transactionname -sleepseconds 5 -outputfile $outputfile -screenshot $true -measured ( Measure-Command {
            $app = Start-Process  C:\ProgramData\Microsoft\AppV\Client\Integration\4C39F850-61B3-4ED5-95E0-0F21C0B6D0BB\Root\DLS.exe -PassThru 

            } )
        
            # Content store Sluiten
            Stop-Process -Id $app.Id 

   

    # End of test
        $result = Show-PopUp -Message "Test ended sucessfully" -Title "Test Automation" -ButtonSet OK -IconType Information
}
catch
{
    # log if an error occurs, including a screenshot with the error
    $Error

    Write-Transaction -transactionname "ERROR $transactionname" -sleepseconds 0 -outputfile $outputfile -screenshot $true -measured ( Measure-Command { sleep -Milliseconds 100 } )

    $result = Show-PopUp -Message "Test ended with error" -Title "Test Automation" -ButtonSet OK -IconType Exclamation
}

# Ask for conversion to PDF
    $result = Show-PopUp -Message "Do you want to write the results to a PDF file?" -Title "PDF file" -ButtonSet YNC -IconType Question

    if ($result -eq 6)
    {
        # when in an Citrix Session log some information about Citrix
        $sessioninfo = (Get-ItemProperty -Path HKLM:SOFTWARE\Citrix\ICA\Session -ErrorAction SilentlyContinue )
        $outputpdf = (Get-FileName -defaultFileName "$(get-date ((ls $outputfile).CreationTime) -Format "yyyy-MM-dd HHmmss") Workplace and VDI test-automation with PowerShell.pdf" )        
        $message = "VDI Desktop Image testscript run on $(get-date -Format "yyyy-MM-dd HH:mm"). `n`nOutput PDF: $(split-path $outputpdf -leaf)`nComputername: $($env:computername)`n"
		# when in an Citrix Session log some information about Citrix
		if ($sessioninfo -ne $null)
		{
			$message += "Clientaddress: $($sessioninfo.clientaddress) `nClientname: $($sessioninfo.clientname) `nClientversion: $($sessioninfo.clientversion)"
		}
		$message += "`n`n"
        convert-su-to-pdf -inputsu $outputfile -outputpdf $outputpdf -title "Desktop Image functional Script" -message $message
    }

# ask for logoff
    $result = Show-PopUp -Message "Do you want to logoff?" -Title "Logoff" -ButtonSet YNC -IconType Question

    if ($result -eq 6)
    {
        start-process logoff
    }

Download
Download the script, module and test-files here: sources.zip