Set-ADTActiveSetup Error

I am using PSADT v. 4.0.4

Currently I am attempting to run an active setup when new users login.

Here is my current command:

Set-ADTActiveSetup -StubExePath "$Destination\timeStampUserProfile.ps1" -ExecutionPolicy 'Bypass' -Description 'timeStampUserProfile' -Key 'timeStampUserProfile'

I placed the script in the Files folder and the $Destination is the location I copy the script to on the local machine.

Here is the error I am gettting:

[Install] :: Standard error output from the process: File C:\ProgramData\AutoPilotConfig\Start-Menu\timeStampUserProfile.ps1 cannot be loaded because running scripts is 
disabled on this system. For more information, see about_Execution_Policies at 
https:/go.microsoft.com/fwlink/?LinkID=135170.
    + CategoryInfo          : SecurityError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnauthorizedAccess

Obviously this is an execution policy issue for the user. What changes do I need to make to the command to allow this script to run in the user context bypassing the execution policy?

Also, while I love the PSADT documentation I feel like some functions get a bare minimum explanation when it needs just a bit more. Set-ADTActiveSetup is one of those. does anyone have a slightly more comprehensive resource or writeup on the v. 4 active setup function and how to use it?

Please share any tips, tricks, and code on how you are using this function in v. 4. I would love to see what you all are doing.

Any ActiveSetup script or EXE must be able to run as a user.
So find out:

Login as the user.

in a PowerShell console run Get-ExecutionPolicy
It should be Remote-Signed or Unsigned.

Next, are you running AppLocker or WDAC?
If so, you have to make sure users can run PowerShell scripts from that location.
BTW: C:\ProgramData is a poor choice because any user can write there.
This is why PSADT uses C:\Program Files\PSADT for its scripts.

No AppLocker or WDAC.

So if I change

Set-ADTActiveSetup -StubExePath "$Destination\timeStampUserProfile.ps1" -ExecutionPolicy 'Bypass' -Description 'timeStampUserProfile' -Key 'timeStampUserProfile'

to

Set-ADTActiveSetup -StubExePath "timeStampUserProfile.ps1" -ExecutionPolicy 'Bypass' -Description 'timeStampUserProfile' -Key 'timeStampUserProfile'

Will PSADT dump the file in “C:\Program Files\PSADT” by default? It seems PSADT isn’t creating this directory by default unless it needs to.

I do set permissions on the $Destination dir

Set-ADTItemPermission -Path $Destination -User 'DOMAIN\Domain Users', 'BUILTIN\Users' -Permission ReadAndExecute -Inheritance ObjectInherit, ContainerInherit

Right now my desktops are Windows default “Restricted” and I set my PowerShell TS steps or commands to bypass.

This command is part of a settings package to configure local user settings bypassing the Windows UCPD driver, in and out of domain. It will run in an OSD task sequence, but possibly deployed separately as needed.

I am assuming that the user can’t bypass the policy, because
 User. So the policy needs to change to Remote-Signed (best) or Unsigned (almost unrestricted) for the current user or user group?

Is there another method to run these scripts once, in bypass mode, as SYSTEM, on behalf of the user, for each new user that signs in?

@That-Annoying-Guy I always appreciate your knowledge and detailed quick responses to this forum. Do you have any good resources or cheat sheets that go into a bit more detail on the Set-ADTActiveSetup function with more usage examples?

Looks like your main issue is the execution policy.
Fix that first.

If you want to have SYSTEM launch something as the user you can use Start-ADTProcessAsUser
This gets launched at install time.
The Catch? there better be a user to run as or this line will fail.
So this will not work for unattended installs.

ActiveSetup works for unattended and attended installs
For all your options, consult this:

When I have time, I’ll test it out. Currently, I only have a per-user installation. Active Setup is easy once you understand it, although you do have to adapt the template. Currently, I only have version 3.x, where I only need the Active Setup function and don’t use an MSI.

The fact is, you want to run a Powershell script - an easy example without PSAD implementation.

important is the syntax of the StubPath in case of problems as REG_ExPAND_SZ

Windows 11, 64-bit
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\ShowPinTask]
@="ShowPinTask"
"StubPath"="powershell.exe -NonInteractive -executionpolicy bypass -file \"C:\\Program Files (x86)\\ShowPinTaskScript\\SetNotifyIconSetting.ps1\""
"Version"="2408,1913,0018"
Example 2
StubPath in Reg <powershell -NonInteractive -executionpolicy bypass -file "C:\Program Files (x86)\AdobeReaderDC2023-Setting\Usersetting\UserSetting.ps1">
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Active Setup\Installed Components\AdobeReaderDC2023-Setting V1.0.0.0]
"Version"="1,0,0,0"
"StubPath"=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,\
  20,00,2d,00,4e,00,6f,00,6e,00,49,00,6e,00,74,00,65,00,72,00,61,00,63,00,74,\
  00,69,00,76,00,65,00,20,00,2d,00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,\
  6f,00,6e,00,70,00,6f,00,6c,00,69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,\
  00,73,00,73,00,20,00,2d,00,66,00,69,00,6c,00,65,00,20,00,22,00,43,00,3a,00,\
  5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,20,00,46,00,69,00,6c,00,65,\
  00,73,00,20,00,28,00,78,00,38,00,36,00,29,00,5c,00,41,00,64,00,6f,00,62,00,\
  65,00,52,00,65,00,61,00,64,00,65,00,72,00,44,00,43,00,32,00,30,00,32,00,33,\
  00,2d,00,53,00,65,00,74,00,74,00,69,00,6e,00,67,00,5c,00,55,00,73,00,65,00,\
  72,00,73,00,65,00,74,00,74,00,69,00,6e,00,67,00,5c,00,55,00,73,00,65,00,72,\
  00,53,00,65,00,74,00,74,00,69,00,6e,00,67,00,2e,00,70,00,73,00,31,00,22,00,\
  00,00
"Author"="Toni Strodel"
"Product"="AdobeReaderDC2023-Setting V1.0.0.0"

for SCCM
msi under User, I only have Active Setup with V3.x, V4.x I still have to work out and test

Attention, here I’m doing another trick: if a version is available, everything will be skipped. Because Microsoft performs an update from its own server when it is started.

Customize template config.psd1
because of MSI Restart Manager /qn

    # InstallParams = 'ALLUSERS=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
	InstallParams = 'ALLUSERS=2 MSIINSTALLPERUSER=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'	InstallParams = 'ALLUSERS=2 MSIINSTALLPERUSER=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
	
	# Installation parameters used for silent MSI actions.
    # SilentParams = 'ALLUSERS=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN' 
    SilentParams = 'ALLUSERS=2 MSIINSTALLPERUSER=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
		
	#Installation parameters used for MSI uninstall actions.
    # UninstallParams = 'ALLUSERS=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
     UninstallParams = 'ALLUSERS=2 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
	 
    # Registry key used to store toolkit information (with PSAppDeployToolkit as child registry key), e.g. deferral history.
    RegPath = 'HKCU:\SOFTWARE'

    # Specify if Administrator Rights are required. Note: Some functions won't work if this is set to false, such as deferral, block execution, file & registry RW access and potentially logging.
    # RequireAdmin = $true       
    RequireAdmin = $false		
