Print
Willem-Jan Vroom
Category: PowerShell
Hits: 507

In some cases it might be useful to have the Ivanti Workspace Control application building block data exported to a CSV file. Useful for further analysis, and checking for consistency. I wrote a PowerShell script to do that job for me. 
In this article I will share the challenges I had and the solution. 

The most important step is to export all the application building blocks to a folder:

An Ivanti Building Block has the following layout (very simplified!):

<?xml version="1.0"?>
<!-- Workspace Control Building Block -->
<respowerfuse>
	<version>10.3.140.0</version>
	<buildingblock>
		<application required="yes">
			<appid>6276</appid>
			<guid>{AE1C49D1-20CD-4C1E-8A15-734DB701C050}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Microsoft Edge</title>
				<description>Microsoft Edge</description>
				<commandline>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</commandline>
				<workingdir>C:\Program Files (x86)\Microsoft\Edge\Application</workingdir>
				<parameters></parameters>
           </configuration>
        </application>
    </buildingblock>
</respowerfuse>

With PowerShell this is easy to read:

# =============================================================================================================================================
# Define the building block xml file.
# =============================================================================================================================================

$BuildingBlockDetails = [xml]@"
<?xml version="1.0"?>
<!-- Workspace Control Building Block -->
<respowerfuse>
	<version>10.3.140.0</version>
	<buildingblock>
		<application required="yes">
			<appid>6276</appid>
			<guid>{AE1C49D1-20CD-4C1E-8A15-734DB701C050}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Microsoft Edge</title>
				<description>Microsoft Edge</description>
				<commandline>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</commandline>
				<workingdir>C:\Program Files (x86)\Microsoft\Edge\Application</workingdir>
				<parameters></parameters>
           </configuration>
        </application>
    </buildingblock>
</respowerfuse>
"@

# =============================================================================================================================================
# Read the title and appid and write them to the host. 
# =============================================================================================================================================

$ApplicationTitle = $BuildingBlockDetails.respowerfuse.buildingblock.application.configuration.title
$ApplicationAppID = $BuildingBlockDetails.respowerfuse.buildingblock.application.appid

Write-Host "Title:  $ApplicationTitle"
Write-Host "AppID:  $ApplicationAppID"

The output looks like:

And now the challenge. An Ivanti application can have linked applications. So the settings / actions from the linked application are used. 

The same script, but with modified building block data:

# =============================================================================================================================================
# Define the building block xml file.
# =============================================================================================================================================

$BuildingBlockDetails = [xml]@"
<?xml version="1.0"?>
<!-- Workspace Control Building Block -->
<respowerfuse>
	<version>10.3.140.0</version>
	<buildingblock>
        <application required="yes">
			<appid>18</appid>
			<guid>{CACE91A7-7202-4CA2-92A3-0EB32FEB61CE}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Calculator</title>
				<description>Performs basic arithmetic tasks with an on-screen calculator.</description>
				<commandline>%SYSTEMROOT%\SYSTEM32\calc.exe</commandline>
				<workingdir>%SYSTEMROOT%\SYSTEM32</workingdir>
				<parameters></parameters>
            </configuration>
        </application>
		<application>
			<appid>6276</appid>
			<guid>{AE1C49D1-20CD-4C1E-8A15-734DB701C050}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Microsoft Edge - Application with linked action</title>
				<description>Microsoft Edge - Application with linked action</description>
				<commandline>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</commandline>
				<workingdir>C:\Program Files (x86)\Microsoft\Edge\Application</workingdir>
				<parameters></parameters>
           </configuration>
           <powerlaunch>
				<linked_actions>
					<description>Test</description>
					<linked_to_application>{CACE91A7-7202-4CA2-92A3-0EB32FEB61CE}</linked_to_application>
                </linked_actions>
            </powerlaunch>
        </application>
    </buildingblock>
</respowerfuse>
"@

# =============================================================================================================================================
# Read the title and appid and write them to the host. 
# =============================================================================================================================================

$ApplicationTitle = $BuildingBlockDetails.respowerfuse.buildingblock.application.configuration.title
$ApplicationAppID = $BuildingBlockDetails.respowerfuse.buildingblock.application.appid

Write-Host "Title:  $ApplicationTitle"
Write-Host "AppID:  $ApplicationAppID"

But the output looks different:

The title and appid are mixed up. It appears that the XML data respowerfuse.buildingblock.application.configuration.title and respowerfuse.buildingblock.application.appid is added together. 

The 'main' application has the following XML data added:

<respowerfuse>
   <buildingblock>
      </application>
           <powerlaunch>
		<linked_actions>
		       <description>Test</description>
			<linked_to_application>{CACE91A7-7202-4CA2-92A3-0EB32FEB61CE}</linked_to_application>
                </linked_actions>
            </powerlaunch>
        </application>
    </buildingblock>
</respowerfuse>

So only the data from the application block with linked_actions should be used. 

# =============================================================================================================================================
# Define the building block xml file.
# =============================================================================================================================================

$BuildingBlockDetails = [xml]@"
<?xml version="1.0"?>
<!-- Workspace Control Building Block -->
<respowerfuse>
	<version>10.3.140.0</version>
	<buildingblock>
        <application required="yes">
			<appid>18</appid>
			<guid>{CACE91A7-7202-4CA2-92A3-0EB32FEB61CE}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Calculator</title>
				<description>Performs basic arithmetic tasks with an on-screen calculator.</description>
				<commandline>%SYSTEMROOT%\SYSTEM32\calc.exe</commandline>
				<workingdir>%SYSTEMROOT%\SYSTEM32</workingdir>
				<parameters></parameters>
            </configuration>
        </application>
		<application>
			<appid>6276</appid>
			<guid>{AE1C49D1-20CD-4C1E-8A15-734DB701C050}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Microsoft Edge - Application with linked action</title>
				<description>Microsoft Edge - Application with linked action</description>
				<commandline>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</commandline>
				<workingdir>C:\Program Files (x86)\Microsoft\Edge\Application</workingdir>
				<parameters></parameters>
           </configuration>
           <powerlaunch>
				<linked_actions>
					<description>Test</description>
					<linked_to_application>{CACE91A7-7202-4CA2-92A3-0EB32FEB61CE}</linked_to_application>
                </linked_actions>
            </powerlaunch>
        </application>
    </buildingblock>
</respowerfuse>
"@

# =============================================================================================================================================
# Find the number of applications that are defined in the building block xml file. In this case there are 2 applications. 
# =============================================================================================================================================

$numApplications    = $BuildingBlockDetails.respowerfuse.buildingblock.application.Count
if(-not($numApplications))
 {
  $numApplications = 1
 }

Write-Host "There are $numApplications applications defined in the building block XML." 

