The operation failed because the settings for the packages in the connection group are not identical
AppV 5.0 connection groups are causing a lot of issues. Sometimes you can add them, but not enable them. You receive an error message similar to this one.
If you dig in the documentation you see that the COM objects need to be the same across all the applications that are a part of the connection group. You will have to check each deployment file and check it. If the connection group contains a lot of applications that are a hassle. So it is easier to have an overview of all the published applications on a computer. Then you see quickly which application needs to be modified.
Therefore, I created a PowerShell script that runs that inventory for you. You will get an overview of the following objects, including the package name, write mode, objects enabled, fonts enabled, COM Mode, In Process Enabled, Out of Process enabled and the connection group(s) to which the application belongs.
The details can be exported to a CSV file or HTML page.
While creating this PowerShell script I had some challenges.
Config files
I read the AppXManifest.xml file, but not all the information was present. So I had to make sure that the information that was a part of the deployment XML file was included in this overview as well. On https://docs.microsoft.com/en-us/microsoft-desktop-optimization-pack/appv-v5/application-publishing-and-client-interaction51 I found that the various XML files are applied in this order:
- AppXManifest.XML file
- Manifest.xml and DeploymentConfiguration.xml (only if published globally)
- UserManifest.xml and DynamicConfiguration.xml (depends on the boolean published globally).
But the question remains: where are these files stored?
The short answer is in the GetDynamicDeploymentConfigurationPath and GetDynamicUserConfigurationPath methods of Get-AppVClientPackage.
And now in more detail. If you type the following...
Get-AppVClientPackage | Get-Member
... then you will get the following output:
TypeName: Microsoft.AppV.AppvClientPowerShell.AppvClientPackage
Name MemberType Definition
---- ---------- ----------
Add Method void Add(string path, string policy)
CancelMount Method void CancelMount()
Equals Method bool Equals(System.Object obj)
GetApplications Method Microsoft.AppV.AppvClientPowerShell.AppvClientApplication[] GetAppl...
GetDynamicDeploymentConfigurationPath Method string GetDynamicDeploymentConfigurationPath()
GetDynamicUserConfigurationPath Method string GetDynamicUserConfigurationPath(bool global)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
Mount Method void Mount()
Publish Method void Publish(Microsoft.AppV.AppvClientFacade.PublishScope scope, st...
Remove Method void Remove(bool safeRemove)
Repair Method void Repair(Microsoft.AppV.AppvClientFacade.PublishScope scope, boo...
Set Method void Set(string path, string policy)
Stop Method void Stop(bool global)
ToString Method string ToString()
Unpublish Method void Unpublish(Microsoft.AppV.AppvClientFacade.PublishScope scope, ...
GlobalPending Property bool GlobalPending {get;}
HasAssetIntelligence Property bool HasAssetIntelligence {get;}
InUse Property bool InUse {get;}
InUseByCurrentUser Property bool InUseByCurrentUser {get;}
IsLoading Property bool IsLoading {get;}
IsPublishedGlobally Property bool IsPublishedGlobally {get;}
IsPublishedToUser Property bool IsPublishedToUser {get;}
Name Property string Name {get;}
PackageId Property guid PackageId {get;}
PackageSize Property uint64 PackageSize {get;}
Path Property string Path {get;}
PercentLoaded Property uint16 PercentLoaded {get;}
UserPending Property bool UserPending {get;}
Version Property string Version {get;}
VersionId Property guid VersionId {get;}
You can retrieve the information as follows:
(Get-AppVClientPackage -Name "AppV Package Name").GetDynamicDeploymentConfigurationPath()
If there is a result, then you can use that result. It is an XML file, and you can read it with the Get-Content command.
The second one is a little bit more complicated.
(Get-AppvClientPackage -Name "AppV Package Name").GetDynamicUserConfigurationPath((Get-AppVClientPackage -Name "AppV Package Name").IsPublishedGlobally)
And read the content with the Get-Content as well.
Applications as a part of a connection group
The second challenge was about the packages that are a part of a connection group.
If you enter:
Get-AppVClientConnectionGroup | Get-Member
Then you will get the following output:
TypeName: Microsoft.AppV.AppvClientPowerShell.AppvClientConnectionGroup
Name MemberType Definition
---- ---------- ----------
Add Method void Add(string path)
Disable Method void Disable(Microsoft.AppV.AppvClientFacade.PublishScope scope, string userSID)
Enable Method void Enable(Microsoft.AppV.AppvClientFacade.PublishScope scope, string userSID)
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetPackages Method Microsoft.AppV.AppvClientPowerShell.AppvClientPackage[] GetPackages()
GetType Method type GetType()
Mount Method void Mount()
Remove Method void Remove()
Repair Method void Repair(Microsoft.AppV.AppvClientFacade.PublishScope scope, bool deleteUserState, ...
Stop Method void Stop(bool global)
ToString Method string ToString()
GlobalPending Property bool GlobalPending {get;}
GroupId Property guid GroupId {get;}
InUse Property bool InUse {get;}
InUseByCurrentUser Property bool InUseByCurrentUser {get;}
IsEnabledGlobally Property bool IsEnabledGlobally {get;}
IsEnabledToUser Property bool IsEnabledToUser {get;}
Name Property string Name {get;}
PercentLoaded Property uint16 PercentLoaded {get;}
Priority Property uint32 Priority {get;}
UserPending Property bool UserPending {get;}
VersionId Property guid VersionId {get;}
Note: This only works if there are connection groups enabled.
The most important one is GetPackages. You will get an overview of all the packages that are a part of the connection group.
(Get-AppVClientConncectionGroup -Name "Some Name").GetPackages()
With that knowledge, it was easy for me to create the script.
The script has one requirement: a screen resolution of at least 1400 x 800 pixels. If this requirement is not met, the application will fall back into silent mode.
PowerShell ConstrainedLanguage e and FullLanguage Mode
During additional testing, I found that applocker can cause some issues. If script rules are defined, and the script is not run from %WINDIR% or %ProgramFiles% then the constrainedlanguage in PowerShell is effective. Then there is a limited set of commands available. That has been implemented.
Command line options
If you want to know all the command line options please run the following:
Get-Help ".\InformationAboutLoadedAppVPackages_v06.ps1" -Detailed
The output:
NAME
C:\tmp\InformationAboutPublishedAppVPackages_v06\InformationAboutPublishedAppVPackages_v06.ps1
SYNOPSIS
Displays information about published AppV packages in a grid.
SYNTAX
C:\tmp\InformationAboutPublishedAppVPackages_v06\InformationAboutPublishedAppVPackages_v06.ps1 [-Silent] [-LogPath
<String>] [-DetailedLogging] [-SaveAsHTMLPage] [-SaveAsCSVFile] [-SaveAsPDF] [-Summary] [-Delimiter <String>]
[<CommonParameters>]
DESCRIPTION
It gives detailed information about loaded AppV packages that are published on a system in a grid.
PARAMETERS
-Silent [<SwitchParameter>]
-LogPath <String>
-DetailedLogging [<SwitchParameter>]
-SaveAsHTMLPage [<SwitchParameter>]
-SaveAsCSVFile [<SwitchParameter>]
-SaveAsPDF [<SwitchParameter>]
-Summary [<SwitchParameter>]
-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:\>Start the application with a GUI.
."InformationAboutPublishedAppVPackages_v06.ps1"
-------------------------- EXAMPLE 2 --------------------------
PS C:\>Start the application with a GUI and detailed logging to c:\tmp
."InformationAboutPublishedAppVPackages_v05.ps1" -DetailedLogging -LogPath c:\tmp
-------------------------- EXAMPLE 3 --------------------------
PS C:\>Start the application with a GUI and verbose output
."InformationAboutPublishedAppVPackages_v06.ps1" -Verbose
-------------------------- EXAMPLE 4 --------------------------
PS C:\>Start the application with silent and export the result to a CSV file.
."InformationAboutPublishedAppVPackages_v06.ps1" -Silent -SaveAsCSVFile
-------------------------- EXAMPLE 5 --------------------------
PS C:\>Start the application with silent and export the result to a CSV file and use a comma as de delimiter
."InformationAboutPublishedAppVPackages_v06.ps1" -Silent -SaveAsCSVFile -Delimiter ","
-------------------------- EXAMPLE 6 --------------------------
PS C:\>Start the application but only the following columns are shown:
- Display Name
- Package and version ID
- Package Version
- Published globally
- Published to user
- COM Mode
- InProcess Enabled
- Out of Process Enabled
- Objects Enabled
- Connection group
."InformationAboutPublishedAppVPackages_v05.ps1" -Summary
REMARKS
To see the examples, type: "get-help
C:\tmp\InformationAboutPublishedAppVPackages_v06\InformationAboutPublishedAppVPackages_v06.ps1 -examples".
For more information, type: "get-help
C:\tmp\InformationAboutPublishedAppVPackages_v06\InformationAboutPublishedAppVPackages_v06.ps1 -detailed".
For technical information, type: "get-help
C:\tmp\InformationAboutPublishedAppVPackages_v06\InformationAboutPublishedAppVPackages_v06.ps1 -full".
More background information:
PowerShell error message stating that the connection group could not be created as there is a mismatch with the virtual COM settings.
Check the COM Mode settings from the marked applications (with the summary parameter).
And now with the corrected deployment XML files used (with the summary parameter).
Now, with detailed connection group information (with the summary parameter).
And you can create an HTML overview (with the summary parameter).
If you do not include the summary parameter, then you will get this overview:
(I played with the Edge Chromium 'zoom'-function to get all the columns in the overview)
Then you have a clear overview of the used XML files.
The application failed to launch
If the connection group has been created successfully, you can get an error 'The application failed to launch.', followed by an error code while starting an application that is a part of the connection group.
And the 2 characters before the hyphen sign in the error code are the critical factor to the solution.
In this case, the 2 characters before the hyphen sign are 0A. In the table below you can find that the Virtual Subsystem is causing issues:
Hex Code | Category | Hex Code | Category |
01 | Integration | 0B | Subsystem Controller |
02 | Orchestration | 0C | Streaming Manager |
03 | Client Service | 0D | ISV API |
04 | Virtualization Manager | 0E | Client Host |
05 | Shared Component | 0F | Client Configuration |
06 | Catalog | 10 | Scripting |
07 | Publishing | 11 | Client User Interface |
08 | Client Common | 12 | Sequencer |
09 | Policy | 13 | Reporting |
0A | Virtualization Subsystem | 14 | Manifest |
You also see that in the Event Viewer:
Luckily, you can disable virtual objects globally. How to do that is explained in the article Hidden App-V Registry Keys.
In this example the Virtual Objects subsystem has been disabled globally via the registry:
The globally disabled subsystems are also shown in the overview. The column that subsystem has been disabled globally has a grey background colour. You can disable more items if you like. But you will have to verify that all the applications are working correctly.
With the virtual objects globally disabled (with the summary parameter) (1/2)
With the virtual objects globally disabled (with the summary parameter) (2/2)
And now the script:
<#
.SYNOPSIS
Displays information about published AppV packages in a grid.
.DESCRIPTION
It gives detailed information about loaded AppV packages that are published on a system in a grid.
.EXAMPLE
Start the application with a GUI.
."InformationAboutPublishedAppVPackages_v06.ps1"
.EXAMPLE
Start the application with a GUI and detailed logging to c:\tmp
."InformationAboutPublishedAppVPackages_v05.ps1" -DetailedLogging -LogPath c:\tmp
.EXAMPLE
Start the application with a GUI and verbose output
."InformationAboutPublishedAppVPackages_v06.ps1" -Verbose
.EXAMPLE
Start the application with silent and export the result to a CSV file.
."InformationAboutPublishedAppVPackages_v06.ps1" -Silent -SaveAsCSVFile
.EXAMPLE
Start the application with silent and export the result to a CSV file and use a comma as de delimiter
."InformationAboutPublishedAppVPackages_v06.ps1" -Silent -SaveAsCSVFile -Delimiter ","
.EXAMPLE
Start the application but only the following columns are shown:
- Display Name
- Package and version ID
- Package Version
- Published globally
- Published to user
- COM Mode
- InProcess Enabled
- Out of Process Enabled
- Objects Enabled
- Connection group
."InformationAboutPublishedAppVPackages_v05.ps1" -Summary
.NOTES
Author: Willem-Jan Vroom
Website: https://www.vroom.cc/
Twitter: @TheStingPilot
v0.1:
* Initial version.
v0.2:
* Added:
- Shortcuts -> enabled (true or false)
- FileTypeAssociations -> enabled (true or false)
- Registry -> enabled (true or false)
- FileSystem -> enabled (true or false)
- EnvironmentVariables -> enabled (true or false)
- Services -> enabled (true or false)
- DeploymentConfigFiles that are used.
* Added the parameter:
- Summary
* Some coding improvements.
* The inventory is run immediately after starting the GUI.
v0.3:
* Added: an overview of the globally disabled items:
- Integration
- Virtual Fonts
- Just-in-timeVirtualization
- Virtual Registry
- Virtual Filesystem
- Virtual COM
- Virtual Objects
- Virtual Environment
- Registry Staging
- Virtual Services
- Virtual Shell
* Shortcuts instead of applications in the shortcut-column
v0.4:
* Option to print to PDF with the swith 'SaveAsPDF'
* Messagebox for all the messages.
* The buttons 'Save as PDF and exit', 'Save as HTML and exit' and 'Save as CSV and exit' are replaced by a new button 'Save options'.
Then a new window will pop-up and the user can select the items to print.
The button 'Globally subsystems' has a new position, next to 'Connection group information'.
v0.5:
* Get-AppVClientPackage has been replaced by Get-AppVClientPackage -All in the function Process-AppVPackages.
* PowerShell LanguageMode is detected. Usefull when AppLocker is effective.
v0.6:
* Changed the date notation of the logfile to yyyy-MM-dd HH-mm-ss, for example '2022-11-14 22-23-09'.
* Userdetails has been added
* Improved error handlling
#>
[CmdletBinding(DefaultParameterSetName = 'Default')]
Param
(
[Parameter(HelpMessage='Perform all the actions silently.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $Silent,
[Parameter(HelpMessage='Specify the log directory.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[String] $LogPath = "",
[Parameter(HelpMessage='Enable detailed logging to a log file.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $DetailedLogging,
[Parameter(HelpMessage='Save as an HTML file.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $SaveAsHTMLPage,
[Parameter(HelpMessage='Save as an CSV file.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $SaveAsCSVFile,
[Parameter(HelpMessage='Save as a PDF file.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $SaveAsPDF,
[Parameter(HelpMessage='Only show a limit set of columns in the HTML page or CSV file.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $Summary,
[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 / Modified 09-May-2022: Includes the function name
Created by: Willem-Jan Vroom
Organization:
Functionname: Add-EntryToLogFile
=============================================================================================================================================
.SYNOPSIS
This function adds a line to a log file
#>
Param
(
[Parameter(Mandatory=$True)] [string] $Entry,
[Parameter(Mandatory=$False)] [String] $FunctionName
)
Write-Verbose "[Function: $FunctionName] - $Entry"
If ($Global:gblDetailedLogging -and $Global:gblLogFile)
{
$Timestamp = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
Add-Content $Global:gblLogFile -Value $($Timestamp + "[Function: $FunctionName] - $Entry") -Force -ErrorAction SilentlyContinue
}
}
Function Display-MessageBox
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 24-May-2021 / 24-Apr-2024 / 09-June-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Display-MessageBox
=============================================================================================================================================
.SYNOPSIS
This function displays a message box.
The return value is:
None (no result) 0
OK 1
Cancel 2
Yes 6
No. 7
#>
param
(
[Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()][String] $Text,
[Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()][String] $Title,
[Parameter(Mandatory=$False)][Switch] $GUI,
[Parameter(Mandatory=$False)][Switch] $Error,
[Parameter(Mandatory=$False)][ValidateSet('Ok','AbortRetryIgnore','OkCancel','YesNoCancel','YesNo')][String] $Button = "Ok"
)
If ($GUI)
{
If ($Error)
{
$Return = [System.Windows.Forms.MessageBox]::Show($this,$Text.Trim(),$Title,$Button,"Error")
}
else
{
$Return = [System.Windows.Forms.MessageBox]::Show($this,$Text.Trim(),$Title,$Button,"Asterisk")
}
}
else
{
Write-Host "$Text`n"
Return 0
}
Return $($Return.value__)
}
Function UserDetails
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 03-Jan-21 / Modified on 14-Jan-21 / Modified on 22-Apr-22 / Modified on 01-May-2022 / Modified on 17-May-2022 /
Modified 21-Nov-2022
Created by: Willem-Jan Vroom
Functionname: UserDetails
=============================================================================================================================================
.SYNOPSIS
This function returns 4 details of the Current Logged In Usser
1. The username of the current logged in user
2. User\Domain of the current logged in user
3. User SID fo the User\Domain
4. Account name that is using the script
Initially, the scriptAccount was found with the command
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
But that command throws up an error due to the PowerShell ConstrainedMode.
Also, the output of whoami /user depends on the language. In the German language the output is different.
The header information is in the German language, so the header should be read from the CSV file.
That can be done with PSObject.Properties.Name
C:\Users\Test>whoami /user
BENUTZERINFORMATIONEN
---------------------
Benutzername SID
==================== ==============================================
windows10wkg_02\test S-1-5-21-1753037473-1212035439-1379364385-1001
On 21-Nov-2022 the function has been changed.
There are 6 situations that should be handled:
1. Find the logged on user sid when there is one user logged on on a 'normal' Windows computer
2. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where there is no local admin.
3. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where the users are local admin.
4. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on a 'normal' Windows computer.
This occurs during a Software Center installation performed under the SYSTEM account.
5. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on an RDS / Citrix environment.
6. Take care of the PowerShell Language Mode.
While testing I found that the MainWindowHandle is not 0 for the user that is running the explorer process. That is true for all the
above mentioned situations.
You can check while running this command with elevated rights:
get-process -IncludeUserName | Select-Object -Property Username, Id, Name,MainWindowHandle | Where {($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr")} | Format-Table
The output will be something like this:
UserName Id Name MainWindowHandle
-------- -- ---- ----------------
DEMO\user1 1380 explorer 0
DEMO\adminuser2 6556 explorer 131134
So, you have to continue with PID ID 6556.
So, I used the method of finding the PID, and use that PID as a condition for the Get-WMIObject to search for the explorer or pfwsmgr
process with that PID.
#>
# =============================================================================================================================================
# Find the current logged on user by checking the rights on the explore.exe (of pfwsmgr.exe with Ivanti Workspace Control) process.
# If the language mode is FullLanguage then use MainWindowHandle. That is needed when this script is run from SYSTEM context. I assume that
# the SYSTEM account is not effected by the PowerShell Language Mode.
# If the language mode is not FullLanguage then use a check on username and the owner of the explorer or pfwsmgr process.
# =============================================================================================================================================
if($Global:gblFullLanguage)
{
$PIDID = (get-process | Select-Object -Property Id, Name, MainWindowHandle | Where {(($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr") -and $($_.MainWindowHandle).ToInt32() -gt 0)}).Id
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer' or 'pfwsmgr' has the PID $PIDID."
$Explorer = (Get-WMIObject -Query "Select * From Win32_Process Where (ProcessId=$PIDID)")
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process with PID $PIDID has the name $($Explorer.Name)."
$UserName = $Explorer.GetOwner()
$SID = ($Explorer.GetOwnerSID()).SID
}
else
{
$Explorer = @(Get-WMIObject -Query "Select * From Win32_Process Where (Name='explorer.exe' or Name='pfwsmgr.exe')")
$EnvUSERNAME = $Env:USERNAME
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer.exe' or 'pfwsmgr.exe' is running $($Explorer.Count) times."
For ($a=0; $a -le ($Explorer.Count); $a++)
{
$UserName = ($Explorer[$a]).GetOwner()
If ($($UserName.User) -eq $EnvUSERNAME)
{
$SID = (($Explorer[$a]).GetOwnerSID()).SID
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "A valid SID '$SID' has been found for user '$EnvUSERNAME'."
Break
}
}
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found domain: $($UserName.Domain)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found username: $($UserName.User)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found SID: $SID."
$UserAndDomain = "$($Username.Domain )\$($Username.User)".ToUpper()
$tmpScriptAccount = (whoami /user /FO csv | convertfrom-csv)
$TranslatedUserName = $tmpScriptAccount.PSObject.Properties.Name[0]
$ScriptAccount = $($tmpScriptAccount.$TranslatedUserName).ToUpper()
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found scriptaccount: $ScriptAccount"
Return $($Username.User),$UserAndDomain,$SID,$ScriptAccount
}
Function Test-Service
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 24-May-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Test-Service
=============================================================================================================================================
.SYNOPSIS
This function tests if the given service exists and in case yes, if running.
If the service does not exists or is not running, the function returns a false
#>
param
(
[String] $Name
)
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Testing service '$Name'."
Try
{
$ServiceDetails = Get-Service -Name $Name -ErrorAction SilentlyContinue
if ($ServiceDetails.Status -eq "Running")
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The service '$Name' is running."
Return $True
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The service '$Name' is NOT running."
Return $False
}
}
Catch
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "There is an error: '$($_.Exception.Message)'."
Return $False
}
}
Function Write-CSVFile
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 06-September-2018 Modified on 27-April-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Write-CSVFile
=============================================================================================================================================
.SYNOPSIS
This function writes the content of a table to a CSV file.
#>
param
(
[String] $CSVFileWithResults,
[String] $DelimChar = ";",
[Switch] $GUI
)
If($Global:gblarrTable)
{
$Global:gblarrTable | Export-Csv $CSVFileWithResults -NoTypeInformation -Delimiter $DelimChar
$tmpLine = "The CSV file '$CSVFileWithResults' has been created."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry ">> Write-CSVFile: $tmpLine"
if($GUI)
{
Display-MessageBox -Text $tmpLine -GUI -Title "CSV File"
}
else
{
Display-MessageBox -Text $tmpLine -Title "CSV File"
}
}
else
{
$ErrorMessage = "Something went wrong while writing the CSV file '$CSVFileWithResults'. Maybe nothing to report..."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "[Error]: $ErrorMessage"
if($GUI)
{
Display-MessageBox -Text $ErrorMessage -GUI -Error -Title "CSV File"
}
else
{
Display-MessageBox -Text $ErrorMessage -Error -Title "CSV File"
}
}
}
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 information for the datagrid table
information.
#>
Param
(
[String] $DisplayName = "",
[String] $PackageAndVersionID = "",
[String] $PackageVersion = "",
[String] $PackageDescription = "",
[String] $PublishedGlobally = "",
[String] $PublishedToUser = "",
[String] $Shortcuts = "",
[String] $WriteMode = "",
[String] $ObjectsEnabled = "",
[String] $FontsEnabled = "",
[String] $COMMode = "-",
[String] $COMInProcessEnabled = "",
[String] $COMOutOfProcessEnabled = "",
[String] $ConnectionGroup = "",
[String] $ShortcutsEnabled = "",
[String] $FTAEnabled = "",
[String] $URLProtocolsEnabled = "",
[String] $RegistryEnabled = "",
[String] $FSEnabled = "",
[String] $EVEnabled = "",
[String] $ServicesEnabled = "",
[String] $DeploymentConfigFiles = ""
)
$Record = [ordered] @{"Display Name" = "";
"Package and version ID" = "";
"Package Version" = "";
"Package Description" = "";
"Published globally" = "";
"Published to user" = "";
"Shortcuts" = "";
"Full VFS Write Mode" = "";
"Deployment config files" = "";
"Shortcuts Enabled" = "";
"Filetype associatons Enabled" = "";
"URLProtocols Enabled" = "";
"COM Mode" = "";
"InProcess Enabled" = "";
"Out of Process Enabled" = "";
"Objects Enabled" = "";
"Registry Enabled" = "";
"Filesystem Enabled" = "";
"Fonts Enabled" = "";
"Environment variables Enabled" = "";
"Services Enabled" = "";
"Connection group" = "";
}
$Record."Display Name" = $DisplayName
$Record."Package and version ID" = $PackageAndVersionID
$Record."Package Version" = $PackageVersion
$Record."Package Description" = $PackageDescription
$Record."Published globally" = $PublishedGlobally
$Record."Published to user" = $PublishedToUser
$Record."Shortcuts" = $Shortcuts
$Record."Full VFS Write Mode" = $WriteMode
$Record."Deployment config files" = $DeploymentConfigFiles
$Record."Shortcuts Enabled" = $ShortcutsEnabled
$Record."Filetype associatons Enabled" = $FTAEnabled
$Record."URLProtocols Enabled" = $URLProtocolsEnabled
$Record."COM Mode" = $COMMode
$Record."InProcess Enabled" = $COMInProcessEnabled
$Record."Out of Process Enabled" = $COMOutOfProcessEnabled
$Record."Objects Enabled" = $ObjectsEnabled
$Record."Registry Enabled" = $RegistryEnabled
$Record."Filesystem Enabled" = $FSEnabled
$Record."Fonts Enabled" = $FontsEnabled
$Record."Environment variables Enabled" = $EVEnabled
$Record."Services Enabled" = $ServicesEnabled
$Record."Connection group" = $ConnectionGroup
$objRecord = New-Object PSObject -Property $Record
$Global:gblarrTable += $objRecord
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Display Name: $DisplayName"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Package and version: $PackageAndVersionID"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Package Version: $PackageVersion"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Package Description: $PackageDescription"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Published globally: $PublishedGlobally"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Published to user: $PublishedToUser"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Shortcuts: $Shortcuts"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Full VFS Write Mode: $WriteMode"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Deployment config files: $DeploymentConfigFiles"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Shortcuts Enabled: $ShortcutsEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Filetype associatons Enabled: $FTAEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "URLProtocols Enabled: $URLProtocolsEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "COM Mode: $COMMode"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "InProcess Enabled: $COMInProcessEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Out of Process Enabled: $COMOutOfProcessEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Objects Enabled: $ObjectsEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Registry Enabled: $RegistryEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Filesystem Enabled: $FSEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Fonts Enabled: $FontsEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Environment variables Enabled: $EVEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Services Enabled: $ServicesEnabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Connection group: $ConnectionGroup"
}
Function Add-EntryToConnectionGroupOverview
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 03-August-2018
Created by: Willem-Jan Vroom
Organization:
Functionname: Add-EntryToConnectionGroupOverview
=============================================================================================================================================
.SYNOPSIS
This function adds an entry to the connection group overview.
#>
Param
(
[String] $ConnName,
[String] $ConnPackages,
[String] $ConnEnabledToUser,
[String] $ConnEnabledGlobally,
[String] $ConnInUse,
[String] $ConnInUseByCurrentUser,
[Int] $ConnPriority
)
$Record = [ordered] @{"Connection group name" = "";
"Packages as a part of the connection group" = "";
"Enabled to User" = "";
"Enabled Globally" = "";
"In use" = "";
"In use by current user" = "";
"Priority" = "";
}
$Record."Connection group name" = $ConnName
$Record."Packages as a part of the connection group" = $ConnPackages
$Record."Enabled to User" = $ConnEnabledToUser
$Record."Enabled Globally" = $ConnEnabledGlobally
$Record."In use" = $ConnInUse
$Record."In use by current user" = $ConnInUseByCurrentUser
$Record."Priority" = $ConnPriority
$objRecord = New-Object PSObject -Property $Record
$Global:gblarrConnectionGroups += $objRecord
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Connection group name: $ConnName"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Packages as a part of the connection group: $ConnPackages"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Enabled to User: $ConnEnabledToUser"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Enabled Globally: $ConnEnabledGlobally"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "In use: $ConnInUse"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "In use by current user: $ConnInUseByCurrentUser"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Priority: $ConnPriority"
}
Function Add-EntryToGloballyEnabledOrDisabledItems
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 03-August-2018
Created by: Willem-Jan Vroom
Organization:
Functionname: Add-EntryToGloballyEnabledOrDisabledItems
=============================================================================================================================================
.SYNOPSIS
This function adds an entry to the table with all the globally enabled or disabled items.
#>
Param
(
[String] $SubsystemName,
[String] $Enabled,
[String] $Disabled
)
$Record = [ordered] @{"Subsystem name" = "";
"Enabled" = "";
"Disabled" = "";
}
$Record."Subsystem name" = $SubsystemName
$Record."Enabled" = $Enabled
$Record."Disabled" = $Disabled
$objRecord = New-Object PSObject -Property $Record
$Global:gblarrEnabledDisabled += $objRecord
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Subsystem name: $SubsystemName"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Enabled: $Enabled"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Disabled: $Disabled"
}
Function Write-HTMLFile
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 02-February-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Write-HTMLFile
=============================================================================================================================================
.SYNOPSIS
This function creates an HTML file.
#>
param
(
[String] $HTMLFileToWrite,
[Switch] $SaveAsPDFFile,
[Switch] $GUI
)
# =============================================================================================================================================
# Define the CSS file.
# =============================================================================================================================================
$Header = ""
$CSS = "<style type=$([char]34)text/css$([char]34)>`n"
$CSS += "table {`n"
$CSS += " font-size: 16px;`n"
$CSS += " border: 1px solid #395870;`n"
$CSS += " font-family: Arial, Helvetica, sans-serif;`n"
$CSS += " }`n`n"
$CSS += "td {`n"
$CSS += " padding: 5px;`n"
$CSS += " margin: 0px;`n"
$CSS += " border: 1px solid #395870;`n"
$CSS += " max-width: 700px;`n"
$CSS += " vertical-align: top;`n"
$CSS += " }`n`n"
$CSS += "th {`n"
$CSS += " background: #395870;`n"
$CSS += " background: linear-gradient(#49708f, #293f50);`n"
$CSS += " color: #fff;`n"
$CSS += " font-size: 14px;`n"
$CSS += " padding: 10px 15px;`n"
$CSS += " vertical-align: top;`n"
$CSS += " border: 1px solid #395870;`n"
$CSS += " }`n`n"
$CSS += "tr {`n"
$CSS += " width: 1000px;`n"
$CSS += " }`n`n"
$CSS += "h1 {`n"
$CSS += " font-family: Arial, Helvetica, sans-serif;`n"
$CSS += " color: #e68a00;`n"
$CSS += " font-size: 28px;`n"
$CSS += " text-align: center;`n"
$CSS += " }`n`n"
$CSS += "h2 {`n"
$CSS += " font-family: Arial, Helvetica, sans-serif;`n"
$CSS += " color: #000099;`n"
$CSS += " font-size: 16px;`n"
$CSS += " text-align: center;`n"
$CSS += " }`n`n"
$CSS += "#Cred {`n"
$CSS += " font-family: Arial, Helvetica, sans-serif;`n"
$CSS += " color: #0000ff;`n"
$CSS += " font-size: 12px;`n"
$CSS += " text-align: left;`n"
$CSS += " }`n`n"
$CSS += "tr:nth-child(even) {`n"
$CSS += " background: #CCC;`n"
$CSS += " }`n`n"
$CSS += "tr:nth-child(odd) {`n"
$CSS += " background: #FFF;`n"
$CSS += " }`n`n"
$CSS += "</style>"
$CSS += ""
# =============================================================================================================================================
# Replace the `n with <br> in various columns. So there is a proper table layout.
# Do some cleanup afterwards.
# =============================================================================================================================================
ForEach ($Record in $Global:gblarrTable)
{
If($Record."Shortcuts")
{
$Record."Shortcuts" = $Record."Shortcuts" -replace "`n","<br><br>"
}
If($Record."Connection group")
{
$Record."Connection group" = $Record."Connection group" -replace "`n","<br><br>"
}
If($Record."Deployment config files")
{
$Record."Deployment config files" = $Record."Deployment config files" -replace "`n","<br><br>"
}
If($Record."Package and version ID")
{
$Record."Package and version ID" = $Record."Package and version ID" -replace "`n","<br><br>"
}
}
ForEach ($Record in $Global:gblarrConnectionGroups)
{
If($Record."Packages as a part of the connection group")
{
$Record. "Packages as a part of the connection group" = $Record. "Packages as a part of the connection group" -replace "`n","<br><br>"
}
}
$HTMLTable = ""
if($SaveAsPDFFile)
{
$Global:gblarrTable = $Global:gblarrTable |Sort-Object -Property "Display Name"
ForEach ($Record in $Global:gblarrTable)
{
$HTMLTable += $Record | ConvertTo-Html -Fragment -As List
$HTMLTable += "<br>"
}
$A4Pixels = 595 * .9
$Table1_Width = $A4Pixels *.3
$Table1_Width = $A4Pixels *.7
$HTMLTable = $HTMLTable -replace ("<table>","<table width=$($A4Pixels)px>")
$HTMLTable = $HTMLTable -replace ("<tr><td>","<tr><td width=$($Table1_Width)px>")
$HTMLTable = $HTMLTable -replace ("</td><td>","</td><td width=$($Table1_Width)px>")
$HTMLTable = $HTMLTable -replace ("</table>","</table>`n")
}
else
{
$HTMLTable = $Global:gblarrTable |Sort-Object -Property "Display Name" | ConvertTo-Html -Fragment
}
$HTMLTable = [System.Web.HttpUtility]::HtmlDecode($HTMLTable)
$Title = "<h1>Overview of all the AppV Packages published on the computer $($Global:gblComputerName)</h1>"
$Body = "$Title<h2>Table</h2>$HTMLTable"
# =============================================================================================================================================
# If applicable: add information about the connection groups to the HTML page.
# =============================================================================================================================================
if($Global:gblarrConnectionGroups.Count -gt 0)
{
if($Global:gblarrConnectionGroups.Count -gt 1)
{
$Global:gblarrConnectionGroups = $Global:gblarrConnectionGroups | Sort-Object -Property Priority
}
if($SaveAsPDFFile)
{
$HTMLConnectionGroupOverview = ""
ForEach ($Record in $Global:gblarrConnectionGroups)
{
$HTMLConnectionGroupOverview += $Record | ConvertTo-Html -Fragment -As List
$HTMLConnectionGroupOverview += "<br>"
}
}
else
{
$HTMLConnectionGroupOverview = $Global:gblarrConnectionGroups | ConvertTo-Html -Fragment
}
$HTMLConnectionGroupOverview = [System.Web.HttpUtility]::HtmlDecode($HTMLConnectionGroupOverview)
$Body +="<br><h2>Overview of the connection groups.</h2><br>$HTMLConnectionGroupOverview"
}
# =============================================================================================================================================
# If applicable: add information about globally enabled or disabled subsystems to the HTML page.
# =============================================================================================================================================
if($Global:gblarrEnabledDisabled.Count -gt 0)
{
if($Global:gblarrEnabledDisabled.Count -gt 1)
{
$Global:gblarrEnabledDisabled = $Global:gblarrEnabledDisabled | Sort-Object -Property "Subsystem Name"
}
if($SaveAsPDFFile)
{
$HTMLEnabledOrDisabledSubsystems = ""
ForEach ($Record in $Global:gblarrEnabledDisabled)
{
$HTMLEnabledOrDisabledSubsystems += $Record | ConvertTo-Html -As List -Fragment
$HTMLEnabledOrDisabledSubsystems += "<br>"
}
}
else
{
$HTMLEnabledOrDisabledSubsystems = $Global:gblarrEnabledDisabled | ConvertTo-Html -Fragment
}
$HTMLEnabledOrDisabledSubsystems = [System.Web.HttpUtility]::HtmlDecode($HTMLEnabledOrDisabledSubsystems)
$Body +="<br><h2>Overview of the disabled and enabled subsystems.</h2><br>$HTMLEnabledOrDisabledSubsystems"
}
# =============================================================================================================================================
# If applicable: add information about the used parameters to the HTML page.
# =============================================================================================================================================
if($TableWithParameters.Count -gt 0)
{
if($SaveAsPDFFile)
{
$HTMLParameterstable = ""
ForEach ($Record in $TableWithParameters)
{
$HTMLParameterstable += $Record | ConvertTo-Html -As List -Fragment
$HTMLParameterstable += "<br>"
}
}
else
{
$HTMLParameterstable = $TableWithParameters | ConvertTo-Html -Fragment
}
$Body +="<br><h2>Used parameters for the script.</h2><br>$HTMLParameterstable"
}
# =============================================================================================================================================
# Load all the DLL files that are needed for IText7 HTML To PDF
# See https://kb.itextsupport.com/home/it7kb/ebooks/itext-7-converting-html-to-pdf-with-pdfhtml for more information.
# For licensing issues the following files are not included in the zip package:
# - BouncyCastle.Crypto.dll
# - Common.Logging.Core.dll / .pdb / .xml
# - Common.Logging.dll / .pdb / .xml
# - itext.barcodes.dll / .xml
# - itext.forms.dll / .xml
# - itext.html2pdf.dll / .xml
# - itext.io.dll / .xml
# - itext.kernel.dll / .xml
# - itext.layout.dll / .xml
# - itext.pdfa.dll / .xml
# - itext.sign.dll / .xml
# - itext.styledxmlparser.dll / .xml
# - itext.svg.dll / .xml
# =============================================================================================================================================
$DLLFilesLoadedSuccessfully = $True
if($SaveAsPDFFile)
{
if($Global:gblDLLPathExists)
{
$DLLFiles = Get-ChildItem -Path $Global:gblDLLPath -Filter *.dll -File
ForEach ($DLLFile in $DLLFiles)
{
Try
{
Add-Type -Path $($DLLFile.FullName)
Add-EntryToLogFile "The DLL file '$($DLLFile.FullName)' has been loaded successfully."
}
Catch
{
$DLLFilesLoadedSuccessfully = $False
Add-EntryToLogFile "Failure while loading the DLL file '$($DLLFile.FullName)': $($_.Exception.Message)."
}
}
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The path '$Global:gblDLLPath' does not exists. As these DLL's are needed, the PDF file cannot be created."
}
}
# =============================================================================================================================================
# The footer and create the HTML page.
# =============================================================================================================================================
$Timestamp = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
$PostContent = "<p id=$([char]34)Cred$([char]34)>Creation Date: $Timestamp</p>"
$Report = ConvertTo-Html -Head $CSS -Body $Body -PostContent $PostContent
if($SaveAsPDFFile)
{
if($Global:gblDLLPathExists)
{
if($DLLFilesLoadedSuccessfully)
{
$PDFFileToWrite = [System.IO.FileInfo]::new($HTMLFileToWrite -replace("html","pdf"))
$HTMLFileToWrite = $env:TEMP + "\TempHTMLFile.html"
$Report | Out-File $HTMLFileToWrite
$HTMLInputFile = [System.IO.FileInfo]::new($HTMLFileToWrite)
[iText.Html2Pdf.HtmlConverter]::ConvertToPdf($HTMLInputFile, $PDFFileToWrite)
$tmpLine = "The PDF file '$PDFFileToWrite' has been created."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry $tmpLine
if($GUI)
{
Display-MessageBox -GUI -Text $tmpLine -Title "PDF Document"
}
else
{
Display-MessageBox -Text $tmpLine -Title "PDF Document"
}
Remove-Item -Path $HTMLFileToWrite
}
else
{
$tmpLine = "There where errors while loading the DLL files from '$Global:gblDLLPath'. So no PDF file is created."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry $tmpLine
if($GUI)
{
Display-MessageBox -GUI -Text $tmpLine -Title "PDF Document"
}
else
{
Display-MessageBox -Text $tmpLine -Title "PDF Document"
}
}
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The path '$Global:gblDLLPath' does not exists. So the PDF file is not created as it needs files in that directory."
}
}
else
{
$Report | Out-File $HTMLFileToWrite
$tmpLine = "The webpage '$HTMLFileToWrite' has been created."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry $tmpLine
if($GUI)
{
Display-MessageBox -GUI -Text $tmpLine -Title "HTML File"
}
else
{
Display-MessageBox -Text $tmpLine -Title "HTML File"
}
}
}
Function Read-Registry
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 13-February-2021 / Modified 14-May-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Read-Registry
=============================================================================================================================================
.SYNOPSIS
This function reads a registry key and returns the value
#>
param
(
[Parameter(Mandatory=$True)] [String]$RegistryKey,
[Parameter(Mandatory=$True)] [String]$ValueName
)
if(Test-Path ($RegistryKey))
{
$Value = (Get-ItemProperty -Path $RegistryKey).$ValueName
if(($Value -ne $null) -and ($Value.Length -ne 0))
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The registrykey '$RegistryKey' with valuename '$ValueName' exists."
$PropertyType = (Get-Item $RegistryKey).GetValueKind($ValueName)
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Hive: $RegistryKey"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " - ValueName: $ValueName"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " - Type: $PropertyType"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " - Value: $Value"
if($PropertyType -eq "String")
{
Return $Value
}
elseif($PropertyType -eq "DWord")
{
if($Value -eq 1)
{
Return $True
}
else
{
Return $False
}
}
}
}
Return [string]::Empty
}
Function Process-ShortcutsInAppVPackage
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 14-May-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Process-ShortcutsInAppVPackage
=============================================================================================================================================
.SYNOPSIS
This function processes all the shortcuts that are in an AppV package.
#>
param
(
[xml] $XMLContent,
[Switch] $UserConfig
)
$AllShortcuts = ""
$ShortcutCounter = 0
if($UserConfig)
{
$Shortcuts = @($XMLContent.UserConfiguration.Subsystems.Shortcuts.Extensions.Extension)
}
else
{
$Shortcuts = @($XMLContent.DeploymentConfiguration.UserConfiguration.Subsystems.Shortcuts.Extensions.Extension)
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "There a $($Shortcuts.Count) shortcuts found."
ForEach ($Shortcut in $Shortcuts)
{
$SingleShortcut = ""
$tmpFile = $Shortcuts[$ShortcutCounter].Shortcut.File
$tmpTarget = $Shortcuts[$ShortcutCounter].Shortcut.Target
$tmpArguments = $Shortcuts[$ShortcutCounter].Shortcut.Arguments
$tmpWorkingDir = $Shortcuts[$ShortcutCounter].Shortcut.WorkingDirectory
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " Shortcut details:"
if($tmpFile)
{
$tmpLine = "File: $tmpFile`n"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " $tmpLine"
$SingleShortcut += $tmpLine
}
if($tmpTarget)
{
$tmpLine = "Target: $tmpTarget $tmpArguments`n"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " $tmpLine"
$SingleShortcut += $tmpLine
}
if($tmpWorkingDir)
{
$tmpLine = "Working Dir: $tmpWorkingDir"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " $tmpLine"
$SingleShortcut += $tmpLine
}
if(-not($AllShortcuts))
{
$AllShortcuts = $SingleShortcut
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " "
$AllShortcuts += "`n`n$SingleShortcut"
}
$ShortcutCounter++
}
Return $AllShortcuts
}
Function Process-AppVPackages
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 02-February-2021 / Modified on 10-Dec-2021
Created by: Willem-Jan Vroom
Organization:
Functionname: Process-AppVPackages
=============================================================================================================================================
.SYNOPSIS
This function processes all published AppV Packages.
#>
param
(
[Switch] $GUI
)
$ProgramDataFolder = $env:ProgramData
$PublishedAppVPackages = Get-AppvClientPackage -All
$valCounter = 1
$valTotalAppVPackages = $PublishedAppVPackages.Count
$valConnectionGroups = (Get-AppvClientConnectionGroup).Count
if($GUI)
{
$lblAction.Text = "Running an inventory on the installed App-V 5 packages."
$btnCancel.Enabled = $False
$pgbProcessing.Step = $valCounter / $valTotalAppVPackages * 100
}
ForEach($PublishedAppVPackage in $PublishedAppVPackages)
{
$tmpPackageID = ($PublishedAppVPackage.PackageID).ToString()
$tmpVersionID = ($PublishedAppVPackage.VersionID).ToString()
$tmpPackageVersion = ($PublishedAppVPackage.Version).ToString()
$tmpDisplayName = ($PublishedAppVPackage.Name)
$tmpPublishedGlobally = ($PublishedAppVPackage.IsPublishedGlobally)
$tmpPublishedToUser = ($PublishedAppVPackage.IsPublishedToUser)
$tmpDeploymentConfigFiles = $null
$tmpShortcutsEnabled = $null
$tmpFTAEnabled = $null
$tmpObjectsEnabled = $null
$tmpFontsEnabled = $null
$tmpURLProtocolsEnabled = $null
$tmpRegistryEnabled = $null
$tmpFSEnabled = $null
$tmpEVEnabled = $null
$tmpServicesEnabled = $null
$tmpShortcuts = $null
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found an AppV 5 application with the following details:"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Name: $tmpDisplayName"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Package and version ID: $tmpPackageID / $tmpVersionID"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Version: $tmpPackageVersion"
if($GUI)
{
[int] $Percentage = $valCounter / $valTotalAppVPackages * 100
$lblAction.Text = "Processing: $tmpDisplayName (package $valCounter of $valTotalAppVPackages packages - $($Percentage)%)"
$pgbProcessing.PerformStep()
}
else
{
[int] $Percentage = $valCounter / $valTotalAppVPackages * 100
Write-Progress -Id 1 -Activity "Processing all the installed App-V packages. (package $valCounter of $valTotalAppVPackages packages - $($Percentage)%)" -Status "Processing App-V package $tmpDisplayName" -PercentComplete $Percentage
}
# =============================================================================================================================================
# Fist step: read the %ProgramData%\App-V\<PackageID>\<VersionID>\AppxManifest.xml
# =============================================================================================================================================
$AppxManifestXMLFile = $ProgramDataFolder + "\App-V\" + $tmpPackageID + "\" + $tmpVersionID + "\AppxManifest.xml"
[xml]$AppxManifest = (Get-Content -Path $AppxManifestXMLFile)
$tmpWriteMode = $AppXManifest.Package.Properties.FullVFSWriteMode
$tmpPackageDescription = $AppXManifest.Package.Properties.AppVPackageDescription
$tmpDeploymentConfigFiles = $AppxManifestXMLFile
if($tmpPublishedGlobally)
{
# =============================================================================================================================================
# Second step: (part 1): Read the manifest.xml file that is used. It is in the same location as the deployment configuration xml file.
# =============================================================================================================================================
$tmpGlobalDeploymentConfigFilesDir = Split-Path (($PublishedAppVPackage).GetDynamicDeploymentConfigurationPath())
$tmpGlobalDeploymentConfigFiles = $tmpGlobalDeploymentConfigFilesDir + "\Manifest.xml"
$tmpDeploymentConfigFiles += "`n" + $tmpGlobalDeploymentConfigFiles
[xml]$DeploymentConfiguration = (Get-Content -Path ((split-path $tmpGlobalDeploymentConfigFiles) + "\manifest.xml"))
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Reading the file '$tmpGlobalDeploymentConfigFiles'."
$tmpCOMMode = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.Mode
$tmpCOMInProcessEnabled = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.IntegratedCOMAttributes.InProcessEnabled
$tmpCOMOutOfProcessEnabled = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.IntegratedCOMAttributes.OutOfProcessEnabled
$tmpGlobalDeploymentConfigFiles = $tmpGlobalDeploymentConfigFilesDir + "\DeploymentConfiguration.xml"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Reading the file '$tmpGlobalDeploymentConfigFiles' for specific settings."
[xml]$DeploymentConfiguration = (Get-Content -Path $tmpGlobalDeploymentConfigFiles)
if($DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.HasChildNodes)
{
# =============================================================================================================================================
# Second step: (part 2): Read the global deployment config file only if there are settings applied. That is the case when the node
# DeploymentConfiguration.UserConfiguration has child nodes.
# =============================================================================================================================================
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> The file '$tmpGlobalDeploymentConfigFiles' is read. It contains settings."
$tmpDeploymentConfigFiles += "`n" + $tmpGlobalDeploymentConfigFiles
$tmpCOMMode = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.COM.Mode
$tmpCOMInProcessEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.COM.IntegratedCOMAttributes.InProcessEnabled
$tmpCOMOutOfProcessEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.COM.IntegratedCOMAttributes.OutOfProcessEnabled
$tmpObjectsEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.Objects.Enabled
$tmpFontsEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.Fonts.Enabled
$tmpShortcutsEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.Shortcuts.Enabled
$tmpFTAEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.FileTypeAssociations.Enabled
$tmpURLProtocolsEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.URLProtocols.Enabled
$tmpRegistryEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.Registry.Enabled
$tmpFSEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.FileSystem.Enabled
$tmpEVEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.EnvironmentVariables.Enabled
$tmpServicesEnabled = $DeploymentConfiguration.DeploymentConfiguration.UserConfiguration.Subsystems.Services.Enabled
$tmpShortcuts = Process-ShortcutsInAppVPackage -XMLContent $DeploymentConfiguration
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The file '$tmpGlobalDeploymentConfigFiles' does not contain settings."
}
}
if($tmpPublishedToUser)
{
# =============================================================================================================================================
# Third step: (part 1): Read the UserManifest.xml file that is used. It is in the same location as the deployment configuration xml file.
# =============================================================================================================================================
if(-not($Global:gblConstrainedLanguage))
{
$tmpDynamicConfiguration = ($PublishedAppVPackage).GetDynamicUserConfigurationPath($tmpPublishedGlobally)
if($tmpDynamicConfiguration)
{
$tmpUserManifestDir = Split-Path $tmpDynamicConfiguration
$tmpUserManifest = $tmpUserManifestDir + "\UserManifest.xml"
$tmpDeploymentConfigFiles += "`n" + $tmpUserManifest
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Reading the file '$tmpUserManifests'."
[xml]$DeploymentConfiguration = (Get-Content -Path $tmpUserManifest)
$tmpCOMMode = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.Mode
$tmpCOMInProcessEnabled = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.IntegratedCOMAttributes.InProcessEnabled
$tmpCOMOutOfProcessEnabled = $DeploymentConfiguration.Package.ExtensionsConfiguration.COM.IntegratedCOMAttributes.OutOfProcessEnabled
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> Reading the file '$tmpDynamicConfiguration' for specific settings."
[xml]$DynamicConfiguration = (Get-Content -Path $tmpDynamicConfiguration)
if($DynamicConfiguration.UserConfiguration.HasChildNodes)
{
# =============================================================================================================================================
# Third step: (part 2): Read the user deployment config file only if there are settings applied. That is the case when the node
# UserConfiguration has child nodes.
# =============================================================================================================================================
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " -> The application is published to a user. Reading the file '$tmpDynamicConfiguration' for specific settings."
$tmpDeploymentConfigFiles += "`n" + $tmpDynamicConfiguration
$tmpCOMMode = $DynamicConfiguration.UserConfiguration.Subsystems.COM.Mode
$tmpCOMInProcessEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.COM.IntegratedCOMAttributes.InProcessEnabled
$tmpCOMOutOfProcessEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.COM.IntegratedCOMAttributes.OutOfProcessEnabled
$tmpObjectsEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.Objects.Enabled
$tmpFontsEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.Fonts.Enabled
$tmpShortcutsEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.Shortcuts.Enabled
$tmpFTAEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.FileTypeAssociations.Enabled
$tmpURLProtocolsEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.URLProtocols.Enabled
$tmpRegistryEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.Registry.Enabled
$tmpFSEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.FileSystem.Enabled
$tmpEVEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.EnvironmentVariables.Enabled
$tmpServicesEnabled = $DynamicConfiguration.UserConfiguration.Subsystems.Services.Enabled
$NumberOfShortcuts = 0
$NumberOfShortcuts = $DynamicConfiguration.UserConfiguration.Subsystems.Shortcuts.Extensions.Extension.Count
$tmpShortcuts = Process-ShortcutsInAppVPackage -XMLContent $DynamicConfiguration -UserConfig
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The file '$tmpDynamicConfiguration' does not contain settings."
}
}
}
}
# =============================================================================================================================================
# Get all the connection groups where a application belongs to.
# =============================================================================================================================================
$ConnectionGroupNames = (Get-AppvClientConnectionGroup).Name
$tmpConnectionGroups = ""
ForEach ($ConnectionGroupName in $ConnectionGroupNames)
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " Processing connection group: $ConnectionGroupName"
$bolFound = (Get-AppvClientConnectionGroup -Name $ConnectionGroupName).GetPackages() | Where {$_.PackageId -eq $tmpPackageID}
if($bolFound)
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry " The package '$tmpDisplayName' is found in the connectiongroup '$ConnectionGroupName'"
if(-not($tmpConnectionGroups))
{
$tmpConnectionGroups = $ConnectionGroupName
}
else
{
$tmpConnectionGroups += "`n$ConnectionGroupName"
}
}
}
# =============================================================================================================================================
# Add the information to the results file.
# =============================================================================================================================================
Add-EntryToResultsFile -DisplayName $tmpDisplayName `
-PackageVersion $tmpPackageVersion `
-PackageAndVersionID $($tmpPackageID + "_`n" + $tmpVersionID) `
-PublishedGlobally $tmpPublishedGlobally `
-PublishedToUser $tmpPublishedToUser `
-Shortcuts $tmpShortcuts `
-COMMode $tmpCOMMode `
-COMInProcessEnabled $tmpCOMInProcessEnabled `
-COMOutOfProcessEnabled $tmpCOMOutOfProcessEnabled `
-ConnectionGroup $tmpConnectionGroups `
-PackageDescription $tmpPackageDescription `
-WriteMode $tmpWriteMode `
-ObjectsEnabled $tmpObjectsEnabled `
-FontsEnabled $tmpFontsEnabled `
-ShortcutsEnabled $tmpShortcutsEnabled `
-FTAEnabled $tmpFTAEnabled `
-URLProtocolsEnabled $tmpURLProtocolsEnabled `
-RegistryEnabled $tmpRegistryEnabled `
-FSEnabled $tmpFSEnabled `
-EVEnabled $tmpEVEnabled `
-ServicesEnabled $tmpServicesEnabled `
-DeploymentConfigFiles $tmpDeploymentConfigFiles
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "#################################################################`n`n"
$valCounter ++
}
# =============================================================================================================================================
# Find all the connection groups.
# =============================================================================================================================================
if($valConnectionGroups -gt 0)
{
ForEach ($ConnectionGroup in Get-AppvClientConnectionGroup)
{
$tmpConnName = $ConnectionGroup.Name
$tmpConnEnabledToUser = $ConnectionGroup.IsEnabledToUser
$tmpConnEnabledGlobally = $ConnectionGroup.IsEnabledGlobally
$tmpConnInUse = $ConnectionGroup.InUse
$tmpConnInUseByCurrentUser = $ConnectionGroup.InUseByCurrentUser
$tmpConnPriority = $ConnectionGroup.Priority
$tmpPackages = ""
ForEach ($PackageInConnectionGroup in $(($ConnectionGroup).GetPackages()))
{
$tmpLine = $PackageInConnectionGroup.Name + " (" + $PackageInConnectionGroup.Version + ")"
if(-not($tmpPackages))
{
$tmpPackages = $tmpLine
}
else
{
$tmpPackages += "`n$tmpLine"
}
}
Add-EntryToConnectionGroupOverview -ConnName $tmpConnName `
-ConnEnabledToUser $tmpConnEnabledToUser `
-ConnEnabledGlobally $tmpConnEnabledGlobally `
-ConnInUse $tmpConnInUse `
-ConnInUseByCurrentUser $tmpConnInUseByCurrentUser `
-ConnPriority $tmpConnPriority `
-ConnPackages $tmpPackages
}
}
# =============================================================================================================================================
# Find all the globally enabled or disabled items
# =============================================================================================================================================
$SubsystemItems = @("Integration","Virtual Fonts","Just-in-timeVirtualization","Virtual Registry","Virtual Filesystem","Virtual COM","Virtual Objects","Virtual Environment","Registry Staging","Virtual Services","Virtual Shell")
$Regkey = "HKLM:SOFTWARE\Microsoft\AppV\Subsystem\Disabled"
if(Test-Path -Path $Regkey)
{
ForEach ($SubsystemItem in $SubsystemItems)
{
$tmpEnabled = ""
$tmpDisabled = ""
$Result = Read-Registry -RegistryKey $Regkey -ValueName $SubsystemItem
if($Result -eq $True) {$tmpDisabled = $True}
elseif($Result -eq $False) {$tmpEnabled = $True}
if($tmpEnabled -or $tmpDisabled) {Add-EntryToGloballyEnabledOrDisabledItems -SubsystemName $SubsystemItem -Enabled $tmpEnabled -Disabled $tmpDisabled}
}
}
if($Global:gblSummary)
{
$Global:gblarrTable = $Global:gblarrTable | Select-Object -Property "Display Name" ,`
"Package and version ID" ,`
"Package Version" ,`
"Published globally" ,`
"Published to user" ,`
"COM Mode" ,`
"InProcess Enabled" ,`
"Out of Process Enabled" ,`
"Objects Enabled" ,`
"Connection group"
}
if($GUI)
{
$lblAction.Visible = $False
$pgbProcessing.Visible = $False
$btnCancel.Enabled = $True
if($valTotalAppVPackages -gt 0)
{
$btnShowSaveOptions.Enabled = $True
if($valConnectionGroups -gt 0)
{
$btnConnGroup.Enabled = $True
}
}
}
}
# =============================================================================================================================================
# End function block
# =============================================================================================================================================
# =============================================================================================================================================
# Functions, used in the forms blocks
# =============================================================================================================================================
Function InformationAboutLoad
{
Process-AppVPackages -GUI
$datagridview1.Rows.Clear()
if($Global:gblarrTable.Count -gt 0)
{
$datagridview1.Enabled = $true
if($Global:gblarrTable.Count -gt 1)
{
$Global:gblarrTable = $Global:gblarrTable | Sort-Object -Property "Display Name"
}
$datagridview1.DataSource = $Null
$datagridview1.DataSource = [System.Collections.ArrayList]$Global:gblarrTable
$DisabledItems = $Global:gblarrEnabledDisabled | Where {($_."Disabled" -eq $True)}
if($DisabledItems."Subsystem name".Count -gt 0)
{
$ColumnNames = @()
$btnShowGlobally.Enabled = $True
ForEach ($DisabledItem in $DisabledItems)
{
if ($DisabledItem."Subsystem name" -eq "Integration") {$ColumnNames += "Shortcuts Enabled"}
if ($DisabledItem."Subsystem name" -eq "Virtual Objects") {$ColumnNames += "Objects Enabled"}
if ($DisabledItem."Subsystem name" -eq "Virtual Fonts") {$ColumnNames += "Fonts Enabled"}
if ($DisabledItem."Subsystem name" -eq "Virtual FileSystem") {$ColumnNames += "Filesystem Enabled"}
if ($DisabledItem."Subsystem name" -eq "Virtual COM") {$ColumnNames += "COM Mode"; $ColumnNames += "InProcess Enabled"; $ColumnNames += "Out of Process Enabled";}
if ($DisabledItem."Subsystem name" -eq "Virtual Environment") {$ColumnNames += "Environment variables Enabled"}
if ($DisabledItem."Subsystem name" -eq "Virtual Services") {$ColumnNames += "Services Enabled"}
}
ForEach ($ColumnName in $ColumnNames)
{
$datagridview1.Columns[$ColumnName].DefaultCellStyle.BackColor = "LightGray"
$datagridview1.Columns[$ColumnName].DefaultCellStyle.ForeColor = "Gray"
}
}
}
}
Function Cancel
{
$frmInformationAboutLoad.Close()
$frmInformationAboutLoad.Dispose
}
Function ShowSaveOptions
{
[void]$frmSaveOptions.ShowDialog()
$frmInformationAboutLoad.Close()
$frmInformationAboutLoad.Dispose
}
Function InformationAboutConn
{
$dgvConnectionGroups.Enabled = $True
if($Global:gblarrConnectionGroups.Count -gt 1)
{
$Global:gblarrConnectionGroups = $Global:gblarrConnectionGroups | Sort-Object -Property Priority
}
$dgvConnectionGroups.DataSource = [System.Collections.ArrayList]$Global:gblarrConnectionGroups
}
Function dgExit
{
$frmInformationAboutConn.Close()
$frmInformationAboutConn.Dispose
}
Function DisabledSubsystems
{
if($Global:gblarrConnectionGroups.Count -gt 1)
{
$Global:gblarrEnabledDisabled = $Global:gblarrEnabledDisabled | Sort-Object -Property "Subsystem name"
}
$dgvDisabledEnabledSubSystems.DataSource = [System.Collections.ArrayList]$Global:gblarrEnabledDisabled
}
Function DIExit
{
$frmDisabledSubsystems.Close()
$frmDisabledSubsystems.Dispose
}
Function SoExit
{
$chkSaveHTML.Enabled = $False
$chkSaveCSV.Enabled = $False
$chkSaveAsPDFFile.Enabled = $False
if($chkSaveCSV.Checked)
{
$CSVFile = $Global:gblLogFile.Replace(".log",".csv")
Write-CSVFile -CSVFileWithResults $CSVFile -DelimChar $Delimiter -GUI
}
if($chkSaveHTML.Checked)
{
$HTMLPage = $Global:gblLogFile.Replace(".log",".html")
Write-HTMLFile -HTMLFileToWrite $HTMLPage -GUI
}
if($chkSaveAsPDFFile.Checked)
{
$HTMLPage = $Global:gblLogFile.Replace(".log",".html")
Write-HTMLFile -HTMLFileToWrite $HTMLPage -SaveAsPDFFile -GUI
}
$frmSaveOptions.Close()
$frmSaveOptions.Dispose
}
# =============================================================================================================================================
# End functions, used in the forms blocks
# =============================================================================================================================================
# =============================================================================================================================================
# Define the variables
# =============================================================================================================================================
Clear-Host
$Global:gblLogFile = ""
$Global:gblNoProgressBar = $NoProgressBar
$Global:gblarrTable = @()
$Global:gblarrConnectionGroups = @()
$Global:gblDetailedLogging = $DetailedLogging
$Global:gblLogPath = $LogPath
$Global:gblComputerName = $env:COMPUTERNAME
$Global:gblSummary = $Summary
$Global:gblarrEnabledDisabled = @()
$Global:gblDLLPath = $(Split-Path $MyInvocation.MyCommand.Definition) + "\DLLFilesForItext7"
$Global:gblDLLPathExists = $False
$PowerShellLanguageMode = $ExecutionContext.SessionState.LanguageMode
$Global:gblConstrainedLanguage = $PowerShellLanguageMode -eq "ConstrainedLanguage"
$Global:gblFullLanguage = $PowerShellLanguageMode -eq "FullLanguage"
$Results = @()
$valCounter = 1
$Message = ""
$bolError = $false
$MinimumWidth = 1400
$MinimumHeight = 800
$Header = "Information about published AppV Packages v0.6 (on the $Global:gblComputerName)"
$AppVServiceName = "AppVClient"
$ErrorNumber = 0
$ErrorText = $null
if(-not($Global:gblLogPath))
{
$Global:gblLogPath = Split-Path $MyInvocation.MyCommand.Definition
}
if(Test-Path $Global:gblDLLPath)
{
$Global:gblDLLPathExists = $True
}
if(-not(test-path $Global:gblLogPath))
{
$Returntext, $bolResult = Create-Folder -FolderName $Global:gblLogPath
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.
# It is saved as yyyy-MM-dd HH-mm-ss, for example 2022-11-14 22-23-09
# =============================================================================================================================================
$strLastPartOfFileName = " ($((Get-Date -format "yyyy-MM-dd HH-mm-ss").ToString()))"
$PreFixLogFile = "Overview Published AppV 5 Applications (on $Global:gblComputerName)"
$Global:gblLogFile = $Global:gblLogPath + "\"+ $PreFixLogFile + $($strLastPartOfFileName + ".log")
if($Global:gblDetailedLogging)
{
New-Item $Global:gblLogFile -ItemType File -Force | Out-Null
}
If ($Message)
{
If ($bolError)
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "$Message"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "This script will now quit."
Write-Error $Message -Category CloseError
Exit 3
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "[Warning]: $Message"
}
}
# =============================================================================================================================================
# Find all the arguments and put them in the log file
# Source: https://ss64.com/ps/psboundparameters.html
# =============================================================================================================================================
if(-not($Global:gblConstrainedLanguage))
{
$TableWithParameters = @()
$RecordWithParameters = [ordered] @{"Key" = "";
"Value" = ""}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "***** Parameters part *****"
ForEach($boundparam in $PSBoundParameters.GetEnumerator())
{
$tmpValue = $($boundparam.Value)
$Value = ""
if($tmpValue -is [array])
{
ForEach ($object in $tmpValue)
{
if(-not($value))
{
$Value = $object
}
else
{
$Value +=",$($object)"
}
}
}
else
{
$Value = $tmpValue
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Key: $($boundparam.Key) Value: $Value"
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "***** End Parameters part *****`r`n"
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The parameters are not written to the logfile due to PowerShell ConstrainedMode."
}
# =============================================================================================================================================
# Write the logged in user details to the log file.
# =============================================================================================================================================
$OnlyUserName, `
$LoggedOnUserInDomainFormat, `
$UseridSID, `
$InstallAccount = UserDetails
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "***** User details part *****"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Logged on user: $LoggedOnUserInDomainFormat"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Logged on user (SID): $UseridSID"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Installation account: $InstallAccount"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "***** End User details part *****`r`n"
# =============================================================================================================================================
# Define the error number and messages
# =============================================================================================================================================
$bolError = $False
$Error02 = "Warning: The Powershell Language mode '$PowerShellLanguageMode' is not supported."
$Error16 = "Error: The AppV Service $AppVServiceName is not running or does not exists."
$Error32 = "Warning: The directory with all the DLL files for converting a HTML file to PDF is not found. Therefore, the option SaveAsPDF is disabled."
$Error64 = "Warning: Only the option SaveAsCSVFile is supported when the PowerShell Language Mode has been set to '$PowerShellLanguageMode'."
if (-not($Global:gblFullLanguage)) {$ErrorNumber += 2 ; $Silent = $True}
if ($SaveAsPDF -and -not $Global:gblDLLPathExists) {$ErrorNumber += 32 ; $SaveAsPDF = $False}
if ((-not($Global:gblFullLanguage)) -and ($SaveAsHTMLPage -or $SaveAsPDF)) {$ErrorNumber += 64 ; $SaveAsHTMLPage = $False ; $SaveAsPDF = $False ; $SaveAsCSVFile = $True}
if ((-not $Silent) -and $Global:gblFullLanguage)
{
# =============================================================================================================================================
# Check the screenwidth and screenheight. If too small than falling back to silent mode.
# Source: https://stackoverflow.com/questions/7967699/get-screen-resolution-using-wmi-powershell-in-windows-7
# =============================================================================================================================================
if((-not $Silent) -and $Global:gblFullLanguage)
{
Add-Type -AssemblyName System.Web | Out-Null
Add-Type -AssemblyName System.Drawing | Out-Null
Add-Type -AssemblyName System.Windows.Forms | Out-Null
Add-Type -AssemblyName PresentationFramework
}
$DetectedWidth = ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize).Width
$DetectedHeight = ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize).Height
$tmpLine = ""
if($DetectedWidth -le $MinimumWidth)
{
$Error04 = "Warning: The detected screen width of $DetectedWidth is less than the minimum width of $MinimumWidth."
$ErrorNumber += 4
}
if($DetectedHeight -le $MinimumHeight)
{
$Error08 = "Warning: The detected screen height of $DetectedHeight is less than of the minimum height of $MinimumHeight."
$ErrorNumber += 8
}
}
# =============================================================================================================================================
# Check if the AppVService exists and is running.
# =============================================================================================================================================
if(-not (Test-Service $AppVServiceName)) {$ErrorNumber += 16 ; $bolError = $True}
# =============================================================================================================================================
# Error handling.
# =============================================================================================================================================
If (($ErrorNumber -band 2) -eq 2) {$ErrorText = $Error02}
If (($ErrorNumber -band 4) -eq 4) {If ($ErrorText) {$ErrorText += "`n$Error04"} else {$ErrorText = $Error04}}
If (($ErrorNumber -band 8) -eq 8) {If ($ErrorText) {$ErrorText += "`n$Error08"} else {$ErrorText = $Error08}}
If (($ErrorNumber -band 16) -eq 16) {If ($ErrorText) {$ErrorText += "`n$Error16"} else {$ErrorText = $Error16}}
If (($ErrorNumber -band 32) -eq 32) {If ($ErrorText) {$ErrorText += "`n$Error32"} else {$ErrorText = $Error32}}
If (($ErrorNumber -band 64) -eq 64) {If ($ErrorText) {$ErrorText += "`n$Error64"} else {$ErrorText = $Error64}}
if (($ErrorNumber -band 16) -eq 16)
{$ErrorText += "`r$The application is quit."}
else
{$ErrorText += "`r$The application will continue."}
If ($ErrorNumber -gt 0)
{
if ($Silent -or -not $Global:gblFullLanguage) {$GUI = $False} else {$GUI = $True}
$Null = Display-MessageBox -Text $ErrorText -GUI:$GUI -Error -Title "Result"
if ($bolError)
{
Exit $ErrorNumber
}
}
if($Silent)
{
# =============================================================================================================================================
# In the silent mode.
# =============================================================================================================================================
Process-AppVPackages
# =============================================================================================================================================
# If the ContrainedMode is used, then use only a limited set of columns.
# =============================================================================================================================================
if($Global:gblConstrainedLanguage)
{
$Global:gblarrTable = $Global:gblarrTable | Select-Object -Property "Display Name","Package and version ID","Package Version","Package Description","Published globally","Published to user","Shortcuts","Full VFS Write Mode","Deployment config files"
}
# =============================================================================================================================================
# Write the output files.
# =============================================================================================================================================
if($SaveAsCSVFile -or (-not $SaveAsHTMLPage -and -not $SaveAsPDF))
{
$CSVFile = $Global:gblLogFile.Replace(".log",".csv")
Write-CSVFile -CSVFileWithResults $CSVFile -DelimChar $Delimiter
}
if($SaveAsPDF)
{
$HTMLPage = $Global:gblLogFile.Replace(".log",".html")
Write-HTMLFile -HTMLFileToWrite $HTMLPage -SaveAsPDFFile
}
if($SaveAsHTMLPage)
{
$HTMLPage = $Global:gblLogFile.Replace(".log",".html")
Write-HTMLFile -HTMLFileToWrite $HTMLPage
}
}
else
{
# =============================================================================================================================================
# In the non-silent mode.
# =============================================================================================================================================
# =============================================================================================================================================
# Forms block (main form)
# =============================================================================================================================================
[System.Windows.Forms.Application]::EnableVisualStyles()
$frmInformationAboutLoad = New-Object 'System.Windows.Forms.Form'
$lblAction = New-Object 'System.Windows.Forms.Label'
$pgbProcessing = New-Object 'System.Windows.Forms.ProgressBar'
$btnShowSaveOptions = New-Object 'System.Windows.Forms.Button'
$btnExit = New-Object 'System.Windows.Forms.Button'
$btnCancel = New-Object 'System.Windows.Forms.Button'
$btnConnGroup = New-Object 'System.Windows.Forms.Button'
$btnShowGlobally = New-Object 'System.Windows.Forms.Button'
$datagridview1 = New-Object 'System.Windows.Forms.DataGridView'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$ToolTips = New-Object 'System.Windows.Forms.ToolTip'
# ToolTips
#
$ToolTips.AutomaticDelay = 500
$ToolTips.AutoPopDelay = 5010
$ToolTips.InitialDelay = 500
$ToolTips.IsBalloon = $True
$ToolTips.ReshowDelay = 100
$ToolTips.Tag = 'Information'
$ToolTips.ToolTipIcon = 'Info'
$ToolTips.ToolTipTitle = 'Additonal information'
# frmInformationAboutLoad
#
$frmInformationAboutLoad.Controls.Add($btnShowSaveOptions)
$frmInformationAboutLoad.Controls.Add($btnConnGroup)
$frmInformationAboutLoad.Controls.Add($btnCancel)
$frmInformationAboutLoad.Controls.Add($datagridview1)
$frmInformationAboutLoad.Controls.Add($lblAction)
$frmInformationAboutLoad.Controls.Add($pgbProcessing)
$frmInformationAboutLoad.Controls.Add($btnShowGlobally)
$frmInformationAboutLoad.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmInformationAboutLoad.AutoScaleMode = 'Font'
$frmInformationAboutLoad.ClientSize = New-Object System.Drawing.Size(1384, 761)
$frmInformationAboutLoad.FormBorderStyle = 'Fixed3D'
$frmInformationAboutLoad.Name = 'frmInformationAboutLoad'
$frmInformationAboutLoad.StartPosition = 'CenterScreen'
$frmInformationAboutLoad.Text = $Header
$frmInformationAboutLoad.add_Shown({InformationAboutLoad})
# lblAction
#
$lblAction.AutoSize = $True
$lblAction.Location = New-Object System.Drawing.Point(13, 706)
$lblAction.Name = 'lblAction'
$lblAction.Size = New-Object System.Drawing.Size(859, 26)
$lblAction.TabIndex = 7
# pgbProcessing
#
$pgbProcessing.Location = New-Object System.Drawing.Point(13, 730)
$pgbProcessing.Name = 'pgbProcessing'
$pgbProcessing.Size = New-Object System.Drawing.Size(859, 26)
$pgbProcessing.Style = 'Continuous'
$pgbProcessing.TabIndex = 0
# btnShowSaveOptions
#
$btnShowSaveOptions.Location = New-Object System.Drawing.Point(1054, 706)
$btnShowSaveOptions.Name = 'btnShowSaveOptions'
$btnShowSaveOptions.Size = New-Object System.Drawing.Size(75, 50)
$btnShowSaveOptions.TabIndex = 4
$btnShowSaveOptions.Text = 'Save options'
$btnShowSaveOptions.UseVisualStyleBackColor = $True
$btnShowSaveOptions.Enabled = $False
$ToolTips.SetToolTip($btnShowSaveOptions, 'Save the results as a PDF, HTML or CSV file.')
# btnConnGroup
#
$btnConnGroup.Location = New-Object System.Drawing.Point(1216, 706)
$btnConnGroup.Name = 'btnConnGroup'
$btnConnGroup.Size = New-Object System.Drawing.Size(75, 50)
$btnConnGroup.TabIndex = 2
$btnConnGroup.Text = 'Connectiongroup information'
$btnConnGroup.UseVisualStyleBackColor = $True
$btnConnGroup.Enabled = $False
$ToolTips.SetToolTip($btnConnGroup, 'Show connectiongroup information.')
# btnCancel
#
$btnCancel.Location = New-Object System.Drawing.Point(1297, 706)
$btnCancel.Name = 'btnCancel'
$btnCancel.Size = New-Object System.Drawing.Size(75, 50)
$btnCancel.TabIndex = 1
$btnCancel.Text = 'Cancel'
$btnCancel.UseVisualStyleBackColor = $True
$ToolTips.SetToolTip($btnCancel, 'Exit and nothing is saved.')
# btnShowGlobally
#
$btnShowGlobally.Location = New-Object System.Drawing.Point(1135, 706)
$btnShowGlobally.Name = 'btnShowGlobally'
$btnShowGlobally.Size = New-Object System.Drawing.Size(75, 50)
$btnShowGlobally.TabIndex = 5
$btnShowGlobally.Text = 'Globally subsystems'
$btnShowGlobally.UseVisualStyleBackColor = $True
$btnShowGlobally.Enabled = $False
$ToolTips.SetToolTip($btnShowGlobally, 'Shows information about globally disabled and enabled subsystems.')
# datagridview1
#
$datagridview1.ColumnHeadersHeightSizeMode = 'AutoSize'
$datagridview1.Location = New-Object System.Drawing.Point(12, 12)
$datagridview1.Name = 'datagridview1'
$datagridview1.Size = New-Object System.Drawing.Size(1360, 677)
$datagridview1.TabIndex = 0
$DataGridViewCellStyle_1 = New-Object 'System.Windows.Forms.DataGridViewCellStyle'
$DataGridViewCellStyle_1.Alignment = 'TopLeft'
$DataGridViewCellStyle_1.BackColor = [System.Drawing.SystemColors]::Window
$DataGridViewCellStyle_1.Font = [System.Drawing.Font]::new('Microsoft Sans Serif', '8.25')
$DataGridViewCellStyle_1.ForeColor = [System.Drawing.SystemColors]::ControlText
$DataGridViewCellStyle_1.SelectionBackColor = [System.Drawing.SystemColors]::Highlight
$DataGridViewCellStyle_1.SelectionForeColor = [System.Drawing.SystemColors]::HighlightText
$DataGridViewCellStyle_1.WrapMode = 'True'
$datagridview1.DefaultCellStyle = $DataGridViewCellStyle_1
$datagridview1.ColumnHeadersHeightSizeMode = 'AutoSize'
$datagridview1.AutoSizeRowsMode = 'AllCells'
$datagridview1.AutoSizeColumnsMode = 'AllCells'
$btnCancel.add_Click({Cancel})
$btnShowSaveOptions.add_Click({ShowSaveOptions})
$btnConnGroup.add_Click({[void]$frmInformationAboutConn.ShowDialog()})
$btnShowGlobally.add_Click({[void]$frmDisabledSubsystems.ShowDialog()})
# =============================================================================================================================================
# End forms block (main form)
# =============================================================================================================================================
# =============================================================================================================================================
# Forms block (connection groups)
# =============================================================================================================================================
$frmInformationAboutConn = New-Object 'System.Windows.Forms.Form'
$btndgExit = New-Object 'System.Windows.Forms.Button'
$dgvConnectionGroups = New-Object 'System.Windows.Forms.DataGridView'
# frmInformationAboutConn
#
$frmInformationAboutConn.Controls.Add($btndgExit)
$frmInformationAboutConn.Controls.Add($dgvConnectionGroups)
$frmInformationAboutConn.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmInformationAboutConn.AutoScaleMode = 'Font'
$frmInformationAboutConn.BackColor = [System.Drawing.SystemColors]::ButtonFace
$frmInformationAboutConn.ClientSize = New-Object System.Drawing.Size(797, 366)
$frmInformationAboutConn.FormBorderStyle = 'Fixed3D'
$frmInformationAboutConn.Name = 'frmInformationAboutConn'
$frmInformationAboutConn.StartPosition = 'CenterScreen'
$frmInformationAboutConn.Text = 'Information about connection groups'
$frmInformationAboutConn.add_Load({InformationAboutConn})
# btndgExit
#
$btndgExit.BackColor = [System.Drawing.SystemColors]::ButtonShadow
$btndgExit.Location = New-Object System.Drawing.Point(714, 310)
$btndgExit.Name = 'btndgExit'
$btndgExit.Size = New-Object System.Drawing.Size(75, 50)
$btndgExit.TabIndex = 1
$btndgExit.Text = '&Exit'
$btndgExit.UseVisualStyleBackColor = $False
$btndgExit.add_Click({dgExit})
# dgvConnectionGroups
#
$System_Windows_Forms_DataGridViewCellStyle_1 = New-Object 'System.Windows.Forms.DataGridViewCellStyle'
$System_Windows_Forms_DataGridViewCellStyle_1.Alignment = 'TopLeft'
$System_Windows_Forms_DataGridViewCellStyle_1.WrapMode = 'True'
$dgvConnectionGroups.AlternatingRowsDefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_1
$dgvConnectionGroups.ColumnHeadersHeightSizeMode = 'AutoSize'
$dgvConnectionGroups.Location = New-Object System.Drawing.Point(10, 11)
$dgvConnectionGroups.Name = 'dgvConnectionGroups'
$dgvConnectionGroups.Size = New-Object System.Drawing.Size(779, 293)
$dgvConnectionGroups.TabIndex = 0
$dgvConnectionGroups.DefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_1
$dgvConnectionGroups.ColumnHeadersHeightSizeMode = 'AutoSize'
$dgvConnectionGroups.AutoSizeRowsMode = 'AllCells'
$dgvConnectionGroups.AutoSizeColumnsMode = 'AllCells'
# =============================================================================================================================================
# End forms block (Connection Groups)
# =============================================================================================================================================
# =============================================================================================================================================
# Forms block (Globally disabled and enabled subsystems)
# =============================================================================================================================================
$frmDisabledSubsystems = New-Object 'System.Windows.Forms.Form'
$btnDIExit = New-Object 'System.Windows.Forms.Button'
$dgvDisabledEnabledSubSystems = New-Object 'System.Windows.Forms.DataGridView'
$frmDisabledSubsystems.Controls.Add($btnDIExit)
$frmDisabledSubsystems.Controls.Add($dgvDisabledEnabledSubSystems)
$frmDisabledSubsystems.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmDisabledSubsystems.AutoScaleMode = 'Font'
$frmDisabledSubsystems.BackColor = [System.Drawing.SystemColors]::ButtonFace
$frmDisabledSubsystems.ClientSize = New-Object System.Drawing.Size(530, 280)
$frmDisabledSubsystems.FormBorderStyle = 'Fixed3D'
$frmDisabledSubsystems.Name = 'frmDisabledSubsystems'
$frmDisabledSubsystems.StartPosition = 'CenterScreen'
$frmDisabledSubsystems.Text = 'Information about globally disabled and enabled subsystems'
$frmDisabledSubsystems.add_Load({DisabledSubsystems})
# btnDIExit
#
$btnDIExit.BackColor = [System.Drawing.SystemColors]::ButtonShadow
$btnDIExit.Location = New-Object System.Drawing.Point(443, 222)
$btnDIExit.Name = 'btnDIExit'
$btnDIExit.Size = New-Object System.Drawing.Size(75, 50)
$btnDIExit.TabIndex = 1
$btnDIExit.Text = '&Exit'
$btnDIExit.UseVisualStyleBackColor = $False
$btnDIExit.add_Click({DIExit})
# dgvDisabledEnabledSubSystems
#
$System_Windows_Forms_DataGridViewCellStyle_2 = New-Object 'System.Windows.Forms.DataGridViewCellStyle'
$System_Windows_Forms_DataGridViewCellStyle_2.Alignment = 'TopLeft'
$System_Windows_Forms_DataGridViewCellStyle_2.WrapMode = 'True'
$dgvDisabledEnabledSubSystems.DefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_2
$dgvDisabledEnabledSubSystems.AlternatingRowsDefaultCellStyle = $System_Windows_Forms_DataGridViewCellStyle_2
$dgvDisabledEnabledSubSystems.ColumnHeadersHeightSizeMode = 'AutoSize'
$dgvDisabledEnabledSubSystems.Location = New-Object System.Drawing.Point(10, 11)
$dgvDisabledEnabledSubSystems.Name = 'dgvDisabledEnabledSubSystems'
$dgvDisabledEnabledSubSystems.Size = New-Object System.Drawing.Size(508, 205)
$dgvDisabledEnabledSubSystems.TabIndex = 0
$dgvDisabledEnabledSubSystems.ColumnHeadersHeightSizeMode = 'AutoSize'
$dgvDisabledEnabledSubSystems.AutoSizeRowsMode = 'AllCells'
$dgvDisabledEnabledSubSystems.AutoSizeColumnsMode = 'AllCells'
# =============================================================================================================================================
# End Forms block (Globally disabled and enabled items)
# =============================================================================================================================================
# =============================================================================================================================================
# Forms block Save options
# =============================================================================================================================================
$frmSaveOptions = New-Object 'System.Windows.Forms.Form'
$chkSaveAsPDFFile = New-Object 'System.Windows.Forms.CheckBox'
$chkSaveHTML = New-Object 'System.Windows.Forms.CheckBox'
$chkSaveCSV = New-Object 'System.Windows.Forms.CheckBox'
$btnSOExit = New-Object 'System.Windows.Forms.Button'
$ToolTips = New-Object 'System.Windows.Forms.ToolTip'
# frmSaveOptions
#
$frmSaveOptions.Controls.Add($chkSaveAsPDFFile)
$frmSaveOptions.Controls.Add($chkSaveHTML)
$frmSaveOptions.Controls.Add($chkSaveCSV)
$frmSaveOptions.Controls.Add($btnSOExit)
$frmSaveOptions.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmSaveOptions.AutoScaleMode = 'Font'
$frmSaveOptions.BackColor = [System.Drawing.SystemColors]::ButtonFace
$frmSaveOptions.ClientSize = New-Object System.Drawing.Size(291, 132)
$frmSaveOptions.FormBorderStyle = 'Fixed3D'
$frmSaveOptions.Name = 'frmSaveOptions'
$frmSaveOptions.StartPosition = 'CenterScreen'
$frmSaveOptions.Text = 'Save options'
# checkboxSaveAsPDFFile
#
$chkSaveAsPDFFile.Location = New-Object System.Drawing.Point(12, 72)
$chkSaveAsPDFFile.Name = 'checkboxSaveAsPDFFile'
$chkSaveAsPDFFile.Size = New-Object System.Drawing.Size(171, 24)
$chkSaveAsPDFFile.TabIndex = 4
$chkSaveAsPDFFile.Text = 'Save as &PDF file'
$chkSaveAsPDFFile.UseVisualStyleBackColor = $True
$ToolTips.SetToolTip($chkSaveAsPDFFile, 'Select this option if you want to save the results as a PDF file. More options are possible.')
if(-not($Global:gblDLLPathExists))
{
$chkSaveAsPDFFile.Enabled = $False
}
# chkSaveHTML
#
$chkSaveHTML.Location = New-Object System.Drawing.Point(12, 42)
$chkSaveHTML.Name = 'chkSaveHTML'
$chkSaveHTML.Size = New-Object System.Drawing.Size(171, 24)
$chkSaveHTML.TabIndex = 3
$chkSaveHTML.Text = 'Save as &HTML page'
$chkSaveHTML.UseVisualStyleBackColor = $True
$ToolTips.SetToolTip($chkSaveHTML, 'Select this option if you want to save the results as a HTML page. More options are possible.')
# chkSaveCSV
#
$chkSaveCSV.Location = New-Object System.Drawing.Point(12, 12)
$chkSaveCSV.Name = 'chkSaveCSV'
$chkSaveCSV.Size = New-Object System.Drawing.Size(171, 24)
$chkSaveCSV.TabIndex = 2
$chkSaveCSV.Text = 'Save as &CSV file'
$chkSaveCSV.UseVisualStyleBackColor = $True
$ToolTips.SetToolTip($chkSaveCSV, 'Select this option if you want to save the results as a CSV file. More options are possible.')
# btnSOExit
#
$btnSOExit.BackColor = [System.Drawing.SystemColors]::ButtonShadow
$btnSOExit.Location = New-Object System.Drawing.Point(201, 72)
$btnSOExit.Name = 'btnSOExit'
$btnSOExit.Size = New-Object System.Drawing.Size(75, 50)
$btnSOExit.TabIndex = 1
$btnSOExit.Text = '&Exit'
$btnSOExit.UseVisualStyleBackColor = $False
$btnSoExit.add_Click({SoExit})
# =============================================================================================================================================
# End forms block Save options
# =============================================================================================================================================
[void]$frmInformationAboutLoad.ShowDialog()
}
Please 'unblock' the Powershell script and/or the batch file after extracting the ZIP file.