RemoteDesktop Invoke-AppDeployToolkit.ps1

<#

.SYNOPSIS
PSAppDeployToolkit - This script performs the installation or uninstallation of an application(s).

.DESCRIPTION
- The script is provided as a template to perform an install, uninstall, or repair of an application(s).
- The script either performs an "Install", "Uninstall", or "Repair" deployment type.
- The install deployment type is broken down into 3 main sections/phases: Pre-Install, Install, and Post-Install.

The script imports the PSAppDeployToolkit module which contains the logic and functions required to install or uninstall an application.

PSAppDeployToolkit is licensed under the GNU LGPLv3 License - (C) 2024 PSAppDeployToolkit Team (Sean Lillis, Dan Cunningham, Muhammad Mashwani, Mitch Richters, Dan Gough).

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

.PARAMETER DeploymentType
The type of deployment to perform. Default is: Install.

.PARAMETER DeployMode
Specifies whether the installation should be run in Interactive, Silent, or NonInteractive mode. Default is: Interactive. Options: Interactive = Shows dialogs, Silent = No dialogs, NonInteractive = Very silent, i.e. no blocking apps. NonInteractive mode is automatically set if it is detected that the process is not user interactive.

.PARAMETER AllowRebootPassThru
Allows the 3010 return code (requires restart) to be passed back to the parent process (e.g. SCCM) if detected from an installation. If 3010 is passed back to SCCM, a reboot prompt will be triggered.

.PARAMETER TerminalServerMode
Changes to "user install mode" and back to "user execute mode" for installing/uninstalling applications for Remote Desktop Session Hosts/Citrix servers.

.PARAMETER DisableLogging
Disables logging to file for the script. Default is: $false.

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -DeployMode Silent

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -AllowRebootPassThru

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -DeploymentType Uninstall

.EXAMPLE
Invoke-AppDeployToolkit.exe -DeploymentType "Install" -DeployMode "Silent"

.INPUTS
None. You cannot pipe objects to this script.

.OUTPUTS
None. This script does not generate any output.

.NOTES
Toolkit Exit Code Ranges:
- 60000 - 68999: Reserved for built-in exit codes in Invoke-AppDeployToolkit.ps1, and Invoke-AppDeployToolkit.exe
- 69000 - 69999: Recommended for user customized exit codes in Invoke-AppDeployToolkit.ps1
- 70000 - 79999: Recommended for user customized exit codes in PSAppDeployToolkit.Extensions module.

.LINK
https://psappdeploytoolkit.com

#>

[CmdletBinding()]
param
(
    [Parameter(Mandatory = $false)]
    [ValidateSet('Install', 'Uninstall', 'Repair')]
    [System.String]$DeploymentType = 'Install',

    [Parameter(Mandatory = $false)]
    [ValidateSet('Interactive', 'Silent', 'NonInteractive')]
    [System.String]$DeployMode = 'Interactive',

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$AllowRebootPassThru,

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$TerminalServerMode,

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$DisableLogging
)


##================================================
## MARK: Variables
##================================================

$adtSession = @{
	##*===============================================    
    # App variables.
	##*===============================================
    AppVendor = 'Microsoft'
    AppName = 'RemoteDesktop'
    AppVersion = '1.2.6014.0'
    AppArch = 'x64'
    AppLang = 'EN'
    AppRevision = '01'
    AppSuccessExitCodes = @(0)
    AppRebootExitCodes = @(1641, 3010)
    AppScriptVersion = '1.0.0'
    AppScriptDate = '2025-02-20'
    AppScriptAuthor = 'Toni Strodel'

	##===============================================
    # Install Titles (Only set here to override defaults set by the toolkit).
    ##===============================================
    InstallName = '101250-Microsoft-RemoteDesktop_1.2.6014.0_x64'
    InstallTitle = '101250-Microsoft-RemoteDesktop_1.2.6014.0_x64'
	##===============================================

    # Script variables.
    DeployAppScriptFriendlyName = $MyInvocation.MyCommand.Name
    DeployAppScriptVersion = '4.0.5'
    DeployAppScriptParameters = $PSBoundParameters
}

    ##*===============================================
    ##* Toni VARIABLE DECLARATION Package
    ##*===============================================
	[string]$appScriptIDNr = '101250'
        # mehrere können nicht per Variablen gelöst werden
	[string]$appCloseApp = 'msrdcw,msrdc'

    ##*===============================================
    ##* Toni VARIABLE DECLARATION SystemEnvironment
    ##*===============================================
    [string]$MyFirma=$env:c_Firma
    [string]$MyLanguage=$env:c_Sprache

    # neue Version von Remote Destop ist
    [version]$MyInstallVersion="1.2.6014.0"

	##===============================================
    # Install Files
    ##===============================================
    [string]$MyMSIFile ='RemoteDesktop_1.2.6014.0_x64.msi'
    # your install Parameter EDITOR_LANGUAGE=de-DE NOUPDATER=1 SET_AS_DEFAULT=0
    [string]$MyArgumentList='yourinstallParameter'
    [string]$MyArgumentListDE='yourinstallParameter'
    [string]$MyArgumentListFR='yourinstallParameter'
    # wurde in der Config.psd1 angepasst
    # 'ALLUSERS=2 MSIINSTALLPERUSER=1 REBOOT=ReallySuppress REBOOTPROMPT=Suppress ROOTDRIVE=C:\ /QN'
    # Your MSI ProductName zb. Notepad++
    [string]$MyRemove='RemoteDesktop'
    [string]$MyRemoveFR='Bureau Ă  distance'
	##===============================================