For($ApplicationCounter = 0; $ApplicationCounter -lt $numApplications; $ApplicationCounter++)
 {
  if($numApplications -eq 1)

  # =============================================================================================================================================
  # If there is one application then use $BuildingBlockDetails.respowerfuse.buildingblock.application
  # If there are more applications the use $BuildingBlockDetails.respowerfuse.buildingblock.application.Item(x)
  # =============================================================================================================================================

   {
    $ApplicationXML = $BuildingBlockDetails.respowerfuse.buildingblock.application
   }
    else
   {
    $ApplicationXML = $BuildingBlockDetails.respowerfuse.buildingblock.application.Item($ApplicationCounter)
   }
  
  # =============================================================================================================================================
  # Check if there is a linked application mentioned in this applicaton block. In that case only read the details for the linked application.
  # =============================================================================================================================================

  $ContainsLinkedActions = $false
  If($ApplicationXML.powerlaunch.linked_actions.linked_to_application)
   {
    $ContainsLinkedActions = $true
   }
  
  if(($numApplications -eq 1) -or ($numApplications -gt 1 -and $ContainsLinkedActions))
   {
    
    # =============================================================================================================================================
    # Read the details and write them to the host.
    # =============================================================================================================================================
    
    $ApplicationTitle = $ApplicationXML.configuration.title
    $ApplicationAppID = $ApplicationXML.appid
    Write-Host "Title:  $ApplicationTitle"
    Write-Host "AppID:  $ApplicationAppID"
   }
 }

And the output looks like:

And this code also works if there is only one application in the XML file defined:

# =============================================================================================================================================
# Define the building block xml file.
# =============================================================================================================================================

$BuildingBlockDetails = [xml]@"
<?xml version="1.0"?>
<!-- Workspace Control Building Block -->
<respowerfuse>
	<version>10.3.140.0</version>
	<buildingblock>
		<application required="yes">
			<appid>6276</appid>
			<guid>{AE1C49D1-20CD-4C1E-8A15-734DB701C050}</guid>
			<configuration>
				<menu>Start\Accessories</menu>
				<title>Microsoft Edge</title>
				<description>Microsoft Edge</description>
				<commandline>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</commandline>
				<workingdir>C:\Program Files (x86)\Microsoft\Edge\Application</workingdir>
				<parameters></parameters>
           </configuration>
        </application>
    </buildingblock>
</respowerfuse>
"@

# =============================================================================================================================================
# Find the number of applications that are defined in the building block xml file. In this case there are 2 applications. 
# =============================================================================================================================================

$numApplications    = $BuildingBlockDetails.respowerfuse.buildingblock.application.Count
if(-not($numApplications))
 {
  $numApplications = 1
 }

Write-Host "There are $numApplications applications defined in the building block XML." 

For($ApplicationCounter = 0; $ApplicationCounter -lt $numApplications; $ApplicationCounter++)
 {
  if($numApplications -eq 1)

  # =============================================================================================================================================
  # If there is one application then use $BuildingBlockDetails.respowerfuse.buildingblock.application
  # If there are more applications the use $BuildingBlockDetails.respowerfuse.buildingblock.application.Item(x)
  # =============================================================================================================================================

   {
    $ApplicationXML = $BuildingBlockDetails.respowerfuse.buildingblock.application
   }
    else
   {
    $ApplicationXML = $BuildingBlockDetails.respowerfuse.buildingblock.application.Item($ApplicationCounter)
   }
  
  # =============================================================================================================================================
  # Check if there is a linked application mentioned in this applicaton block. In that case only read the details for the linked application.
  # =============================================================================================================================================

  $ContainsLinkedActions = $false
  If($ApplicationXML.powerlaunch.linked_actions.linked_to_application)
   {
    $ContainsLinkedActions = $true
   }
  
  if(($numApplications -eq 1) -or ($numApplications -gt 1 -and $ContainsLinkedActions))
   {
    
    # =============================================================================================================================================
    # Read the details and write them to the host.
    # =============================================================================================================================================
    
    $ApplicationTitle = $ApplicationXML.configuration.title
    $ApplicationAppID = $ApplicationXML.appid
    Write-Host "Title:  $ApplicationTitle"
    Write-Host "AppID:  $ApplicationAppID"
   }
 }

With the following output:

You can view some background information on YouTube:

This technique is used in my script.

<#
.SYNOPSIS
    Finds the Start Menu Items in Ivanti Workspace Control Building Blocks and export them to a CSV file.

.DESCRIPTION
    An Ivanti Building Block contains all kind of information about a Start Menu item. This script exports the most used details to a CSV file. 

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and its subfolders
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp.
    The delimiter character is ','
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -Delimiter ","

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    Check if the executable excel.exe or winword.exe is used in the commandline
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -LookFor -InCommandLine excel.exe,winword.exe

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    Check if Microsoft is used in the title.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -LookFor -InTitle Office

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    Check if Microsoft is used in the title. Use detailed logging to a log file.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -LookFor -InTitle Office -DetailedLogging

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    Check if the group name 'Appl_Visio' is used.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -LookFor -GroupName Appl_Visio

.EXAMPLE
    Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result file in c:\tmp
    Copy all the building block files that have msedge.exe or iexplore.exe in the command line to c:\tmp-internet
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders -LogPath c:\tmp -LookFor -InCommandLine msedge.exe,iexplore.exe -CopyFiles -To c:\tmp-internet

.NOTES
    Author:  Willem-Jan Vroom
    Website: https://www.vroom.cc/
    Twitter: @TheStingPilot

v0.1:
   * Initial version.

v0.2:
   * Added parameters:
       - detailedlogging
       - lookfor
           - InTitle
           - incommandline
           - copyfiles
              - to

v0.3:
   * LookFor as been extended with 'GroupOrUse

#>

[CmdletBinding(DefaultParameterSetName = 'Default')]

