From a7f9f6d2a6408f8f9195b9ba02f1e88e82c4531f Mon Sep 17 00:00:00 2001 From: Josh Wittner Date: Wed, 7 Mar 2018 13:52:18 -0800 Subject: [PATCH 1/3] Better support for UnitySetupComponent --- UnitySetup/UnitySetup.psd1 | 3 +- UnitySetup/UnitySetup.psm1 | 85 +++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/UnitySetup/UnitySetup.psd1 b/UnitySetup/UnitySetup.psd1 index b690562..85b4a98 100644 --- a/UnitySetup/UnitySetup.psd1 +++ b/UnitySetup/UnitySetup.psd1 @@ -81,7 +81,8 @@ FunctionsToExport = @( 'Install-UnitySetupInstance', 'Select-UnitySetupInstance', 'Uninstall-UnitySetupInstance', - 'Start-UnityEditor' + 'Start-UnityEditor', + 'New-UnitySetupComponent' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/UnitySetup/UnitySetup.psm1 b/UnitySetup/UnitySetup.psm1 index 2f295d8..bdd2832 100644 --- a/UnitySetup/UnitySetup.psm1 +++ b/UnitySetup/UnitySetup.psm1 @@ -3,7 +3,7 @@ Import-Module powershell-yaml -Force -ErrorAction Stop [Flags()] -enum UnitySetupComponentType +enum UnitySetupComponent { Setup = (1 -shl 0) Documentation = (1 -shl 1) @@ -24,7 +24,7 @@ enum UnitySetupComponentType class UnitySetupInstaller { - [UnitySetupComponentType] $ComponentType + [UnitySetupComponent] $ComponentType [UnityVersion] $Version [int64]$Length [DateTime]$LastModified @@ -34,7 +34,7 @@ class UnitySetupInstaller class UnitySetupInstance { [UnityVersion]$Version - [UnitySetupComponentType]$Components + [UnitySetupComponent]$Components [string]$Path UnitySetupInstance([string]$path) { @@ -49,23 +49,23 @@ class UnitySetupInstance $this.Path = $path $this.Version = $xmlDoc.'ivy-module'.info.unityVersion - $this.Components = [UnitySetupComponentType]::Setup + $this.Components = [UnitySetupComponent]::Setup $componentTests = @{ - [UnitySetupComponentType]::Documentation = ,"$Path\Editor\Data\Documentation"; - [UnitySetupComponentType]::StandardAssets = ,"$Path\Editor\Standard Assets"; - [UnitySetupComponentType]::Windows_IL2CPP = ,"$Path\Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations\win32_development_il2cpp"; - [UnitySetupComponentType]::Metro = "$Path\Editor\Data\PlaybackEngines\MetroSupport\Templates\UWP_.NET_D3D", + [UnitySetupComponent]::Documentation = ,"$Path\Editor\Data\Documentation"; + [UnitySetupComponent]::StandardAssets = ,"$Path\Editor\Standard Assets"; + [UnitySetupComponent]::Windows_IL2CPP = ,"$Path\Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations\win32_development_il2cpp"; + [UnitySetupComponent]::Metro = "$Path\Editor\Data\PlaybackEngines\MetroSupport\Templates\UWP_.NET_D3D", "$Path\Editor\Data\PlaybackEngines\MetroSupport\Templates\UWP_D3D"; - [UnitySetupComponentType]::UWP_IL2CPP = ,"$Path\Editor\Data\PlaybackEngines\MetroSupport\Templates\UWP_IL2CPP_D3D"; - [UnitySetupComponentType]::Android = ,"$Path\Editor\Data\PlaybackEngines\AndroidPlayer"; - [UnitySetupComponentType]::iOS = , "$Path\Editor\Data\PlaybackEngines\iOSSupport"; - [UnitySetupComponentType]::AppleTV = , "$Path\Editor\Data\PlaybackEngines\AppleTVSupport"; - [UnitySetupComponentType]::Facebook = , "$Path\Editor\Data\PlaybackEngines\Facebook"; - [UnitySetupComponentType]::Linux = , "$Path\Editor\Data\PlaybackEngines\LinuxStandaloneSupport"; - [UnitySetupComponentType]::Mac = , "$Path\Editor\Data\PlaybackEngines\MacStandaloneSupport"; - [UnitySetupComponentType]::Vuforia = , "$Path\Editor\Data\PlaybackEngines\VuforiaSupport"; - [UnitySetupComponentType]::WebGL = , "$Path\Editor\Data\PlaybackEngines\WebGLSupport"; + [UnitySetupComponent]::UWP_IL2CPP = ,"$Path\Editor\Data\PlaybackEngines\MetroSupport\Templates\UWP_IL2CPP_D3D"; + [UnitySetupComponent]::Android = ,"$Path\Editor\Data\PlaybackEngines\AndroidPlayer"; + [UnitySetupComponent]::iOS = , "$Path\Editor\Data\PlaybackEngines\iOSSupport"; + [UnitySetupComponent]::AppleTV = , "$Path\Editor\Data\PlaybackEngines\AppleTVSupport"; + [UnitySetupComponent]::Facebook = , "$Path\Editor\Data\PlaybackEngines\Facebook"; + [UnitySetupComponent]::Linux = , "$Path\Editor\Data\PlaybackEngines\LinuxStandaloneSupport"; + [UnitySetupComponent]::Mac = , "$Path\Editor\Data\PlaybackEngines\MacStandaloneSupport"; + [UnitySetupComponent]::Vuforia = , "$Path\Editor\Data\PlaybackEngines\VuforiaSupport"; + [UnitySetupComponent]::WebGL = , "$Path\Editor\Data\PlaybackEngines\WebGLSupport"; } $componentTests.Keys | ForEach-Object { @@ -159,6 +159,25 @@ class UnityVersion : System.IComparable } } +<# +.Synopsis + Help to create UnitySetupComponent +.PARAMETER Components + What components would you like included? +.EXAMPLE + New-UnitySetupComponent -Components Setup,Metro +#> +function New-UnitySetupComponent +{ + [CmdletBinding()] + param( + [parameter(Mandatory=$true)] + [UnitySetupComponent] $Components + ) + + $Components +} + <# .Synopsis Finds UnitySetup installers for a specified version. @@ -181,7 +200,7 @@ function Find-UnitySetupInstaller [UnityVersion] $Version, [parameter(Mandatory=$false)] - [UnitySetupComponentType] $Components = [UnitySetupComponentType]::All + [UnitySetupComponent] $Components = [UnitySetupComponent]::All ) $unitySetupRegEx = "^(.+)\/([a-z0-9]+)\/Windows64EditorInstaller\/UnitySetup64-(\d+)\.(\d+)\.(\d+)([fpb])(\d+).exe$" @@ -192,21 +211,21 @@ function Find-UnitySetupInstaller ) $installerTemplates = @{ - [UnitySetupComponentType]::Setup = ,"Windows64EditorInstaller/UnitySetup64-$Version.exe"; - [UnitySetupComponentType]::Documentation = ,"WindowsDocumentationInstaller/UnityDocumentationSetup-$Version.exe"; - [UnitySetupComponentType]::StandardAssets = ,"WindowsStandardAssetsInstaller/UnityStandardAssetsSetup-$Version.exe"; - [UnitySetupComponentType]::Metro = ,"TargetSupportInstaller/UnitySetup-Metro-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::UWP_IL2CPP = ,"TargetSupportInstaller/UnitySetup-UWP-IL2CPP-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Android = ,"TargetSupportInstaller/UnitySetup-Android-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::iOS = ,"TargetSupportInstaller/UnitySetup-iOS-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::AppleTV = ,"TargetSupportInstaller/UnitySetup-AppleTV-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Facebook = ,"TargetSupportInstaller/UnitySetup-Facebook-Games-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Linux = ,"TargetSupportInstaller/UnitySetup-Linux-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Mac = "TargetSupportInstaller/UnitySetup-Mac-Support-for-Editor-$Version.exe", + [UnitySetupComponent]::Setup = ,"Windows64EditorInstaller/UnitySetup64-$Version.exe"; + [UnitySetupComponent]::Documentation = ,"WindowsDocumentationInstaller/UnityDocumentationSetup-$Version.exe"; + [UnitySetupComponent]::StandardAssets = ,"WindowsStandardAssetsInstaller/UnityStandardAssetsSetup-$Version.exe"; + [UnitySetupComponent]::Metro = ,"TargetSupportInstaller/UnitySetup-Metro-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::UWP_IL2CPP = ,"TargetSupportInstaller/UnitySetup-UWP-IL2CPP-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Android = ,"TargetSupportInstaller/UnitySetup-Android-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::iOS = ,"TargetSupportInstaller/UnitySetup-iOS-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::AppleTV = ,"TargetSupportInstaller/UnitySetup-AppleTV-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Facebook = ,"TargetSupportInstaller/UnitySetup-Facebook-Games-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Linux = ,"TargetSupportInstaller/UnitySetup-Linux-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Mac = "TargetSupportInstaller/UnitySetup-Mac-Support-for-Editor-$Version.exe", "TargetSupportInstaller/UnitySetup-Mac-Mono-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Vuforia = ,"TargetSupportInstaller/UnitySetup-Vuforia-AR-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::WebGL = ,"TargetSupportInstaller/UnitySetup-WebGL-Support-for-Editor-$Version.exe"; - [UnitySetupComponentType]::Windows_IL2CPP = ,"TargetSupportInstaller/UnitySetup-Windows-IL2CPP-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Vuforia = ,"TargetSupportInstaller/UnitySetup-Vuforia-AR-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::WebGL = ,"TargetSupportInstaller/UnitySetup-WebGL-Support-for-Editor-$Version.exe"; + [UnitySetupComponent]::Windows_IL2CPP = ,"TargetSupportInstaller/UnitySetup-Windows-IL2CPP-Support-for-Editor-$Version.exe"; } # By default Tls12 protocol is not enabled, but is what backs Unity's website, so enable it @@ -240,7 +259,7 @@ function Find-UnitySetupInstaller { $webResult = Invoke-WebRequest $page -UseBasicParsing $prototypeLink = $webResult.Links | Select-Object -ExpandProperty href -ErrorAction SilentlyContinue | Where-Object { - $_ -match "$($installerTemplates[[UnitySetupComponentType]::Setup])$" + $_ -match "$($installerTemplates[[UnitySetupComponent]::Setup])$" } if($null -ne $prototypeLink) { break } From 9037f8e19fedbc261e7713cc2d16de5f8eb3d5a0 Mon Sep 17 00:00:00 2001 From: Josh Wittner Date: Wed, 7 Mar 2018 13:53:27 -0800 Subject: [PATCH 2/3] Added xUnity DSC Resource --- README.md | 24 ++ .../DSCResources/xUnitySetup/xUnitySetup.psm1 | 210 ++++++++++++++++++ .../xUnitySetup/xUnitySetup.schema.mof | Bin 0 -> 816 bytes UnitySetup/Examples/Sample_xUnitySetup.ps1 | 28 +++ .../Examples/Sample_xUnitySetup_Install.ps1 | 16 ++ .../Examples/Sample_xUnitySetup_Uninstall.ps1 | 15 ++ 6 files changed, 293 insertions(+) create mode 100644 UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 create mode 100644 UnitySetup/DSCResources/xUnitySetup/xUnitySetup.schema.mof create mode 100644 UnitySetup/Examples/Sample_xUnitySetup.ps1 create mode 100644 UnitySetup/Examples/Sample_xUnitySetup_Install.ps1 create mode 100644 UnitySetup/Examples/Sample_xUnitySetup_Uninstall.ps1 diff --git a/README.md b/README.md index 89ca955..c955c1b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Install-Module UnitySetup -Scope CurrentUser ## Using +### Cmdlets Find all of your Unity installs: ```powershell Get-UnitySetupInstance @@ -113,6 +114,29 @@ Find-UnitySetupInstaller -Version '2017.3.0f3' | Install-UnitySetupInstance Install-UnitySetupInstance -Installers (Find-UnitySetupInstaller -Version '2017.3.0f3') ``` +### DSC +UnitySetup includes the xUnitySetup DSC Resource. An example configuration might look like: + +```powershell +<# + Install multiple versions of Unity and several components +#> +Configuration Sample_xUnitySetup_Install { + + Import-DscResource -ModuleName UnitySetup + + Node 'localhost' { + + xUnitySetup Unity { + Versions = '2017.3.1f1,2018.1.0b9' + Components = 'Setup', 'Mac', 'Linux', 'Metro', 'iOS' + Ensure = 'Present' + } + } +} +``` + +See more by perusing the `UnitySetup\Examples` folder. # Feedback To file issues or suggestions, please use the [Issues](https://github.com/Microsoft/unitysetup.powershell/issues) page for this project on GitHub. diff --git a/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 b/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 new file mode 100644 index 0000000..aa4b4ac --- /dev/null +++ b/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 @@ -0,0 +1,210 @@ + +<# +.Synopsis + Returns the status of Unity installs and the set of their overlapping components. +.Parameter Versions + The versions of Unity to test for. +#> +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Versions + ) + Write-Verbose "Begin executing Get on $Versions" + + [string[]]$splitVersions = $Versions -split ',' | ForEach-Object { $_.Trim() } + + $setupInstances = Get-UnitySetupInstance | Where-Object { $splitVersions -contains $_.Version } + $result = @{ + "Versions" = $setupInstances | Select-Object -ExpandProperty Version | Sort-Object -Unique + "Ensure" = ($setupInstances.Count -gt 0) + } + + Write-Verbose "Found versions: $($result['Versions'])" + + if( $setupInstances.Count -gt 0 ) + { + $components = $setupInstances[0].Components; + for( $i = 1; $i -lt $setupInstances.Count; $i++) + { + $components = $components -band $setupInstances[$i].Components; + } + + $result["Components"] = $components + } + + $result + + Write-Verbose "Found overlapping components: $($result['Components'])" + Write-Verbose "End executing Get on $Versions" +} + +<# +.Synopsis + Installs or uninstalls the specified Versions of Unity and corresponding Components. +.Parameter Versions + What versions are we concered with? +.Parameter Ensure + Should we ensure they're there or ensure they're not? +.Parameter Components + What components are we concerned with? +.Notes + Only uninstalls whole versions of Unity. Ensuring components doesn't + mean other components weren't previously installed and aren't still available. +#> +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Versions, + + [ValidateSet("Present","Absent")] + [System.String] + $Ensure = 'Present', + + [System.String[]] + $Components = @('All') + ) + + Write-Verbose "Begin executing Set to Ensure $Versions with $Components are $Ensure" + + [string[]]$splitVersions = $Versions -split ',' | ForEach-Object { $_.Trim() } + + switch($Ensure) { + 'Present' { + foreach($version in $splitVersions) + { + $findArgs = @{ + 'Version' = $version + 'Components' = New-UnitySetupComponent -Components $Components + } + + $installArgs = @{ 'Cache' = "$env:TEMP\.unitysetup" } + + $setupInstances = Get-UnitySetupInstance | Select-UnitySetupInstance -Version $version + if($setupInstances.Count -gt 0) { + $findArgs["Components"] = ($findArgs.Components -band (-bnot ($setupInstances[0].Components -band $findArgs.Components))) + $installArgs["Destination"] = $setupInstances[0].Path + } + + # No missing components for this version + if( $findArgs.Components -eq 0 ) { + Write-Verbose "All components of $version were installed" + continue; + } + + Write-Verbose "Finding $($findArgs["Components"]) installers for $version" + $installArgs["Installers"] = Find-UnitySetupInstaller @findArgs -WarningAction Stop + if( $installArgs.Installers.Count -gt 0 ) { + Write-Verbose "Starting install of $($installArgs.Installers.Count) components for $version" + Install-UnitySetupInstance @installArgs + Write-Verbose "Finished install of $($installArgs.Installers.Count) components for $version" + } + } + } + 'Absent' { + $setupInstances = Get-UnitySetupInstance | Where-Object { $splitVersions -contains $_.Version } + Write-Verbose "Found $($setupInstances.Count) instance(s) of $splitVersions" + + if( $setupInstances.Count -gt 0 ) { + Write-Verbose "Starting uninstall of $($setupInstances.Count) versions of Unity" + Uninstall-UnitySetupInstance -Instances $setupInstances + Write-Verbose "Finished uninstall of $($setupInstances.Count) versions of Unity" + } + } + } + + Write-Verbose "End executing Set to Ensure $Versions with $Components are $Ensure" +} + +<# +.Synopsis + Test if the Unity installs are in the desired state. +.Parameter Versions + What versions are we concered with? +.Parameter Ensure + Should we ensure they're there or ensure they're not? +.Parameter Components + What components are we concerned with? +.Notes + This test is not strict. Versions and Components not described are not considered. +#> +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [parameter(Mandatory = $true)] + [System.String] + $Versions, + + [ValidateSet("Present","Absent")] + [System.String] + $Ensure = 'Present', + + [System.String[]] + $Components = @('All') + ) + + Write-Verbose "Begin executing Test to verify $Versions with $Components are $Ensure" + + [string[]]$splitVersions = $Versions -split ',' | ForEach-Object { $_.Trim() } + + $result = $true + switch( $Ensure ) + { + 'Present' { + $setupComponents = New-UnitySetupComponent -Components $Components + foreach($version in $splitVersions) + { + Write-Verbose "Starting test for $version" + $setupInstances = Get-UnitySetupInstance | Select-UnitySetupInstance -Version $version + Write-Verbose "Found $($setupInstances.Count) instance(s) of $version" + + if($setupInstances.Count -eq 0) { + Write-Verbose "Found $version missing." + $result = $false + break + } + + $availableComponents = ($setupInstances[0].Components -band $setupComponents) + if($availableComponents -ne $setupComponents){ + $missingComponents = New-UnitySetupComponent ($setupComponents -bxor $availableComponents) + Write-Verbose "Found $version missing $($missingComponents)" + $result = $false + break + } + } + } + 'Absent' { + foreach($version in $splitVersions) + { + $setupInstances = Get-UnitySetupInstance | Select-UnitySetupInstance -Version $version + Write-Verbose "Found $($setupInstances.Count) instance(s) of $version" + + if($setupInstances.Count -gt 0) { + Write-Verbose "Found $version installed." + $result = $false + break + } + } + } + } + + $result + + Write-Verbose "End executing Test to verify $Versions with $Components are $Ensure" +} + + +Export-ModuleMember -Function *-TargetResource + diff --git a/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.schema.mof b/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.schema.mof new file mode 100644 index 0000000000000000000000000000000000000000..8d0d4be07780462d2f1c9a1cb7afb386bfbcef3f GIT binary patch literal 816 zcmbV~TT8=05QWdP;D1>1WI;q<^+B{MhrziT4cZdjlgp!PO6>uA%QX+P18t+H zE8?@D@GPJQL1&JJx}!EZ#*7$-2bHs%@D=Qb#8R-HlLPm{TzBL20jBoH&%8c0n;xuc|8M_Yy@k7R+_~Lb&YV^Kdny*3T{zb+*?q3N XRXVe-vV0HCyglA(sd!PX_S${`CTNO? literal 0 HcmV?d00001 diff --git a/UnitySetup/Examples/Sample_xUnitySetup.ps1 b/UnitySetup/Examples/Sample_xUnitySetup.ps1 new file mode 100644 index 0000000..e374e93 --- /dev/null +++ b/UnitySetup/Examples/Sample_xUnitySetup.ps1 @@ -0,0 +1,28 @@ +<# + Create a custom configuration by passing in necessary values +#> +Configuration Sample_xUnitySetup { + param + ( + [System.String] + $Versions = '2017.3.0f3,2018.1.0b9', + + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [System.String[]] + $Components = @('Setup','Linux','Metro','Mac','iOS') + ) + + Import-DscResource -ModuleName UnitySetup + + Node 'localhost' { + + xUnitySetup Unity { + Versions = $Versions + Components = $Components + Ensure = $Ensure + } + } +} \ No newline at end of file diff --git a/UnitySetup/Examples/Sample_xUnitySetup_Install.ps1 b/UnitySetup/Examples/Sample_xUnitySetup_Install.ps1 new file mode 100644 index 0000000..d9ebc8e --- /dev/null +++ b/UnitySetup/Examples/Sample_xUnitySetup_Install.ps1 @@ -0,0 +1,16 @@ +<# + Install multiple versions of Unity and several components +#> +Configuration Sample_xUnitySetup_Install { + + Import-DscResource -ModuleName UnitySetup + + Node 'localhost' { + + xUnitySetup Unity { + Versions = '2017.3.1f1,2018.1.0b9' + Components = 'Setup', 'Mac', 'Linux', 'Metro', 'iOS' + Ensure = 'Present' + } + } +} \ No newline at end of file diff --git a/UnitySetup/Examples/Sample_xUnitySetup_Uninstall.ps1 b/UnitySetup/Examples/Sample_xUnitySetup_Uninstall.ps1 new file mode 100644 index 0000000..8e09483 --- /dev/null +++ b/UnitySetup/Examples/Sample_xUnitySetup_Uninstall.ps1 @@ -0,0 +1,15 @@ +<# + Uninstall multiple versions of Unity +#> +Configuration Sample_xUnitySetup_Install { + + Import-DscResource -ModuleName UnitySetup + + Node 'localhost' { + + xUnitySetup Unity { + Versions = '2017.3.1f1,2018.1.0b9' + Ensure = 'Absent' + } + } +} \ No newline at end of file From a4c66a831754cfdaadfc6d8a765f5eca0d563866 Mon Sep 17 00:00:00 2001 From: Josh Wittner Date: Mon, 12 Mar 2018 15:40:33 -0700 Subject: [PATCH 3/3] Fix get Ensure value --- UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 b/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 index aa4b4ac..e84b7f8 100644 --- a/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 +++ b/UnitySetup/DSCResources/xUnitySetup/xUnitySetup.psm1 @@ -22,7 +22,7 @@ function Get-TargetResource $setupInstances = Get-UnitySetupInstance | Where-Object { $splitVersions -contains $_.Version } $result = @{ "Versions" = $setupInstances | Select-Object -ExpandProperty Version | Sort-Object -Unique - "Ensure" = ($setupInstances.Count -gt 0) + "Ensure" = if($setupInstances.Count -gt 0) { 'Present'} else { 'Absent' } } Write-Verbose "Found versions: $($result['Versions'])"