function Install-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Install
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

    ## Show Welcome Message, close Internet Explorer if required, allow up to 3 deferrals, verify there is enough disk space to complete the install, and persist the prompt.
    # Show-ADTInstallationWelcome -CloseProcesses iexplore -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt

    <# nicht verwenden, gibt Probleme bei der Installation im Start-Image
    If ($appCloseApp -notlike $Null)
        {
        # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        }
    #> 

    #region Check installierte Version ============================
    # nur bei bestehder Installation, damit ich die Version ohne Installation ersetze kann
    # Install per User
    # C:\Users\strodel\AppData\Local\Programs\Remote Desktop\
    $MyUser="$env:username"
    Write-ADTLogEntry -Message "angemeldetet User: $MyUser"
    # [version]$MyCheckVersion="0.0.0.0"

    $CheckInstall=Test-Path -Path $env:LOCALAPPDATA'\Programs\Remote Desktop\msrdc.exe'
    If ($CheckInstall -like $true)
        {
        [version]$MyCheckVersion=Get-ADTFileVersion -File "C:\Users\$MyUser\AppData\Local\Programs\Remote Desktop\msrdc.exe" -ProductVersion
        }

    Write-ADTLogEntry -Message "Installierte Version:  $MyCheckVersion"
    # "UpdateValue: " + $MyUpdate
    Write-ADTLogEntry -Message "Version der Installation: $MyInstallVersion"


    try {
        if ($CheckInstall -like $false)
        #  if ($MyCheckVersion -like $Null)
            {
                
                # Write-ADTLogEntry -Message "Braucht Update, Installiere:  $MyInstallVersion"
                # $MyUpdate=0
                Write-ADTLogEntry -Message "Kein RemoteDesktop vorhanden, Installation nötig"
                $MyUpdate=0
            }
        
        # Grösser, was Du willst ob es grösser ist, was Du hast
        elseif ($MyInstallVersion -gt $MyCheckVersion)
        # if ($MyInstallVersion -gt $MyCheckVersion)
        # if ($MyCheckVersion -gt $MyInstallVersion)
            {
                
                # Write-ADTLogEntry -Message "Braucht Update, Installiere:  $MyInstallVersion"
                # $MyUpdate=0
                Write-ADTLogEntry -Message "RemoteDesktop vorhanden, keine Installation:  $MyInstallVersion"
                $MyUpdate=1
            }

        else
            {
                Write-ADTLogEntry -Message "geprĂŒfte Version gewuenscht/vorhanden: $MyInstallVersion als $MyCheckVersion"
                Write-ADTLogEntry -Message "ĂŒberspringe Installation"
                $MyUpdate=1
            }
        "UpdateValue: " + $MyUpdate
    }


    Catch {
                $MyUpdate = 9
                Write-ADTLogEntry -Message "Kontrollwert: $MyUpdate"
                }

                Write-ADTLogEntry -Message "UpdateVersion = 0 - Braucht Installation"
                Write-ADTLogEntry -Message "UpdateVersion = 1 - Installation vorhanden oder Neuere Version installiert - uebersprungen"
                Write-ADTLogEntry -Message "UpdateVersion = 9 - Fehler"
                Write-ADTLogEntry -Message "Updatepruefung Paramter: $MyUpdate"

        If ($MyUpdate -like "9") 
          {   
             Write-ADTLogEntry -Message "Fehler , Abbruch"
             $global:ExitCode = 5000
             Write-ADTLogEntry -Message "ExitCode: $ExitCode"
             # Write-Log "LASTEXITCODE: $LASTEXITCODE"

             # Exit PSAD
             # V3 Exit-Script -ExitCode 5000
             Close-ADTSession -ExitCode 5000
             # Powershell normal
             #  exit 0

          }

    #endregion ===========================

    #region Check installierte Version ============================
    # Nur wenn die Vorversion Àlter ist, wird es Deinstalliert und kommt ein Dialog
    If ($MyUpdate -like "0") 
        {
        If ($appCloseApp -notlike $Null)
            {
              # [string]$appCloseApp = 'msrdcw,msrdc'
              # Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
              Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'msrdc' }, @{ Name = 'msrdcw' }  -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
            }

  
        ## Show Progress Message (with the default message).
        Show-ADTInstallationProgress

		
		## <Perform Pre-Installation tasks here>
		# ==== Deinstallation der Vorversion - Anzeigename im Add/Remove - DisplayName
        #  Write-Log "*** No Remove Previor Version"
        # Nur wenn per User
	    # Write-Log "==== Remove Previor Installation"		
        #V3 Remove-MSIApplications -Name 'RemoteDesktop' 
        #V3 Remove-MSIApplications -Name 'Bureau Ă  distance'
 
     If ($MyUpdate -like "0") 
        {
          Write-ADTLogEntry -Message "keine Deinstallation, wenn vorhanden oder neuere Version"
          Uninstall-ADTApplication -Name $MyRemove -ApplicationType 'MSI'
          Uninstall-ADTApplication -Name $MyRemoveFR -ApplicationType 'MSI'
        }
    }
    #endregion ===========================

    ##================================================
    ## MARK: Install
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI installations.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
        if ($adtSession.DefaultMspFiles)
        {
            $adtSession.DefaultMspFiles | Start-ADTMsiProcess -Action Patch
        }
    }
       
    ##*===============================================
    ##* Log SystemEnvironment
    ##*=============================================== 
    Write-ADTLogEntry -Message "==== Client SystemEnvironment"
    Write-ADTLogEntry -Message "SystemEnvironment c_Domain        : $env:c_Domain"
    Write-ADTLogEntry -Message "SystemEnvironment c_Firma         : $MyFirma"        
    Write-ADTLogEntry -Message "SystemEnvironment c_Nova          : $env:c_Nova"
    Write-ADTLogEntry -Message "SystemEnvironment c_OfficeTemplate: $env:c_OfficeTemplate"
    Write-ADTLogEntry -Message "SystemEnvironment c_ProfitCenter  : $env:c_ProfitCenter"
    Write-ADTLogEntry -Message "SystemEnvironment c_SccmSrv       : $env:c_SccmSrv"
    Write-ADTLogEntry -Message "SystemEnvironment c_Sprache       : $MyLanguage"
    Write-ADTLogEntry -Message "SystemEnvironment c_Tastatur      : $env:c_Tastatur"
    Write-ADTLogEntry -Message "SystemEnvironment c_ThereForeSrv  : $env:c_ThereForeSrv"
    Write-ADTLogEntry -Message "==== Ende Client SystemEnvironment"

    ## <Perform Installation tasks here>
    #region Check installierte Version ============================
    # Nur wenn die Vorversion Àlter ist, wird es Deinstalliert und kommt ein Dialog
    If ($MyUpdate -like "0") 
        {
        $MyUser="$env:username"
        Write-ADTLogEntry -Message "User $MyUser"
        
        # LogName kann nicht geÀndert werden
        Write-ADTLogEntry -Message "LogName is $logName"

        Write-ADTLogEntry -Message "Installation"
        Start-ADTMsiProcess -Action 'Install' -FilePath $MyMSIFile
        }
    #endregion ===========================


	# ============== Vorversions kontrolle entfernen ===================================
    # User
    # V3 Remove-RegistryKey -Key 'HKEY_CURRENT_USER\Software\Maintenance\Applications\101250-Microsoft-RemoteDesktop 1.2.4065.0 EN 1.0'
    Remove-ADTRegistryKey -Key 'HKEY_CURRENT_USER\Software\Maintenance\Applications\101250-Microsoft-RemoteDesktop 1.2.4066.0 EN 2.0'
    Remove-ADTRegistryKey -Key 'HKEY_CURRENT_USER\Software\Maintenance\Applications\101250-Microsoft-RemoteDesktop 1.2.4157.0 EN 1.0'
    Remove-ADTRegistryKey -Key 'HKEY_CURRENT_USER\Software\Maintenance\Applications\101250-Microsoft-RemoteDesktop 1.2.4487.0 EN 1.0'
    Remove-ADTRegistryKey -Key 'HKEY_CURRENT_USER\Software\Maintenance\Applications\101250-Microsoft-RemoteDesktop 1.2.5454.0 EN 1.0'

    # =========== Aktualisiert Software Cente =========================================
    # Aktualisiert Software Center bzgl. Software
    # V3 Invoke-SCCMTask 'SoftwareUpdatesAgentAssignmentEvaluation'
    # per User nicht verwenden !!!!
    # Invoke-ADTSCCMTask 'SoftwareUpdatesAgentAssignmentEvaluation'

    
    ##================================================
    ## MARK: Post-Install
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Installation tasks here>

    ##*===============================================
    ##* Log SystemEnvironment
    ##*=============================================== 
    Write-ADTLogEntry -Message "==== Client SystemEnvironment"
    Write-ADTLogEntry -Message "SystemEnvironment c_Domain        : $env:c_Domain"
    Write-ADTLogEntry -Message "SystemEnvironment c_Firma         : $MyFirma"        
    Write-ADTLogEntry -Message "SystemEnvironment c_Nova          : $env:c_Nova"
    Write-ADTLogEntry -Message "SystemEnvironment c_OfficeTemplate: $env:c_OfficeTemplate"
    Write-ADTLogEntry -Message "SystemEnvironment c_ProfitCenter  : $env:c_ProfitCenter"
    Write-ADTLogEntry -Message "SystemEnvironment c_SccmSrv       : $env:c_SccmSrv"
    Write-ADTLogEntry -Message "SystemEnvironment c_Sprache       : $MyLanguage"
    Write-ADTLogEntry -Message "SystemEnvironment c_Tastatur      : $env:c_Tastatur"
    Write-ADTLogEntry -Message "SystemEnvironment c_ThereForeSrv  : $env:c_ThereForeSrv"
    Write-ADTLogEntry -Message "==== Ende Client SystemEnvironment"

	# nur Deutsch
    if ($MyLanguage -like "de-DE"  ) 
        {
        $MyMessage="Bitte ab- und anmelden bevor Sie die Applikation nutzen"
        }

    # nur French
    if ($MyLanguage -like "fr-Fr" ) 
        {
        $MyMessage="Veuillez vous déconnecter et vous connecter avant d'utiliser l'application"
        }

    # damit Show-ADTInstallationPrompt sicher nie den Wert $Null hat, welcher den Fehler 60001 bringt
    # if ($MyLanguage -notlike "de-DE" -or $MyLanguage -notlike "fr-Fr" ) {$MyMessage="noLanguage"}

    ## Display a message at the end of the install.
    # if (!$adtSession.UseDefaultMsi) {Show-ADTInstallationPrompt -Message $MyMessage -ButtonRightText 'OK' -Icon Information -NoWait}
}