Param
  (
   [Parameter(HelpMessage='Specify the directory that contains all the exported building blocks.')]
   [Parameter(Mandatory=$True,  ParameterSetName='Default')]
   [String]   $Directory = "",

   [Parameter(HelpMessage='Specify the log path.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String]   $LogPath = "",

   [Parameter(HelpMessage='Include subfolders for the directory that contains all the exported building blocks.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [Switch]   $IncludeSubFolders,

   [Parameter(HelpMessage='Enable detailed logging to a log file.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [Switch]   $DetailedLogging,

   [Parameter(HelpMessage='Enable lookfor.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [Switch]   $LookFor,

   [Parameter(HelpMessage='Specify the items to search for in the title, may be seperated by a comma.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String[]] $InTitle,

   [Parameter(HelpMessage='Specify the items to search for in the command line, may be seperated by a comma.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String[]] $InCommandLine,

   [Parameter(HelpMessage='Specify the groups or users to search for. May be seperated by a comma.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String[]] $GroupOrUser,

   [Parameter(HelpMessage='Copy the files that are found with the LookFor parameter to a new location.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [Switch]   $CopyFiles,

   [Parameter(HelpMessage='The location where the files have to be copied to.')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String]   $To,

   [Parameter(HelpMessage='Specify the delimiter character. Default = ;')]
   [Parameter(Mandatory=$False, ParameterSetName='Default')]
   [String]   $Delimiter = ";"

  )

# =============================================================================================================================================
# Function block
# =============================================================================================================================================

  Function Add-EntryToLogFile
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       17-May-2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Add-EntryToLogFile
    =============================================================================================================================================
    .SYNOPSIS

    This function adds a line to a log file

    #>

    Param
     (
      [string] $Entry
     )
      
     Write-Verbose $Entry
     if($Global:DetailedLogging)
      {
       $Timestamp = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
       Add-Content $Global:LogFile -Value $($Timestamp + " " + $Entry) -Force -ErrorAction SilentlyContinue
      }
   }


  Function Create-Folder
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       03-August-2018
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Create-Folder
    =============================================================================================================================================
    .SYNOPSIS

    This function creates the given folder.
    The function returns two results:
     1. A message.
     2. True or false (success or failure)

    #>
    
    param
     (
      [String] $FolderName
     )

   $bolResult     = $True
   $ResultMessage = ""

   if(-not(Test-Path $('FileSystem::' + $FolderName)))
    {
     New-Item -Path $FolderName -ItemType Directory | Out-Null
     Sleep 1
     if(test-path $('FileSystem::' + $FolderName))
      {
       $ResultMessage = "The folder '$FolderName' has been created."
      }
       else
      {
       $ResultMessage = "Something went wrong while creating the folder '$FolderName'. "
       $bolResult     = $false
      }
    }
     else
    {
     $ResultMessage = "The folder $FolderName already exists."
    }

    Return $ResultMessage,$bolResult 

   }

  Function Add-EntryToResultsFile
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       03-August-2018
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Add-EntryToResultsFile
    =============================================================================================================================================
    .SYNOPSIS

    This function adds the success or failure information to the array that contains the log
    information.

    #>

    Param
     (
      [String]  $XMLFileName                       = "",
      [String]  $StartMenu                         = "",
      [String]  $appid                             = "",
      [String]  $Title                             = "",
      [String]  $Description                       = "",
      [String]  $Commandline                       = "",
      [String]  $Workingdir                        = "",
      [String]  $Parameters                        = "",
      [String]  $appv5packagemode                  = "",
      [String]  $appv5packagefile                  = "",
      [String]  $appv5deploymentconfigurationfile  = "",
      [String]  $appv5userconfigurationfile        = "",
      [String]  $appv5packageupdate                = "",
      [String]  $appv5packageroot                  = "",
      [String]  $administrativenote                = "",
      [String]  $unmanagedshortcuts                = "",
      [String]  $createmenushortcut                = "",
      [String]  $allowmultipleshortcuts            = "",
      [String]  $Enabled                           = "",
      [String]  $hidefrommenu                      = "",
      [String]  $checkappexists                    = "",
      [String]  $checkfileexists                   = "",
      [String]  $accesstype                        = "",
      [String]  $GroupList                         = "",
      [String]  $PowerZones                        = "",
      [String]  $Workspaces                        = "",
      [String]  $LearningMode                      = "",
      [String]  $AppGuard                          = "",
      [String]  $ContainsLinkedActions             = "",
      [String]  $Remark                            = ""
     )

    $Record  = [ordered] @{"Timestamp"                                                               = "";
                           "XML File Name"                                                           = "";
                           "Start Menu location"                                                     = "";
                           "Properties - General - ID"                                               = "";
                           "Properties - General - Title"                                            = "";
                           "Properties - General - Description"                                      = "";
                           "Properties - General - Commandline"                                      = "";
                           "Properties - General - Working directory"                                = "";
                           "Properties - General - Parameters"                                       = "";
                           "Properties - General - AppV5 Package delivery mode"                      = "";
                           "Properties - General - AppV5 Package file"                               = "";
                           "Properties - General - AppV5 Deployment configuration file"              = "";
                           "Properties - General - AppV5 User configuration file"                    = "";
                           "Properties - General - AppV5 Always use latest version"                  = "";
                           "Properties - General - AppV5 Package root folder"                        = "";
                           "Properties - General - Administrative note"                              = "";
                           "Properties - Shortcuts - Replace existing unmanaged shortcuts"           = "";
                           "Properties - Shortcuts - Create Start Menu shortcut"                     = "";
                           "Properties - Shortcuts - Allow multiple shortcuts in Start Menu"         = "";
                           "Properties - Settings - Application is enabled"                          = "";
                           "Properties - Settings - Hide application"                                = "";
                           "Properties - Settings - Hide application if executable was not found"    = "";
                           "Properties - Settings - Hide application if file was not found"          = "";
                           "Access Control - Identy - Type"                                          = "";
                           "Access Control - Identy - Selected users and/or groups"                  = "";
                           "Access Control - Location and devices"                                   = "";
                           "Access Control - Workspace containers"                                   = "";
                           "Security - Authorized Files - Run this application in learning mode"     = "";
                           "Security - Authorized Files - Authorized file"                           = "";
                           "Configuration - Actions - At application start contains linked actions"  = "";
                           "Remark"                                                                  = ""
                           }

    $Timestamp         = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
    
    $Record."Timestamp"                                                              = $Timestamp
    $Record."XML File Name"                                                          = $XMLFileName
    $Record."Start Menu location"                                                    = $StartMenu
    $Record."Properties - General - ID"                                              = $appid
    $Record."Properties - General - Title"                                           = $Title
    $Record."Properties - General - Description"                                     = $Description
    $Record."Properties - General - Commandline"                                     = $Commandline
    $Record."Properties - General - Working directory"                               = $Workingdir
    $Record."Properties - General - Parameters"                                      = $Parameters
    $Record."Properties - General - AppV5 Package delivery mode"                     = $appv5packagemode
    $Record."Properties - General - AppV5 Package file"                              = $appv5packagefile
    $Record."Properties - General - AppV5 Deployment configuration file"             = $appv5deploymentconfigurationfile
    $Record."Properties - General - AppV5 User configuration file"                   = $appv5userconfigurationfile
    $Record."Properties - General - AppV5 Always use latest version"                 = $appv5packageupdate
    $Record."Properties - General - AppV5 Package root folder"                       = $appv5packageroot
    $Record."Properties - General - Administrative note"                             = $administrativenote
    $Record."Properties - Shortcuts - Replace existing unmanaged shortcuts"          = $unmanagedshortcuts
    $Record."Properties - Shortcuts - Create Start Menu shortcut"                    = $createmenushortcut
    $Record."Properties - Shortcuts - Allow multiple shortcuts in Start Menu"        = $allowmultipleshortcuts
    $Record."Properties - Settings - Application is enabled"                         = $Enabled
    $Record."Properties - Settings - Hide application"                               = $hidefrommenu
    $Record."Properties - Settings - Hide application if executable was not found"   = $checkappexists
    $Record."Access Control - Identy - Type"                                         = $accesstype
    $Record."Access Control - Identy - Selected users and/or groups"                 = $GroupList
    $Record."Access Control - Location and devices"                                  = $PowerZones
    $Record."Access Control - Workspace containers"                                  = $Workspaces
    $Record."Configuration - Actions - At application start contains linked actions" = $ContainsLinkedActions
    $Record."Security - Authorized Files - Run this application in learning mode"    = $LearningMode
    $Record."Security - Authorized Files - Authorized file"                          = $AppGuard
    $Record."Remark"                                                                 = $Remark

    $objRecord                           = New-Object PSObject -Property $Record
    $Global:arrTable                    += $objRecord

    Add-EntryToLogFile -Entry  "       Timestamp:                                                               $Timestamp"
    Add-EntryToLogFile -Entry  "       XML File Name:                                                           $XMLFileName"
    Add-EntryToLogFile -Entry  "       Start Menu location:                                                     $StartMenu"
    Add-EntryToLogFile -Entry  "       Properties - General - ID:                                               $appid"
    Add-EntryToLogFile -Entry  "       Properties - General - Title:                                            $Title"
    Add-EntryToLogFile -Entry  "       Properties - General - Description:                                      $Description"
    Add-EntryToLogFile -Entry  "       Properties - General - Commandline:                                      $Commandline"
    Add-EntryToLogFile -Entry  "       Properties - General - Working directory:                                $Workingdir"                      
    Add-EntryToLogFile -Entry  "       Properties - General - Parameters:                                       $Parameters"
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 Package delivery mode:                      $appv5packagemode"
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 Package file:                               $appv5packagefile"   
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 Deployment configuration file:              $appv5deploymentconfigurationfile"            
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 User configuration file:                    $appv5userconfigurationfile"                  
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 Always use latest version:                  $appv5packageupdate"
    Add-EntryToLogFile -Entry  "       Properties - General - AppV5 Package root folder:                        $appv5packageroot"                       
    Add-EntryToLogFile -Entry  "       Properties - General - Administrative note:                              $administrativenote"
    Add-EntryToLogFile -Entry  "       Properties - Shortcuts - Replace existing unmanaged shortcuts:           $unmanagedshortcuts"           
    Add-EntryToLogFile -Entry  "       Properties - Shortcuts - Create Start Menu shortcut:                     $createmenushortcut"
    Add-EntryToLogFile -Entry  "       Properties - Shortcuts - Allow multiple shortcuts in Start Menu:         $allowmultipleshortcuts"       
    Add-EntryToLogFile -Entry  "       Properties - Settings - Application is enabled:                          $Enabled"                         
    Add-EntryToLogFile -Entry  "       Properties - Settings - Hide application:                                $hidefrommenu"
    Add-EntryToLogFile -Entry  "       Properties - Settings - Hide application if executable was not found:    $checkappexists"   
    Add-EntryToLogFile -Entry  "       Properties - Settings - Hide application if file was not found:          $checkfileexists"
    Add-EntryToLogFile -Entry  "       Access Control - Identy - Type                                           $accesstype"
    Add-EntryToLogFile -Entry  "       Access Control - Identy - Selected users and/or groups:                  $GroupList"
    Add-EntryToLogFile -Entry  "       Access Control - Location and devices:                                   $PowerZones"                                   
    Add-EntryToLogFile -Entry  "       Access Control - Workspace containers:                                   $Workspaces"
    Add-EntryToLogFile -Entry  "       Configuration - Actions - At application start contains linked actions:  $ContainsLinkedActions"
    Add-EntryToLogFile -Entry  "       Security - Authorized Files - Run this application in learning mode:     $LearningMode"
    Add-EntryToLogFile -Entry  "       Security - Authorized Files - Authorized file:                           $AppGuard"
    Add-EntryToLogFile -Entry  "       Remark:                                                                  $Remark"
    Add-EntryToLogFile -Entry  ""
    Add-EntryToLogFile -Entry  "###############################################################################################################`n"
   
   }

  Function CheckXMLFile
   {

      <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       06-September-2018
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     CheckXMLFile
    =============================================================================================================================================
    .SYNOPSIS

    This function checks if the xml file is valid.

    #>

    param
     (
      [String]$XMLFile
     )

     $xml = New-Object System.Xml.XmlDocument

     Try
      {
       $xml.Load((Get-ChildItem -Path $XMLFile).FullName)
       Add-EntryToLogFile -Entry "------- The file $XMLFile is valid."
       Return $True
      }
       Catch
      {
       Add-EntryToLogFile -Entry "------- The file $XMLFile is not valid."
       Return $False
      }
   }

  Function Export-ResultsLogFileToCSV
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       06-September-2018
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Export-ResultsLogFileToCSV
    =============================================================================================================================================
    .SYNOPSIS

    This function writes the logfile content to a CSV file.

    #>

    If($Global:arrTable.Count -gt 0)
     {
      $Global:arrTable | Sort-Object -Property TimeStamp | Export-Csv $strCSVLogFileSucces -NoTypeInformation -Delimiter $Global:Delimiter
      Add-EntryToLogFile -Entry ">> Export-ResultsLogFileToCSV: The file '$strCSVLogFileSucces' has been written." 
     } 
      else
     {
      $ErrorMessage = "Something went wrong while writing the logfile '$strCSVLogFileSucces'. Maybe nothing to report..."
      Add-EntryToLogFile -Entry "[Error]: $ErrorMessage"
      Write-Error $ErrorMessage -Category CloseError 
     } 
   }

 Function Get-XMLDetailsForAccessInfo
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       26 April 2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Get-XMLDetailsForAccessInfo
    =============================================================================================================================================
    .SYNOPSIS

    This function returns who has rights to use this application:
     - The users and groups
     - The application manager(s).
    #>
   
    Param
      (
       [xml]    $BuildingBlockDetails,
       [string] $XMLPath,
       [string] $accessmode,
       [string] $accesstype
      )
       
       $XMLPath = $XMLPath.Replace(".","/")
       $Return = @()

     # =============================================================================================================================================
     # Users and groups
     # =============================================================================================================================================
       
       if ($accesstype -eq "group")
       
        {
         
        # =============================================================================================================================================
        # The users and groups are stored in 
        # respowerfuse.buildingblock.application.accesscontrol.grouplist.group
        # =============================================================================================================================================
         
         $GroupDetails  = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath/grouplist/group")
         $GroupDetails = ($GroupDetails).Node
         
         if($GroupDetails)
          {
           Add-EntryToLogFile -Entry " Group Details:"
           forEach ($GroupDetail in $GroupDetails)
            {
             if(-not($Return))
              {
               $Type = $GroupDetail | Select-Object -ExpandProperty 'type' -ErrorAction SilentlyContinue
               Add-EntryToLogFile -Entry "  -> Type:  $Type"

               $Name = $GroupDetail | Select-Object -ExpandProperty '#text'
               Add-EntryToLogFile -Entry "  -> Name:  $Name"
               $Return = "$Name   ($($Type))"
              }
               else
              {
               $Type = $GroupDetail | Select-Object -ExpandProperty 'type' -ErrorAction SilentlyContinue
               Add-EntryToLogFile -Entry "  -> Type:  $Type"

               $Name = $GroupDetail | Select-Object -ExpandProperty '#text'
               Add-EntryToLogFile -Entry "  -> Name:  $Name"
               $Return += "`n$($accessmode) $($Name)   ($($Type))"
             }
            }
          
           $NotGroupDetails  = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath/notgrouplist/group")
           if($NotGroupDetails)
            {
             $NotGroupDetails = ($NotGroupDetails).Node
             Add-EntryToLogFile -Entry " Not Group Details:"
             forEach ($NotGroupDetail in $NotGroupDetails)
              {
               $Type = $NotGroupDetail | Select-Object -ExpandProperty 'type'
               Add-EntryToLogFile -Entry "  -> Type:  $Type" 
               $Name = $NotGroupDetail | Select-Object -ExpandProperty '#text'
               Add-EntryToLogFile -Entry "  -> Name:  $Name"
               $Return += "`n    $($accessmode) NOT IN $($Name)   ($($Type))"
              }
            }
          }
       }

     # =============================================================================================================================================
     # Controlled by application managers.
     # =============================================================================================================================================

       elseif($accesstype -eq "delegated")
        {
        
       # =============================================================================================================================================
       # The controlled by application manager(s) are stored in 
       # respowerfuse.buildingblock.application.accesscontrol.appmanlist.appmanglobal
       # =============================================================================================================================================
               
         $AppplicationManagers = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath/appmanlist/appmanglobal")
         $AppplicationManagers = ($AppplicationManagers).Node
         Add-EntryToLogFile -Entry " Group Details:" 

         forEach ($AppplicationManager in $AppplicationManagers)
          {
           if(-not($Return))
            {
             $Name = $AppplicationManager | Select-Object -ExpandProperty '#text'
             Add-EntryToLogFile -Entry "  -> Name:  $Name"
             $Return = "$Name"
            }
             else
            {
             $Name = $AppplicationManager | Select-Object -ExpandProperty '#text'
             Add-EntryToLogFile -Entry "  -> Name:  $Name"
             $Return += "`n$($accessmode) $($Name)"
           }
          }
        }

     Add-EntryToLogFile -Entry "(Function: Get-XMLDetailsForAccessInfo) The resturn value for $XMLPath is $Return."

     Return $Return
   }

Function Get-XMLDetailsForAuthorizedFiles
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       26 April 2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Get-XMLDetailsForAuthorizedFiles
    =============================================================================================================================================
    .SYNOPSIS

    This function returns the authorized files.
    #>
   
    Param
      (
       [xml]    $BuildingBlockDetails,
       [string] $XMLPath,
       [string] $CommandLine
      )
       
     Add-EntryToLogFile -Entry "--> In function: Get-XMLDetailsForAuthorizedFiles"

     $XMLPath = $XMLPath.Replace(".","/")
     $Return = @()
     
   # =============================================================================================================================================
   # At least the application executable is an authorized file.
   # =============================================================================================================================================
   
     if($CommandLine)
      {
       $Return += "$CommandLine    (Process: *)"
      }

   # =============================================================================================================================================
   # The authorized files are stored in 
   # respowerfuse.buildingblock.application.appguard.authorizedfiles.authfile
   # =============================================================================================================================================
   
     $AuthFilesDetails = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath")
     $AuthFilesDetails = ($AuthFilesDetails).Node
       
     forEach ($AuthFilesDetail in $AuthFilesDetails)
      {
       $enabled = $AuthFilesDetail | Select-Object -ExpandProperty 'enabled'
       if($enabled -eq "yes")
        {
         $authorizedfile = $AuthFilesDetail | Select-Object -ExpandProperty 'authorizedfile'
         Add-EntryToLogFile -Entry "  -> authorizedfile:  $authorizedfile"
         $process        = $AuthFilesDetail | Select-Object -ExpandProperty 'process'
         Add-EntryToLogFile -Entry "  -> process:         $process"
         $Return += "`n$authorizedfile   (Process: $($process))"
        }
      }

     Add-EntryToLogFile -Entry "(Function: Get-XMLDetailsForAuthorizedFiles) The resturn value for $XMLPath is $Return." 

     Return $Return
   }

Function Get-XMLDetailsForWorkspaces
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       26 April 2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Get-XMLDetailsForWorkspaces
    =============================================================================================================================================
    .SYNOPSIS

    This function returns the authorized files.
    #>
   
    Param
      (
       [xml]    $BuildingBlockDetails,
       [string] $XMLPath
      )
       
     Add-EntryToLogFile -Entry "--> In function: Get-XMLDetailsForWorkspaces"

     $XMLPath = $XMLPath.Replace(".","/")
     $Return = @()

   # =============================================================================================================================================
   # The workspaces are stored in 
   # respowerfuse.buildingblock.workspaces.workspace
   # =============================================================================================================================================
 
     $WorkspaceDetails = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath")
     $WorkspaceDetails = ($WorkspaceDetails).Node
       
     forEach ($Workspace in $WorkspaceDetails)
      {
       $enabled = $Workspace | Select-Object -ExpandProperty 'enabled'
       if($enabled -eq "yes")
        {
         if(-not($Return))
          {
           $authorizedWorkspace = $Workspace | Select-Object -ExpandProperty 'name'
           Add-EntryToLogFile -Entry "  -> authorized workspace:  $authorizedWorkspace" 
           $Return = "$authorizedWorkspace"
          }
           else
          {
           $authorizedWorkspace = $Workspace | Select-Object -ExpandProperty 'name'
           Add-EntryToLogFile -Entry "  -> authorized workspace:  $authorizedWorkspace" 
           $Return += "`n$authorizedWorkspace"
         }
        }
      }

     Add-EntryToLogFile -Entry "(Function: Get-XMLDetailsForWorkspaces) The resturn value for $XMLPath is $Return." 
     Return $Return
   }

Function Get-XMLDetailsForPowerZones
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       26 April 2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     Get-XMLDetailsForPowerZones
    =============================================================================================================================================
    .SYNOPSIS

    This function returns the authorized files.
    #>
   
    Param
      (
       [xml]    $BuildingBlockDetails,
       [string] $XMLPath
      )
       
     Add-EntryToLogFile -Entry "--> In function: Get-XMLDetailsForPowerZones"
     $XMLPath = $XMLPath.Replace(".","/")
     $Return = @()

   # =============================================================================================================================================
   # The powerzones are stored in 
   # respowerfuse.buildingblock.application.powerzones.powerzone
   # =============================================================================================================================================

     $PowerZones = @($BuildingBlockDetails | Select-Xml -XPath "/$XMLPath").Node."#text"
       
     forEach ($PowerZone in $PowerZones)
      {
       if(-not($Return))
        {
         Add-EntryToLogFile -Entry "  -> authorized powerzone:  $PowerZone" 
         $Return = $PowerZone
        }
         else
        {
         Add-EntryToLogFile -Entry "  -> authorized powerzone:  $PowerZone" 
         $Return += "`n$PowerZone"
       }
      }

     Add-EntryToLogFile -Entry "(Function: Get-XMLDetailsForPowerZones) The resturn value for $XMLPath is $Return." 
     Return $Return
   }

  Function FindInfoInBuildingBlock
   {

    <#
    .NOTES
    =============================================================================================================================================
    Created with:     Windows PowerShell ISE
    Created on:       26 April 2020
    Created by:       Willem-Jan Vroom
    Organization:     
    Functionname:     FindInfoInBuildingBlock
    =============================================================================================================================================
    .SYNOPSIS

    This function finds all the information in the building block.
    #>

    Param
     (
      [xml]    $BuildingBlockDetails,
      [String] $Filename,
      [String] $LogFile
     )

     $Commandline                         = ""
     $numApplications                     = $BuildingBlockDetails.respowerfuse.buildingblock.application.Count
     if(-not($numApplications))
      {
       $numApplications = 1
      }
           
     for($ApplicationCounter = 0; $ApplicationCounter -lt $numApplications; $ApplicationCounter++)
      {
     
       if($numApplications -eq 1)
        {
         $ApplicationXML                     = $BuildingBlockDetails.respowerfuse.buildingblock.application
        }
         else
        {
         $ApplicationXML                     = $BuildingBlockDetails.respowerfuse.buildingblock.application.Item($ApplicationCounter)
        }
      
       $ContainsLinkedActions = $false
       If($ApplicationXML.powerlaunch.linked_actions.linked_to_application)
        {
         $ContainsLinkedActions = $true
        }
       
       if(($numApplications -eq 1) -or ($numApplications -gt 1 -and $ContainsLinkedActions))
        {         
         $appid                               = $ApplicationXML.appid
         $Title                               = $ApplicationXML.configuration.title
         $StartMenu                           = $ApplicationXML.configuration.menu
         $Description                         = $ApplicationXML.configuration.description
         $Commandline                         = $ApplicationXML.configuration.commandline
         $accesstype                          = $ApplicationXML.accesscontrol.accesstype
         $AccessMode                          = $ApplicationXML.accesscontrol.access_mode
         $tmpCounter                          = $ApplicationCounter+1
         Switch ($accesstype)
            {
             "group"     {$GroupList                           = Get-XMLDetailsForAccessInfo -BuildingBlockDetails $BuildingBlockDetails -XMLPath "respowerfuse.buildingblock.application[$tmpCounter].accesscontrol" -accessmode $AccessMode -accesstype $accesstype
                          $accesstype = "Users and groups"
                          break
                         }
             "delegated" {$GroupList                           = Get-XMLDetailsForAccessInfo -BuildingBlockDetails $BuildingBlockDetails -XMLPath "respowerfuse.buildingblock.application[$tmpCounter].accesscontrol" -accessmode $AccessMode -accesstype $accesstype
                          $accesstype = "Controlled by application manager(s)"
                          break
                         }
             "ou"        {$accesstype = "OU membership"
                          break
                         }
             "all"       {$accesstype = "All users"
                          break
                         }
             "secrole"   {$accesstype = "Administrative roles"
                          break
                         }
             "orchestra" {$accesstype = "Identity Director Service"
                          break
                         }
              default    {$accesstype = "An invalid access type has been discovered."}
            }
         
         # =============================================================================================================================================
         # Check if LookFor is used. In that case check the title and commandline
         # =============================================================================================================================================
 
         $boltitle       = $false
         $bolCommandLine = $false
         $Remark         = ""

         if($Global:LookFor)
         {
          # Check the title
          ForEach ($objTitle in $Global:InTitle)
           {
            if($Title -match $objTitle)
             {
              $boltitle = $true
              $Entry    = "$objTitle has been found in $Title."
              Add-EntryToLogFile -Entry $Entry
              $Remark = "[Title] $Entry"
              Break
             }
           }
          # Check the command line
          ForEach ($objCommandLine in $Global:InCommandLine)
           {
            if($Commandline -match $objCommandLine)
             {
              $bolCommandLine = $true
              $Entry          = "$objCommandLine has been found in $Commandline."
              Add-EntryToLogFile -Entry $Entry
              if(-not($Remark))
               {
                $Remark = "[CommandLine] $Entry"
               }
                else
               {
                $Remark += "`n[CommandLine] $Entry"
               }
             }
           }


         # Check the group or user
         if($accesstype = "Users and groups")
          {
           ForEach ($objGroupOrUser in $Global:GroupOrUser)
            {
             ForEach ($obGroupList in $GroupList)
              {
               if($obGroupList -match $objGroupOrUser)
                {
                 $bolGroupOrUser = $true
                 $Entry          = "$objGroupOrUser has been found in $obGroupList."
                 Add-EntryToLogFile -Entry $Entry
                 if(-not($Remark))
                  {
                   $Remark = "[GroupOrUser] $Entry"
                  }
                   else
                  {
                   $Remark += "`n[groupOrUser] $Entry"
                  }
                } 
              }
            }
          }
         }

         if((-not($Global:LookFor)) -or ($boltitle -or $bolCommandLine -or $bolGroupOrUser))
          {
           $Workingdir                          = $ApplicationXML.configuration.workingdir
           $Parameters                          = $ApplicationXML.configuration.parameters
           $appv5packagemode                    = $ApplicationXML.configuration.appv5packagemode
           $appv5packagefile                    = $ApplicationXML.configuration.appv5packagefile
           $appv5deploymentconfigurationfile    = $ApplicationXML.configuration.appv5deploymentconfigurationfile
           $appv5userconfigurationfile          = $ApplicationXML.configuration.appv5userconfigurationfile
           $appv5packageupdate                  = $ApplicationXML.configuration.appv5packageupdate
           $appv5packageroot                    = $ApplicationXML.configuration.appv5packageroot
           $administrativenote                  = $ApplicationXML.configuration.administrativenote 
           $unmanagedshortcuts                  = $ApplicationXML.configuration.unmanagedshortcuts
           $createmenushortcut                  = $ApplicationXML.configuration.createmenushortcut
           $allowmultipleshortcuts              = $ApplicationXML.configuration.allowmultipleshortcuts

           $Enabled                             = $ApplicationXML.settings.enabled
           $hidefrommenu                        = $ApplicationXML.settings.hidefrommenu
           $checkappexists                      = $ApplicationXML.settings.checkappexists
           $checkfileexists                     = $ApplicationXML.settings.checkfileexists
                  
           $LearningMode                        = $ApplicationXML.appguard.learning
                  

           $AppGuard                            = Get-XMLDetailsForAuthorizedFiles -BuildingBlockDetails $BuildingBlockDetails -XMLPath "respowerfuse.buildingblock.application[$tmpCounter].appguard.authorizedfiles.authfile" -CommandLine $Commandline 
           $PowerZones                          = Get-XMLDetailsForPowerZones      -BuildingBlockDetails $BuildingBlockDetails -XMLPath "respowerfuse.buildingblock.application[$tmpCounter].powerzones.powerzone"
           $Workspaces                          = Get-XMLDetailsForWorkspaces      -BuildingBlockDetails $BuildingBlockDetails -XMLPath "respowerfuse.buildingblock.workspaces.workspace"
                  
           Add-EntryToResultsFile  -XMLFileName                      $Filename                           `
                                   -StartMenu                        $StartMenu                          `
                                   -appid                            $appid                              `
                                   -Title                            $Title                              `
                                   -Description                      $Description                        `
                                   -Commandline                      $Commandline                        `
                                   -Workingdir                       $Workingdir                         `
                                   -Parameters                       $Parameters                         `
                                   -appv5packagemode                 $appv5packagemode                   `
                                   -appv5packagefile                 $appv5packagefile                   `
                                   -appv5deploymentconfigurationfile $appv5deploymentconfigurationfile   `
                                   -appv5packageupdate               $appv5packageupdate                 `
                                   -appv5userconfigurationfile       $appv5userconfigurationfile         `
                                   -appv5packageroot                 $appv5packageroot                   `
                                   -administrativenote               $administrativenote                 `
                                   -unmanagedshortcuts               $unmanagedshortcuts                 `
                                   -createmenushortcut               $createmenushortcut                 `
                                   -allowmultipleshortcuts           $allowmultipleshortcuts             `
                                   -Enabled                          $Enabled                            `
                                   -hidefrommenu                     $hidefrommenu                       `
                                   -checkappexists                   $checkappexists                     `
                                   -checkfileexists                  $checkfileexists                    `
                                   -accesstype                       $accesstype                         `
                                   -GroupList                        $GroupList                          `
                                   -PowerZones                       $PowerZones                         `
                                   -Workspaces                       $Workspaces                         `
                                   -LearningMode                     $LearningMode                       `
                                   -AppGuard                         $AppGuard                           `
                                   -ContainsLinkedActions            $ContainsLinkedActions              `
                                   -Remark                           $Remark   
           if($Global:CopyFiles)
            {
             Copy-Item -Path $($Global:BuildingBlockFileName) -Destination $To -Force
             Add-EntryToLogFile "The file $($Global:BuildingBlockFileName) has been copied to $To."
            }
          }
           else
          {
           Add-EntryToLogFile -Entry "The search-item has not been found in the application $Title.`n"
          }                     
        }
      }
   }
 
# =============================================================================================================================================
# End function block
# =============================================================================================================================================

# =============================================================================================================================================
# Check if the parameter -LookFor has not been forgotten.
# Define the variables
# =============================================================================================================================================

  Clear-Host

  $Message  = ""
  $bolError = $false

  # =============================================================================================================================================
  # Check if incorrect combination of parameters is used. If so, correct it or throw an error. 
  # Incorrect combinations are 
  #   - LookFor is used, but no InTitle and InCommand parameters
  #   - CopyFiles is used, but no InTitle and InCommand parameters
  #   - CopyFiles is used, but no To parameter
  # =============================================================================================================================================

  if($LookFor -and (-not($InTitle) -and (-not $InCommandLine) -and (-not $GroupOrUser)))
   {
    $bolError = $true
    $Message = "[Error] LookFor is used, but not InTitle, InCommand or Group or User. Please specify either the InTitle, InCommand or GroupOrUser parameter."
   }

  if($CopyFiles -and (-not($InTitle) -and (-not $InCommandLine)))
   {
    $bolError = $true
    $Text     = "[Error] CopyFiles is used, but not InTitle and InCommand. Please specify either the InTitle or InCommand parameter."
    if(-not($Message))
     {
      $Message = $Text
     }
      else
     {
      $Message = "`n$text"
     }
    }

  if(-not($To) -and $CopyFiles)
   {
    $bolError = $true
    $Text     = "[Error] CopyFiles is used, but To has not been specified. Please specify the To location."
    if(-not($Message))
     {
      $Message = $Text
     }
      else
     {
      $Message = "`n$text"
     }
    }


  $Global:arrTable        = @()
  $Global:DetailedLogging = $DetailedLogging
  $Global:LogFile         = ""
  $Global:LookFor         = $LookFor
  $Global:InTitle         = $InTitle
  $Global:InCommandLine   = $InCommandLine
  $Global:CopyFiles       = $CopyFiles
  $Global:To              = $To
  $Global:Delimiter       = $Delimiter
  $Global:GroupOrUser     = $GroupOrUser
  $Results                = @()
  $valCounter             = 1
  $bolMaxComputers        = $False
  
  if($LogPath -eq "")
   {
    $LogPath   = Split-Path -parent $MyInvocation.MyCommand.Definition
   }
    else
   {
    $Returntext, $bolResult = Create-Folder -FolderName $LogPath
    if($bolResult)
     {
      if(-not($Message))
       {
        $Message = $Returntext
       }
        else
       {
        $Message = "`n$Returntext"
       }
     }
      else
     {
      Write-Error $Returntext -Category WriteError
      Exit 2
     }
   }

# =============================================================================================================================================
# Define the results file. This file contains all the results.
# =============================================================================================================================================
 
  $strLastPartOfFileName = " (" + (Get-Date).ToString('G') + ").csv"
  $strLastPartOfFileName = $strLastPartOfFileName -replace ":","-"
  $strLastPartOfFileName = $strLastPartOfFileName -replace "/","-"
  $PreFixLogFile         = "ExportIvantiBuildingBlock"

  $strCSVLogFileSucces   = $LogPath + "\"+ $PreFixLogFile + $strLastPartOfFileName

  if($Global:DetailedLogging)
   {
    $Global:LogFile = $LogPath + "\"+ $PreFixLogFile + $($strLastPartOfFileName -replace ".csv",".log")
    New-Item $Global:LogFile -ItemType File -Force | Out-Null
   }

   if($Message)
    {
     if(-not($bolError))
      {
       Add-EntryToLogFile -Entry "[Warning]: $Message"
      }
       else
      {
       Add-EntryToLogFile -Entry "$Message"
       Add-EntryToLogFile -Entry "This script will now quit."
       Write-Error $Message -Category CloseError
       Exit 3
      }
    }

# =============================================================================================================================================
# Find all the arguments and put them in the log file
# Source: https://ss64.com/ps/psboundparameters.html
# =============================================================================================================================================

  ForEach($boundparam in $PSBoundParameters.GetEnumerator()) 
   {
    Add-EntryToLogFile -Entry "Key: $($boundparam.Key) Value: $($boundparam.Value)" 
   }



# =============================================================================================================================================
# Create the folder where all the files have to be copied to. Only if the To parameter is used.
# =============================================================================================================================================

  if($To)
   {
    $Returntext, $bolResult = Create-Folder -FolderName $To
    if($bolResult)
     {
      Add-EntryToLogFile -Entry "The folder $To has been created successfully."
     }
      else
     {
      $Text = "There was an error while creating the folder $To. The script will stop now."
      Add-EntryToLogFile -Entry $Text
      Write-Error $Text -Category WriteError
      Exit 4
     }
   }

# =============================================================================================================================================
# Read the directory with all the computer names
# =============================================================================================================================================

  if($Directory -eq "")
   {
    $Directory   = Split-Path -parent $MyInvocation.MyCommand.Definition
   }

  $BuildingBlockFileNames = @(Get-ChildItem -Path $Directory -Filter *.xml -Recurse:$IncludeSubFolders | Sort-Object Path)

# =============================================================================================================================================
# Go through all the xml files.
# =============================================================================================================================================

  $TotalBuildingBlocks = $BuildingBlockFileNames.Count
  $valCounter          = 1

  ForEach ($BuildingBlockFileName in $BuildingBlockFileNames)
   {
  
    Write-Progress -Id 1 -Activity "Processing all the exported building blocks." -Status "Processing building block $BuildingBlockFileName" -PercentComplete ($valCounter / $TotalBuildingBlocks * 100)
    if(test-path($BuildingBlockFileName.FullName))
     {
      $Global:BuildingBlockFileName = $BuildingBlockFileName.FullName
      Add-EntryToLogFile -Entry "Found: $Global:BuildingBlockFileName"
      Try
      {
      $BuildingBlockData = [xml](Get-Content -Path $Global:BuildingBlockFileName)
      if(($BuildingBlockData.respowerfuse.buildingblock.application.guid) -and (CheckXMLFile -XMLFile $Global:BuildingBlockFileName))
       {
        Add-EntryToLogFile -Entry "Processing: $Global:BuildingBlockFileName"
        FindInfoInBuildingBlock -BuildingBlockDetails $BuildingBlockData -Filename $BuildingBlockFileName
       }
        else
       {
        Add-EntryToLogFile -Entry "It seems that $($BuildingBlockFileName.FullName) is not a real Ivanti application building block.`nThus skipping.`n"
       }
      }
      Catch
      {
       Add-EntryToLogFile -Entry ""
       Add-EntryToLogFile -Entry "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
       Add-EntryToLogFile -Entry ""
       Add-EntryToLogFile -Entry "There is an error in the xml file $($BuildingBlockFileName.FullName)."
       Add-EntryToLogFile -Entry ""
       Add-EntryToLogFile -Entry "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
       Add-EntryToLogFile -Entry ""         
      }
     }
    $valCounter++
   } 

# =============================================================================================================================================
# Export the CSV file.
# Exit afterwards.
# =============================================================================================================================================

  Export-ResultsLogFileToCSV

The application ExportIvantiBuildingBlockStartMenuItemsToCSV_v01.ps1 has the following parameters:

 

The output of the command .\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1 -Detailed

NAME
    C:\tmp\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1
    
SYNOPSIS
    Finds the Start Menu Items in Ivanti Workspace Control Building Blocks and export them to a CSV file.
    
    
SYNTAX
    C:\tmp\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1 -Directory <String> [-LogPath <String>] 
    [-IncludeSubFolders] [-DetailedLogging] [-LookFor] [-InTitle <String[]>] [-InCommandLine <String[]>] [-GroupOrUser 
    <String[]>] [-CopyFiles] [-To <String>] [-Delimiter <String>] [<CommonParameters>]
    
    
DESCRIPTION
    An Ivanti Building Block contains all kind of information about a Start Menu item. This script exports the most 
    used details to a CSV file.
    

PARAMETERS
    -Directory <String>
        
    -LogPath <String>
        
    -IncludeSubFolders [<SwitchParameter>]
        
    -DetailedLogging [<SwitchParameter>]
        
    -LookFor [<SwitchParameter>]
        
    -InTitle <String[]>
        
    -InCommandLine <String[]>
        
    -GroupOrUser <String[]>
        
    -CopyFiles [<SwitchParameter>]
        
    -To <String>
        
    -Delimiter <String>
        
    <CommonParameters>
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see 
        about_CommonParameters (https:/go.microsoft.com/fwlink/?LinkID=113216). 
    
    -------------------------- EXAMPLE 1 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles
    
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles
    
    
    
    
    -------------------------- EXAMPLE 2 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and its subfolders
    
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders
    
    
    
    
    -------------------------- EXAMPLE 3 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp
    
    
    
    
    -------------------------- EXAMPLE 4 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp.
    
    The delimiter character is ','
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -Delimiter ","
    
    
    
    
    -------------------------- EXAMPLE 5 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    Check if the executable excel.exe or winword.exe is used in the commandline
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -LookFor -InCommandLine excel.exe,winword.exe
    
    
    
    
    -------------------------- EXAMPLE 6 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    Check if Microsoft is used in the title.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -LookFor -InTitle Office
    
    
    
    
    -------------------------- EXAMPLE 7 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    Check if Microsoft is used in the title. Use detailed logging to a log file.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -LookFor -InTitle Office -DetailedLogging
    
    
    
    
    -------------------------- EXAMPLE 8 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    Check if the group name 'Appl_Visio' is used.
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -LookFor -GroupName Appl_Visio
    
    
    
    
    -------------------------- EXAMPLE 9 --------------------------
    
    PS C:\>Run an inventory on all the building blocks in the folder \\server\path\to\xmlfiles and store the result 
    file in c:\tmp
    
    Copy all the building block files that have msedge.exe or iexplore.exe in the command line to c:\tmp-internet
    ."ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1" -Directory \\server\path\to\xmlfiles -IncludeSubFolders 
    -LogPath c:\tmp -LookFor -InCommandLine msedge.exe,iexplore.exe -CopyFiles -To c:\tmp-internet
    
    
    
    
REMARKS
    To see the examples, type: "get-help C:\tmp\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1 -examples".
    For more information, type: "get-help C:\tmp\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1 -detailed".
    For technical information, type: "get-help C:\tmp\ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.ps1 -full".



 

And an example from the generated CSV file, opened with Excel:

 

Attachments:
Download this file (ExportIvantiBuildingBlockStartMenuItemsToCSV_v01.7z)ExportIvantiBuildingBlockStartMenuItemsToCSV_v01[ExportIvantiBuildingBlockStartMenuItemsToCSV_v01]15 kB
Download this file (ExportIvantiBuildingBlockStartMenuItemsToCSV_v02.7z)ExportIvantiBuildingBlockStartMenuItemsToCSV_v02[ExportIvantiBuildingBlockStartMenuItemsToCSV_v02]16 kB
Download this file (ExportIvantiBuildingBlockStartMenuItemsToCSV_v03.7z)ExportIvantiBuildingBlockStartMenuItemsToCSV_v03[ExportIvantiBuildingBlockStartMenuItemsToCSV_v03]17 kB