My version of ActiveSetup: Set-ADTActiveSetupV2

In V3 of the toolkit I had implemented a repair section, glad to see it in V4 but I also had an ActiveSetup section for installations that required more tweaking and wanting to use the flexibility of the wrapper. Here is my take on this for v4:

  • In Invoke-AppDeployToolkit.ps1 I added these variables in $adtSession
    ADTActiveSetupV2Location = "${env:PROGRAMDATA}\!CieName\ActiveSetup"
    PackageCode = ''
  • Add this function (which is basically a copy of the Repair function)
function ActiveSetup-ADTDeployment {
    ##================================================
	## MARK: ActiveSetup
    ##================================================
    $adtSession.InstallPhase = "Pre-ActiveSetup"

    ## Show Welcome Message, close Internet Explorer with a 60 second countdown before automatically closing.
    Show-ADTInstallationWelcome -CloseProcesses iexplore -CloseProcessesCountdown 60

    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress
	
	## <Perform Pre-ActiveSetup tasks here>
	
	
    ##================================================
	## MARK: ActiveSetup
    ##================================================
    $adtSession.InstallPhase = 'ActiveSetup'
	
	## <Perform ActiveSetup tasks here>
	
	
    ##================================================
	## MARK: Post-ActiveSetup
    ##================================================
    $adtSession.InstallPhase = "Post-ActiveSetup"
	
	## <Perform Post-ActiveSetup tasks here>
	
	
}

  • Make this modification to the function call at the end of the script
    if ($($adtSession.ScriptDirectory) -like "$($adtSession.ADTActiveSetupV2Location)*") { & ActiveSetup-ADTDeployment } 
    else { & "$($adtSession.DeploymentType)-ADTDeployment" }

  • Finally here is the function I added in the extensions:
function Set-ADTActiveSetupV2 {
<#
	.SYNOPSIS
		Enables a custom ActiveSetup scripted through this PoShADT Wrapper.
	
	.DESCRIPTION
		When used, an ActiveSetup will be configured to be executed on this computer using the function ActiveSetup-ADTDeployment for the tasks.
		The Wrapper will be configured to execute without Admin Rights.
	
	.PARAMETER Action
		Enable or Disable the ActiveSetup.
	
	.PARAMETER DeployMode
		Determines if and how the wrapper will display information on the screen while running.
	
	.PARAMETER DoNotRunNow
		To prevent the immidiate execution of the ActiveSetup for the current active desktop user.
	
	.PARAMETER Architecture
		Indicates which ActiveSetup registry key will be used.
	
	.EXAMPLE
		Set-ADTActiveSetupV2
		
		Invokes the New-ADTExampleFunction function and returns any output.
	
	.OUTPUTS
		None
		
		This function does not return any output.
	
	.NOTES
		Additional information about the function.
	
	.INPUTS
		None
		
		You cannot pipe objects to this function.
#>
	
	[CmdletBinding()]
	param
	(
		[Parameter(Mandatory = $true)][PSDefaultValue(Help = 'Disable', Value = 'Enable')][ValidateSet('Enable', 'Disable')][System.String]$Action,
		[Parameter(Mandatory = $false)][PSDefaultValue(Help = 'Interactive', Value = 'Silent')][ValidateSet('Interactive', 'Silent', 'NonInteractive')][System.String]$DeployMode = 'NonInteractive',
		[Parameter(Mandatory = $false)][System.Management.Automation.SwitchParameter]$DoNotRunNow,
		[ValidateSet('64-bit', '32-bit')][string]$Architecture = '64-bit'
	)
	
	begin {
		# Initialize function.
		Initialize-ADTFunction -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
		
		$ASDestination = Join-Path -Path $adtSession.ADTActiveSetupV2Location -ChildPath $adtSession.PackageCode
		New-ADTFolder -Path $ASDestination
		
		if ($DoNotRunNow -eq $true) { $ActiveSetupRunNow = $true }
		else { $ActiveSetupRunNow = $false }
		
		if ($Architecture -eq '32-bit') { $ActiveSetupWOW = $true }
		else { $ActiveSetupWOW = $false }
		
		if ($adtSession.PackageCode.Trim() -eq '') { $ActiveSetupKey = $adtSession.AppName }
		else { $ActiveSetupKey = $adtSession.PackageCode.Trim() }
	}
	
	process {
		try {
			try {
				if ($Action -eq 'Enable') {
					Get-ChildItem -Path "$($adtSession.ScriptDirectory)\*" | `
					Where-Object { $_.Name -notlike '*Files' } | `
					ForEach-Object {
						Copy-ADTFile -Path $_.FullName -Destination $ASDestination -Recurse -FileCopyMode Native
					}
					
					Remove-ADTFile -Path "$ASDestination\Config\config.psd1"
					Rename-Item -Path "$ASDestination\Config\ActiveSetup.config.psd1" -NewName 'config.psd1'
					
					Set-ADTActiveSetup -Key $ActiveSetupKey -StubExePath "$ASDestination\Invoke-AppDeployToolkit.exe" -Arguments "-DeploymentType Install -DeployMode $DeployMode" -DisableActiveSetup:$ActiveSetupRunNow -Wow6432Node:$ActiveSetupWOW
				}
				else {
					# ($Action -eq 'Disable')
					Remove-ADTFolder -Path $ASDestination
					Set-ADTActiveSetup -Key $ActiveSetupKey -PurgeActiveSetupKey
				}
			}
			catch {
				# Re-writing the ErrorRecord with Write-Error ensures the correct PositionMessage is used.
				Write-Error -ErrorRecord $_
			}
		}
		catch {
			# Process the caught error, log it and throw depending on the specified ErrorAction.
			Invoke-ADTFunctionErrorHandler -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState -ErrorRecord $_
		}
	}
	
	end {
		# Finalize function.
		Complete-ADTFunction -Cmdlet $PSCmdlet
	}
}

Along with a folder called ActiveSetup for what ever files are required at that time and changing the config.psd1 called ActiveSetup.config.psd1 to allow running as a user. (currently I made a copy of the file as I haven’t found a clever way to edit it).

I still call the wrapper function Set-ADTActiveSetup but this allows me a little more flexibility. This is in no way perfect but if you find it useful.

Always exciting to see v4 developments and extensions out in the wild! I apologise in advance, but it’s not 100% clear to me what this is doing exactly? Can you explain a bit more or give a real-world scenario?

Also, if the improvement is something isn’t niche and would be beneficial to all end users, PRs are welcome for stuff like this :right_facing_fist::left_facing_fist:

I was faced with a couple installations that were 2 parts, the 1st is system like most but the 2nd involved different operations and configurations that were very user specific to be performed in the end user context.

Most of the time I got by with the standard ActiveSetup or what is now Invoke-ADTAllUsersRegistryAction, but from time to time, I had to launch a script to run within the user context (using an ActiveSetup to launch a secondary script).

With this function we take care of everything in the wrapper, taking advantage of all that it brings instead of having a small script on the side. Everything is in the same place.