function Uninstall-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Uninstall
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

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

    If ($appCloseApp -notlike $Null)
        {
          # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
          # Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -CloseProcessesCountdown 60
          # [string]$appCloseApp = 'msrdcw,msrdc'
          Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'msrdc' }, @{ Name = 'msrdcw' }  -CloseProcessesCountdown 60
        }


    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress

    ## <Perform Pre-Uninstallation tasks here>


    ##================================================
    ## MARK: Uninstall
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI uninstallations.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
    }

    ## <Perform Uninstallation tasks here>
    # V3 Execute-Process -Path "C:\Windows\System32\MsiExec.exe" -Parameters "/x `"$dirFiles\RemoteDesktop_1.2.2924.0_x64.msi`" /QN /L* C:\Logfiles\RemoteDesktop_1.2.2924.0_x64-Remove.log"
    # V3 Execute-MSI -Path EditorV9.x64.msi -Action Uninstall
    Write-ADTLogEntry -Message "Deinstallation"
    Uninstall-ADTApplication -Name $MyRemove -ApplicationType 'MSI'
    Uninstall-ADTApplication -Name $MyRemoveFR -ApplicationType 'MSI'

    ##================================================
    ## MARK: Post-Uninstallation
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Uninstallation tasks here>
}

function Repair-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Repair
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

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

    If ($appCloseApp -notlike $Null)
        {
          # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
          # V4 Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
          # [string]$appCloseApp = 'msrdcw,msrdc'
          Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'msrdc' }, @{ Name = 'msrdcw' } -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        }

    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress

    ## <Perform Pre-Repair tasks here>


    ##================================================
    ## MARK: Repair
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI repairs.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
    }

    ## <Perform Repair tasks here>
    Write-ADTLogEntry -Message "** ReInstallation - uninstall"
    Uninstall-ADTApplication -Name $MyRemove -ApplicationType 'MSI'
    Uninstall-ADTApplication -Name $MyRemoveFR -ApplicationType 'MSI'

    Write-ADTLogEntry -Message "ReInstallation"
    Start-ADTMsiProcess -Action 'Install' -FilePath $MyMSIFile

    ##================================================
    ## MARK: Post-Repair
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Repair tasks here>
}


##================================================
## MARK: Initialization
##================================================

# Set strict error handling across entire operation.
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$ProgressPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
Set-StrictMode -Version 1

# Import the module and instantiate a new session.
try
{
    $moduleName = if ([System.IO.File]::Exists("$PSScriptRoot\PSAppDeployToolkit\PSAppDeployToolkit.psd1"))
    {
        Get-ChildItem -LiteralPath $PSScriptRoot\PSAppDeployToolkit -Recurse -File | Unblock-File -ErrorAction Ignore
        "$PSScriptRoot\PSAppDeployToolkit\PSAppDeployToolkit.psd1"
    }
    else
    {
        'PSAppDeployToolkit'
    }
    Import-Module -FullyQualifiedName @{ ModuleName = $moduleName; Guid = '8c3c366b-8606-4576-9f2d-4051144f7ca2'; ModuleVersion = '4.0.5' } -Force
    try
    {
        $iadtParams = Get-ADTBoundParametersAndDefaultValues -Invocation $MyInvocation
        $adtSession = Open-ADTSession -SessionState $ExecutionContext.SessionState @adtSession @iadtParams -PassThru
    }
    catch
    {
        Remove-Module -Name PSAppDeployToolkit* -Force
        throw
    }
}
catch
{
    $Host.UI.WriteErrorLine((Out-String -InputObject $_ -Width ([System.Int32]::MaxValue)))
    exit 60008
}


##================================================
## MARK: Invocation
##================================================

try
{
    Get-Item -Path $PSScriptRoot\PSAppDeployToolkit.* | & {
        process
        {
            Get-ChildItem -LiteralPath $_.FullName -Recurse -File | Unblock-File -ErrorAction Ignore
            Import-Module -Name $_.FullName -Force
        }
    }
    & "$($adtSession.DeploymentType)-ADTDeployment"
    Close-ADTSession
}
catch
{
    Write-ADTLogEntry -Message ($mainErrorMessage = Resolve-ADTErrorRecord -ErrorRecord $_) -Severity 3
    Show-ADTDialogBox -Text $mainErrorMessage -Icon Stop | Out-Null
    Close-ADTSession -ExitCode 60001
}
finally
{
    Remove-Module -Name PSAppDeployToolkit* -Force
}


This is really good information thanks!

@Toni Thanks for your information as well I appreciate your examples.

Don't forget, it must be installed by machine, it is an active setup, no adjustments of PSADT template V4.x necessary

I tested it with 4.0.6

wherever the time comes
Due to the syntax in V4, you have to do various things differently.
One negative here is that a system file like Powershell must be specified with the exact path, and the entry is a REG_SZ (string). If you have problems, do it with REG_EXPAND_SZ, just remember to do error checking if it's present.

$MyPath1="HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\ShowPinTask"
New-ItemProperty -Path $MyPath1 -Name 'ShowPinTask' -Value 'powershell.exe -NonInteractive -executionpolicy bypass -file "C:\Program Files (x86)\ShowPinTaskScript\SetNotifyIconSetting.ps1"' -PropertyType ExpandString -Force

Quick example
$MyPath1 = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\ShowPinTask"
$PropertyName = "ShowPinTask"
$PropertyValue = 'powershell.exe -NonInteractive -executionpolicy bypass -file "C:\Program Files (x86)\ShowPinTaskScript\SetNotifyIconSetting.ps1"'

Beispiel auf die Schnnelle
$MyPath1 = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\ShowPinTask"
$PropertyName = "ShowPinTask"
$PropertyValue = 'powershell.exe -NonInteractive -executionpolicy bypass -file "C:\Program Files (x86)\ShowPinTaskScript\SetNotifyIconSetting.ps1"'

Fehlerbehandlung aktivieren

try {
# PrĂŒfen, ob der Pfad existiert, wenn nicht, erstellen
if (-not (Test-Path $MyPath1)) {
Write-Host "Registrierungspfad existiert nicht. Erstelle ihn..." -ForegroundColor Yellow
New-Item -Path $MyPath1 -Force | Out-Null
}

# Eigenschaft setzen oder aktualisieren
New-ItemProperty -Path $MyPath1 -Name $PropertyName -Value $PropertyValue -PropertyType ExpandString -Force -ErrorAction Stop

Write-Host "Registrierungseintrag erfolgreich erstellt/geÀndert." -ForegroundColor Green

} catch {
Write-Host "Fehler beim Erstellen der Registrierungseinstellung: $_" -ForegroundColor Red
}

Now you just have to understand it and do it correctly.
PSADT runs Active Setup during installation under the user, thus creating entry 2.
Normally, this is done via logoff/login, then the key is executed from HKLM in HKCU, if not present.

1 Like

Invoke-AppDeployToolkit.ps1

<#

.SYNOPSIS
PSAppDeployToolkit - This script performs the installation or uninstallation of an application(s).

.DESCRIPTION
- The script is provided as a template to perform an install, uninstall, or repair of an application(s).
- The script either performs an "Install", "Uninstall", or "Repair" deployment type.
- The install deployment type is broken down into 3 main sections/phases: Pre-Install, Install, and Post-Install.

The script imports the PSAppDeployToolkit module which contains the logic and functions required to install or uninstall an application.

PSAppDeployToolkit is licensed under the GNU LGPLv3 License - (C) 2025 PSAppDeployToolkit Team (Sean Lillis, Dan Cunningham, Muhammad Mashwani, Mitch Richters, Dan Gough).

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

.PARAMETER DeploymentType
The type of deployment to perform.

.PARAMETER DeployMode
Specifies whether the installation should be run in Interactive (shows dialogs), Silent (no dialogs), or NonInteractive (dialogs without prompts) mode.

NonInteractive mode is automatically set if it is detected that the process is not user interactive.

.PARAMETER AllowRebootPassThru
Allows the 3010 return code (requires restart) to be passed back to the parent process (e.g. SCCM) if detected from an installation. If 3010 is passed back to SCCM, a reboot prompt will be triggered.

.PARAMETER TerminalServerMode
Changes to "user install mode" and back to "user execute mode" for installing/uninstalling applications for Remote Desktop Session Hosts/Citrix servers.

.PARAMETER DisableLogging
Disables logging to file for the script.

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -DeployMode Silent

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -AllowRebootPassThru

.EXAMPLE
powershell.exe -File Invoke-AppDeployToolkit.ps1 -DeploymentType Uninstall

.EXAMPLE
Invoke-AppDeployToolkit.exe -DeploymentType "Install" -DeployMode "Silent"

.INPUTS
None. You cannot pipe objects to this script.

.OUTPUTS
None. This script does not generate any output.

.NOTES
Toolkit Exit Code Ranges:
- 60000 - 68999: Reserved for built-in exit codes in Invoke-AppDeployToolkit.ps1, and Invoke-AppDeployToolkit.exe
- 69000 - 69999: Recommended for user customized exit codes in Invoke-AppDeployToolkit.ps1
- 70000 - 79999: Recommended for user customized exit codes in PSAppDeployToolkit.Extensions module.

.LINK
https://psappdeploytoolkit.com

#>

[CmdletBinding()]
param
(
    [Parameter(Mandatory = $false)]
    [ValidateSet('Install', 'Uninstall', 'Repair')]
    [PSDefaultValue(Help = 'Install', Value = 'Install')]
    [System.String]$DeploymentType,

    [Parameter(Mandatory = $false)]
    [ValidateSet('Interactive', 'Silent', 'NonInteractive')]
    [PSDefaultValue(Help = 'Interactive', Value = 'Interactive')]
    [System.String]$DeployMode,

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$AllowRebootPassThru,

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$TerminalServerMode,

    [Parameter(Mandatory = $false)]
    [System.Management.Automation.SwitchParameter]$DisableLogging
)


##================================================
## MARK: Variables
##================================================

$adtSession = @{
	##*===============================================    
    # App variables.
	##*===============================================
    AppVendor = 'Toni'
    AppName = 'ShowPinTask'
    AppVersion = '2'
    AppArch = 'x86'
    AppLang = 'EN'
    AppRevision = '01'
    AppSuccessExitCodes = @(0)
    AppRebootExitCodes = @(1641, 3010)
    AppScriptVersion = '1.0.0'
    AppScriptDate = '2000-12-31'
    AppScriptAuthor = 'Toni Strodel'

	##===============================================
    # Install Titles (Only set here to override defaults set by the toolkit).
    ##===============================================
    InstallName = '100691-ShowPinTask 4.0.6'
    InstallTitle = '100691-ShowPinTask 4.0.6'
	##===============================================

    # Script variables.
    DeployAppScriptFriendlyName = $MyInvocation.MyCommand.Name
    DeployAppScriptVersion = '4.0.6'
    DeployAppScriptParameters = $PSBoundParameters
}

    ##*===============================================
    ##* Toni VARIABLE DECLARATION Package
    ##*===============================================
	[string]$appScriptIDNr = '100691'
    # mehrere können nicht per Variablen gelöst werden
	[string]$appCloseApp = ''


    ##*===============================================
    ##* Toni VARIABLE DECLARATION SystemEnvironment
    ##*===============================================
    [string]$MyFirma=$env:c_Firma
    [string]$MyLanguage=$env:c_Sprache

	##===============================================
    # Install Files
    ##===============================================
    # manual Active Setup without MSI - must be done by machine !!!! 
    # Active Setup Run only Once
    # if no Log, SetNotifyIconSetting.ps1 generate a New Run - only finished when the log is available 
    #   $MyPath1="HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
    #   New-ItemProperty -Path $MyPath1 -Name 'ShowPinTask' -Value 'powershell.exe -NonInteractive -executionpolicy bypass -file "C:\Program Files (x86)\ShowPinTaskScript\SetNotifyIconSetting.ps1"' -PropertyType ExpandString -Force 
    
    [string]$MyShowPinTaskFolder="C:\Program Files (x86)\ShowPinTaskScript"
    [string]$MyShowPinTaskScript="SetNotifyIconSetting.ps1"
        
    [string]$MyMSIFile ='yourMSI'
    [string]$MyMSITransformFile ='yourTransform'
    [string]$MyMSITransformFileDE ='yourTransform'
    [string]$MyMSITransformFileFR ='yourTransform'
    [string]$MyExeFile ='yourExeFile'
    # your install Parameter EDITOR_LANGUAGE=de-DE NOUPDATER=1 SET_AS_DEFAULT=0
    [string]$MyArgumentList='yourinstallParameter'
    [string]$MyArgumentListDE='yourinstallParameter'
    [string]$MyArgumentListFR='yourinstallParameter'
    # Your MSI ProductName zb. Notepad++
    [string]$MyRemove='yourProductname'
	##===============================================


function Install-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Install
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

    ## Show Welcome Message, close Internet Explorer if required, allow up to 3 deferrals, verify there is enough disk space to complete the install, and persist the prompt.
    # Show-ADTInstallationWelcome -CloseProcesses iexplore -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt

    If ($appCloseApp -notlike $Null)
        {
        # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        # mehrere können nicht per Variablen gelöst werden
        # Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'AcroRd32' }, @{ Name = 'Acrobat' }, @{ Name = 'AcroCEF' }  -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        }


    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress

    ## <Perform Pre-Installation tasks here>
    # ==== Deinstallation der Vorversion - Anzeigename im Add/Remove - DisplayName
    # 64-bit Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
    # 32-bit Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall

    # V3.x Remove-MSIApplications -Name 'PDF-XChange Editor'
    # V4.x Uninstall-ADTApplication -Name 'PDF-XChange Editor' -ApplicationType 'MSI'
    # Uninstall-ADTApplication -Name $MyRemove -ApplicationType 'MSI' 
    # Uninstall-ADTApplication -Name $MyRemove -ApplicationType 'MSI'

	# V4.x oder per ProductCode - Kontrolle ob es vorhanden ist, muss noch eingebaut werden
	# Start-ADTMsiProcess -Action 'Uninstall' -ProductCode '{26923b43-4d38-484f-9b9e-de460746276c}'

    ##================================================
    ## MARK: Install
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI installations.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
        if ($adtSession.DefaultMspFiles)
        {
            $adtSession.DefaultMspFiles | Start-ADTMsiProcess -Action Patch
        }
    }
       
    ##*===============================================
    ##* Log SystemEnvironment
    ##*=============================================== 
    Write-ADTLogEntry -Message "==== Client SystemEnvironment"
    Write-ADTLogEntry -Message "SystemEnvironment c_Domain        : $env:c_Domain"
    Write-ADTLogEntry -Message "SystemEnvironment c_Firma         : $MyFirma"        
    Write-ADTLogEntry -Message "SystemEnvironment c_Nova          : $env:c_Nova"
    Write-ADTLogEntry -Message "SystemEnvironment c_OfficeTemplate: $env:c_OfficeTemplate"
    Write-ADTLogEntry -Message "SystemEnvironment c_ProfitCenter  : $env:c_ProfitCenter"
    Write-ADTLogEntry -Message "SystemEnvironment c_SccmSrv       : $env:c_SccmSrv"
    Write-ADTLogEntry -Message "SystemEnvironment c_Sprache       : $MyLanguage"
    Write-ADTLogEntry -Message "SystemEnvironment c_Tastatur      : $env:c_Tastatur"
    Write-ADTLogEntry -Message "SystemEnvironment c_ThereForeSrv  : $env:c_ThereForeSrv"
    Write-ADTLogEntry -Message "==== Ende Client SystemEnvironment"

    ## <Perform Installation tasks here>

    #region V3 
    <#   
    Write-Log "** Installation"
    Write-Log "** Create MyShowPinTaskFolder"
    New-Folder -Path "$MyShowPinTaskFolder"

    Write-Log "** Copy Script"
    Copy-File -Path "$dirSupportFiles\$MyShowPinTaskScript" -Destination "$MyShowPinTaskFolder\$MyShowPinTaskScript"
    Write-Log "** Active Setup"        

    $MyScript=$MyShowPinTaskFolder+ "\" + $MyShowPinTaskScript
    Write-Log "** Installationspfad:  $MyScript"
    # Active Setup am Schluss ausfĂŒhren
    Set-ActiveSetup -StubExePath 'powershell.exe' -Arguments "-NonInteractive -executionpolicy bypass -file `"$MyScript`"" -Description 'ShowPinTask' -Key 'ShowPinTask' -ContinueOnError $true
    #>
    #endregion 

    Write-ADTLogEntry -Message "Installation"
    Write-ADTLogEntry -Message "** Create MyShowPinTaskFolder: $MyShowPinTaskFolder"
    New-ADTFolder -Path "$MyShowPinTaskFolder"

    Write-ADTLogEntry -Message "** Copy Script"
    Write-ADTLogEntry -Message "Quelle: $($adtSession.DirSupportFiles)\$MyShowPinTaskScript"
    Write-ADTLogEntry -Message "Ziel: $MyShowPinTaskFolder\$MyShowPinTaskScript"
    Copy-ADTFile -Path "$($adtSession.DirSupportFiles)\$MyShowPinTaskScript" -Destination "$MyShowPinTaskFolder\$MyShowPinTaskScript"

    Write-ADTLogEntry -Message "** Active Setup"        
    $MyScript=$MyShowPinTaskFolder+ "\" + $MyShowPinTaskScript
    Write-ADTLogEntry -Message "** Installationspfad:  $MyScript"
    # Active Setup am Schluss ausfĂŒhren
    # V3 Set-ActiveSetup -StubExePath 'powershell.exe' -Arguments "-NonInteractive -executionpolicy bypass -file `"$MyScript`"" -Description 'ShowPinTask1' -Key 'ShowPinTask' -ContinueOnError $true
    ## Set-ADTActiveSetup -StubExePath 'powershell.exe' -Arguments "-NonInteractive -executionpolicy bypass -file `"$MyScript`"" -Description 'ShowPinTask1' -Key 'ShowPinTask'
    
    Set-ADTActiveSetup -StubExePath '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe' -Arguments "-NonInteractive -executionpolicy bypass -file `"$MyScript`"" -Description 'ShowPinTask' -Key 'ShowPinTask' 


    # =========== Aktualisiert Software Cente =========================================
    # Aktualisiert Software Center bzgl. Software
    # V3 Invoke-SCCMTask 'SoftwareUpdatesAgentAssignmentEvaluation'

    Invoke-ADTSCCMTask 'SoftwareUpdatesAgentAssignmentEvaluation'

    
    ##================================================
    ## MARK: Post-Install
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Installation tasks here>

    ##*===============================================
    ##* Log SystemEnvironment
    ##*=============================================== 
    Write-ADTLogEntry -Message "==== Client SystemEnvironment"
    Write-ADTLogEntry -Message "SystemEnvironment c_Domain        : $env:c_Domain"
    Write-ADTLogEntry -Message "SystemEnvironment c_Firma         : $MyFirma"        
    Write-ADTLogEntry -Message "SystemEnvironment c_Nova          : $env:c_Nova"
    Write-ADTLogEntry -Message "SystemEnvironment c_OfficeTemplate: $env:c_OfficeTemplate"
    Write-ADTLogEntry -Message "SystemEnvironment c_ProfitCenter  : $env:c_ProfitCenter"
    Write-ADTLogEntry -Message "SystemEnvironment c_SccmSrv       : $env:c_SccmSrv"
    Write-ADTLogEntry -Message "SystemEnvironment c_Sprache       : $MyLanguage"
    Write-ADTLogEntry -Message "SystemEnvironment c_Tastatur      : $env:c_Tastatur"
    Write-ADTLogEntry -Message "SystemEnvironment c_ThereForeSrv  : $env:c_ThereForeSrv"
    Write-ADTLogEntry -Message "==== Ende Client SystemEnvironment"

	# nur Deutsch
    if ($MyLanguage -like "de-DE"  ) 
        {
        $MyMessage="Bitte ab- und anmelden bevor Sie die Applikation nutzen"
        }

    # nur French
    if ($MyLanguage -like "fr-Fr" ) 
        {
        $MyMessage="Veuillez vous déconnecter et vous connecter avant d'utiliser l'application"
        }


    ## Display a message at the end of the install.
   <# if (!$adtSession.UseDefaultMsi)
    {
        # Show-ADTInstallationPrompt -Message 'You can customize text to appear at the end of an install or remove it completely for unattended installations.' -ButtonRightText 'OK' -Icon Information -NoWait
        Show-ADTInstallationPrompt -Message $MyMessage -ButtonRightText 'OK' -Icon Information -NoWait

    } #>

    # Doppelt, damit Show-ADTInstallationPrompt sicher nie den Wert $Null hat, welcher den Fehler 60001 bringt
    # if ($MyLanguage -notlike "de-DE" -or $MyLanguage -notlike "fr-Fr" ) {$MyMessage="noLanguage"}
    if ($MyLanguage -ne "de-DE" -and $MyLanguage -ne "fr-Fr" ) {$MyMessage="noLanguage"}
 
    # ohne der Abfrage, ob ein User angemeldet ist, gibt es die Fehlermeldung 60001, wenn die Dialoge in einer anderen Sprache kommen
    $MyUser=(Get-ADTRunAsActiveUser).Username
    Write-ADTLogEntry -Message "angemelderter User: $MyUser"
    Write-ADTLogEntry -Message "Sprache: $MyLanguage" 
    Write-ADTLogEntry -Message "$MyMessage" 
    # if ($MyUser) {if (!$adtSession.UseDefaultMsi) {Show-ADTInstallationPrompt -Message $MyMessage -ButtonRightText 'OK' -Icon Information -NoWait} } 
}

function Uninstall-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Uninstall
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

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

    If ($appCloseApp -notlike $Null)
        {
        # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        # Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -CloseProcessesCountdown 60
        # mehrere können nicht per Variablen gelöst werden
        # Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'AcroRd32' }, @{ Name = 'Acrobat' }, @{ Name = 'AcroCEF' }  -CloseProcessesCountdown 60
        }


    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress

    ## <Perform Pre-Uninstallation tasks here>


    ##================================================
    ## MARK: Uninstall
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI uninstallations.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
    }

    ## <Perform Uninstallation tasks here>
    #region V3 
    <#   
    Write-Log '** Remove Active Setup TeamsCleanUp'
    Set-ActiveSetup -Key 'ShowPinTask' -PurgeActiveSetupKey
        
    $MyScript=$MyShowPinTaskFolder+ "\" + $MyShowPinTaskScript
    Remove-File -Path $MyScript
    Remove-Folder -Path "$MyShowPinTaskFolder"
    #>
    #endregion 

    Write-ADTLogEntry -Message '** Remove Active Setup ShowPinTask'
    #V3 Set-ActiveSetup -Key 'ShowPinTask' -PurgeActiveSetupKey
    Set-ADTActiveSetup -Key 'ShowPinTask' -PurgeActiveSetupKey
        
    $MyScript=$MyShowPinTaskFolder+ "\" + $MyShowPinTaskScript
    Remove-ADTFile -Path $MyScript
    Remove-ADTFolder -Path "$MyShowPinTaskFolder"


    ##================================================
    ## MARK: Post-Uninstallation
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Uninstallation tasks here>
}

function Repair-ADTDeployment
{
    ##================================================
    ## MARK: Pre-Repair
    ##================================================
    $adtSession.InstallPhase = "Pre-$($adtSession.DeploymentType)"

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

    If ($appCloseApp -notlike $Null)
        {
        # V3.x Show-InstallationWelcome -CloseApps $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        Show-ADTInstallationWelcome -CloseProcesses $appCloseApp -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        # mehrere können nicht per Variablen gelöst werden
        # Show-ADTInstallationWelcome -CloseProcesses @{ Name = 'AcroRd32' }, @{ Name = 'Acrobat' }, @{ Name = 'AcroCEF' } -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
        }

    ## Show Progress Message (with the default message).
    Show-ADTInstallationProgress

    ## <Perform Pre-Repair tasks here>


    ##================================================
    ## MARK: Repair
    ##================================================
    $adtSession.InstallPhase = $adtSession.DeploymentType

    ## Handle Zero-Config MSI repairs.
    if ($adtSession.UseDefaultMsi)
    {
        $ExecuteDefaultMSISplat = @{ Action = $adtSession.DeploymentType; FilePath = $adtSession.DefaultMsiFile }
        if ($adtSession.DefaultMstFile)
        {
            $ExecuteDefaultMSISplat.Add('Transform', $adtSession.DefaultMstFile)
        }
        Start-ADTMsiProcess @ExecuteDefaultMSISplat
    }

    ## <Perform Repair tasks here>
    # V3 Execute-Process -Path "C:\Windows\System32\MsiExec.exe" -Parameters "/Foums `"$dirFiles\RemoteDesktop_1.2.2924.0_x64.msi`" /QN /L* C:\Logfiles\RemoteDesktop_1.2.2924.0_x64-Repair.log"
    # V3 Execute-MSI -Path EditorV9.x64.msi -Action REPAIR
    # V3 Show-DialogBox -Title 'Repair - HĂ€lg Group IT Helpdesk' -Text "NoRepair" -Buttons 'OK' -Timeout 600 -Icon Information
    Show-ADTDialogBox -Title 'Repair - HĂ€lg Group IT Helpdesk' -Text "NoRepair" -Buttons 'OK' -Icon 'Information' -Timeout 600

    ##================================================
    ## MARK: Post-Repair
    ##================================================
    $adtSession.InstallPhase = "Post-$($adtSession.DeploymentType)"

    ## <Perform Post-Repair tasks here>
}


##================================================
## MARK: Initialization
##================================================

# Set strict error handling across entire operation.
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$ProgressPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
Set-StrictMode -Version 1

# Import the module and instantiate a new session.
try
{
    $moduleName = if ([System.IO.File]::Exists("$PSScriptRoot\PSAppDeployToolkit\PSAppDeployToolkit.psd1"))
    {
        Get-ChildItem -LiteralPath $PSScriptRoot\PSAppDeployToolkit -Recurse -File | Unblock-File -ErrorAction Ignore
        "$PSScriptRoot\PSAppDeployToolkit\PSAppDeployToolkit.psd1"
    }
    else
    {
        'PSAppDeployToolkit'
    }
    Import-Module -FullyQualifiedName @{ ModuleName = $moduleName; Guid = '8c3c366b-8606-4576-9f2d-4051144f7ca2'; ModuleVersion = '4.0.6' } -Force
    try
    {
        $iadtParams = Get-ADTBoundParametersAndDefaultValues -Invocation $MyInvocation
        $adtSession = Open-ADTSession -SessionState $ExecutionContext.SessionState @adtSession @iadtParams -PassThru
    }
    catch
    {
        Remove-Module -Name PSAppDeployToolkit* -Force
        throw
    }
}
catch
{
    $Host.UI.WriteErrorLine((Out-String -InputObject $_ -Width ([System.Int32]::MaxValue)))
    exit 60008
}


##================================================
## MARK: Invocation
##================================================

try
{
    Get-Item -Path $PSScriptRoot\PSAppDeployToolkit.* | & {
        process
        {
            Get-ChildItem -LiteralPath $_.FullName -Recurse -File | Unblock-File -ErrorAction Ignore
            Import-Module -Name $_.FullName -Force
        }
    }
    & "$($adtSession.DeploymentType)-ADTDeployment"
    Close-ADTSession
}
catch
{
    Write-ADTLogEntry -Message ($mainErrorMessage = Resolve-ADTErrorRecord -ErrorRecord $_) -Severity 3
    Show-ADTDialogBox -Text $mainErrorMessage -Icon Stop | Out-Null
    Close-ADTSession -ExitCode 60001
}
finally
{
    Remove-Module -Name PSAppDeployToolkit* -Force
}


Conclusion: Testing Active Setup without MSI Set-ADTActiveSetup works

have fun

Don’t forget, to avoid errors, the source must be local on the client

@Toni & @That-Annoying-Guy , Thanks for the detailed information and breakdown of your observations. This is really helpful.

My Solution:
The easiest way, I found, to get around Active Setup and powershell execution policy as a user: Use Active Setup to call a PSADT package with the config.psd1 configured to run as a user, then call the Invoke-AppDeployToolkit.exe to run the script in silent mode.

Yes: probably overkill for a few regedits but it works.

But I didn’t end up using Active Setup. Instead I had to use the RunOnce key. See Below :backhand_index_pointing_down:

The Long Version:
to give a bit more background I have been PowerShellifying/PSADTing, my OSD task sequence to reduce steps and resources. I have multiple Sub Task Sequences I use to modify the OS on the machine level and user level depending on OS version. I am trying to combine the Sub TS’s into a single PSADT package so I can leverage all of the PSADT features and functions, and have everything in one place
 sort of. It also makes those settings portable to other environments.

For some reason Microsoft has made changing the “Task Bar Search box”, back to a button or getting rid of it all together for Admins very difficult without using GPO. I want our desktops to have the icon by default, using registry edits.

Because of our environment I can’t just use GPO to make these changes across all of our computers. Though I will probably set these in the near future for enforcement on domain computers. I also want users to be able to change it back if they want. So the changes have to be made in the user context.

I also found that Microsoft, after a certain version of WIndows 10, uses the “User Choice Protection Driver” (UCPD) to prevent direct registry modifications to certain user keys and properties.

See: UserChoice Protection Driver – UCPD.sys – the kolbicz blog
and Here: Reddit - The heart of the internet

Disabling UCPD was the fix for a host of other settings changes I make to the Default user profile during OSD. BUT it wasn’t working for the Search box. Upon user creation Windows would take the following registry change I made in the OSD

        $searchBoxPath = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search'
        $sbValueName = 'SearchBoxTaskbarMode'
        $sbValue = '1'
        Set-ADTRegistryKey -Key $searchBoxPath -Name $sbValueName -Value $sbValue -Type DWord

Backup the value I set in ‘SearchBoxTaskbarMode’ to ‘PreviousSearchBoxTaskbarMode’ then change ‘SearchBoxTaskbarMode’ back to a value of 2. :roll_eyes:

Here is what I discovered trying to get around this issue regarding Active Setup and other methods:

Active Setup:
Active Setup seems to run really early in the user profile copy and creation during a user’s first login.
I would make the change using a batch file, or even a PSADT package I copied to the Hard Drive (configured to run as the user). All of these methods I was able to get to run as the user, and I could see from the script logging that the changes were being made. But Windows would change the setting back after the Active Setup ran.

Scheduled Task:
I ran the same resources with a Scheduled Task. It seemed to me, this method was a bit inconsistent. It would sometimes work and other times it wouldn’t, it just depended on when the task kicks off. Plus it’s much more difficult to configure it to kick off only once, for each new user that logs in.

RunOnce (DefaultProfile)
This is the method that worked for me to consistently change the search bar for the user. It seems that RunOnce starts running it’s tasks after the user profile is fully created and logged in. This means that a script ran as the user, can make the change to the above registry key without Windows slapping your hand and telling you NO!

I had a few other settings I needed to perform after the user logged in. I combined them, and the SearchBoxTaskbarMode changes, into a seperate PSADT package (configured so the user can run it). I tossed that package into a .wim file. I placed the .wim into the files directory of the main package. During OSD the main settings package then mounts the wim file and copies the contents to the "$envProgramFiles\PSADT\PostInitalLoginSettings" folder so the RunOnce key can run

$envProgramFiles\PSADT\PostInitalLoginSettings\Invoke-AppDeployToolkit.exe -DeploymentType Install -DeployMode Silent

While PSADT might be a bit “overkill” for writing a few registry keys upon first user login. The logging and completely silent run (via .exe launcher) makes up for it. No windows pop up for the user. The task bar changes to a button, and that’s it.

I am not sure this is ideal. But it satisfies my pragmatism and I can’t argue with the end result.

2 Likes

thanks for the info, many ways lead to rom, it is not an active setup but a way