Quantcast
Channel: psappdeploytoolkit Discussions Rss Feed
Viewing all articles
Browse latest Browse all 1769

New Post: Set-ActiveSetup and Remove-ActiveSetup: Per-user changes (as requested)

$
0
0
  • Added -Arguments parameter
  • $ActiveSetupPath renamed to $StubExePath
  • The function to make -Purge work is still not done and I have no time to finish it for now. Using -Purge will give you an error
Function Set-ActiveSetup {
<#
.SYNOPSIS
    Creates an Active Setup entry in the registry and copies the StubPath file if needed.
    
.DESCRIPTION
    Version: 0.6 - Author: CodePlex's That_annoying_guy - 2014 Sept 05 - BETA USE AT YOUR OWN RISK!!
    
    Active Setup is a built-in feature of Windows to handle per-user changes
    A registry key is created in HKLM and *as users login*, the user runs the "Stub" in the StubPath value and copies the Version value to HKCU in a matching Key
    If the Version value in HKLM is higher than the version value in HKCU, the StubPath is ran again when a user logs in.   
    This Function:
    -Creates the registry entries in HKLM:\Software\Microsoft\Active Setup\Installed Components\$installName
    -Creates StubPath value depending on the file extension of the $StubExePath parameter
    -Handles Version value with YYYYMMDDHHMMSS granularity to permit re-installs 
    in the same day and still trigger Active Setup as users logon.
    -Copies the Stub file to $StubExePath is not already there and if it's in $scriptDirectory
    -Runs the Stub for the user that is installing (no need to logout/login to trigger Active Setup)

.LINK
    http://www.sepago.de/d/helge/2010/04/22/active-setup-explained  
    
.SYNTAX
    Set-ActiveSetup -StubExePath <PathToStub> [-Arguments "MyArgs"][-Description "MyDesc"][-Key "KeyName"][-Locale "en"][-IsInstalled $false]
    
.EXAMPLE
    Set-ActiveSetup -StubExePath $PathToMyActiveSetup -Arguments "MyArgs" -Description "MyDesc" -Key "KeyName" -Locale "en" -IsInstalled $false
    Set-ActiveSetup "$PKGUNINSTALLDIR\MyApp_v1r1_HKCU.exe"
    Set-ActiveSetup "$PKGUNINSTALLDIR\MyApp_v1r1_HKCU.VBS"
    Set-ActiveSetup "$PKGUNINSTALLDIR\MyApp_v1r1_HKCU.CMD"
    Set-ActiveSetup "$PKGUNINSTALLDIR\MyApp_v1r1_HKCU.PS1"
    Set-ActiveSetup "C:\Program Files\MyApp\MyApp_v1r1_HKCU.JS"

.BAD_EXAMPLE
    Set-ActiveSetup "MyApp_v1r1_HKCU.exe" 
    This will not work. We need a full path to where it is or will go!
    
.PARAMETER -StubExePath
    -Full path to the EXE/VBS/CMD/PS1/JS that will be launched for each new and existing user profile.
    -This will be used as path of the StubPath value in Active Setup in HKLM
    -If the file does not exists at $StubExePath, it is copied from $scriptDirectory
    -Note: -StubExePath and -Arguments are combined in the StubPath value

.PARAMETER -Arguments
    -Optional Arguments to send to the EXE/VBS/CMD/PS1/JS file above 
    -Note: -StubExePath and -Arguments are combined in the StubPath value

.PARAMETER -Description
    -Optional Description for the Active Setup. 
    -Users will see "Setting up personalised settings for: $Description" at logon
    -Defaults to $installName if blank

.PARAMETER -Key
    -Optional Name of registry Key name used for the Active Setup.
    -Defaults to $installName if blank
    
.PARAMETER -Locale
    -Optional. Arbitrary string used to specify the installation language of the stub
    -Not replicated to HKCU. Only used for identification purposes inn HKLM. Ignored if omitted.
    
.PARAMETER -Purge
    -Will load each HKCU hive (.Dat file) to remove Active setup key.
    -For those who love overkill.
    
.NOTES
    Your ActiveSetupStub file can be copied to $StubExePath via the MSI or other means. In which case it is only stubbed in HKLM
    If ActiveSetupStub file is in the pkg container and not in $StubExePath, it is copied to $StubExePath and stubbed in HKLM.

    TBD: [bool]$global:ACTIVESETUP_DISABLE can be used to prevent the Active Setup from being created (Needed?)
    TODO: Add 32/64Bit support. (Current version is 64-bit only but I've been told this is important)

    Publishing CAVEATS: 
    $PKGUNINSTALLDIR is used in Author's modified version of the ToolKit. This feature is not in Original TK
    
    How to add to AppDeployToolKit (Too Lazy; Don't Read version):
    Edit \AppDeployToolkit\AppDeployToolkitExtensions.ps1 to add theses functions
    
    Add this line in 
        
.COMPONENT
    Depends on TK's Copy-File, Execute-Process and Write-Log functions
    
#>
    Param(
        [Parameter(Mandatory = $true)]
        [string]$StubExePath = $(throw "StubExePath Param required"),
        [string]$Arguments,
        [string]$Description=$installName,
        [string]$Key=$installName,
        [string]$Locale,
        [bool]$IsInstalled
    )

    # CAVEAT: Version value is limited in # of digits and cannot do yyyyMMddHHmmss
    # Currently, it is known that 8 consecutive digits is one limit. (yyMMddHHmm)
    # Extra digits above 8 are ignored and will not trigger Active Setup
    # We are using commas to get more digits and it still triggers Active Setup
    [String]$Version=Get-Date -format "yyMM,ddHH,mmss"  #1405,1515,0522
    [String]$ActiveSetupKey="HKLM:\Software\Microsoft\Active Setup\Installed Components\$Key"
    [String]$ActiveSetupKey4Reg="HKLM\Software\Microsoft\Active Setup\Installed Components\$Key"
    [String]$HKCU_ACTIVESETUPKEY="HKCU:\Software\Microsoft\Active Setup\Installed Components\$Key"

    #CAVEAT: Deprecated feature (Deprecated = May disappear in a future version)
    IF ($global:ACTIVESETUP_DISABLE) { 
        Write-Log "WARNING: ActiveSetup is disabled for this package. Exiting Set-ActiveSetup() function..."
        return
    }

    #Copy file to StubExePath if needed
    #Your Stub file can be copied to $StubExePath via the MSI or other means. In which case it is only stubbed in HKLM
    #If the Stub file is in the pkg container and not in $StubExePath, it is copied to $StubExePath and stubbed in HKLM.
    [string]$StubExePath=[Environment]::ExpandEnvironmentVariables($StubExePath) # to handle %EnvVars%
    [string]$ActiveSetupFileName=[System.IO.Path]::GetFileName($StubExePath) #FYI: .Net does not care if $StubExePath exists
    If (Test-Path "$scriptDirectory\$ActiveSetupFileName") {
        #CAVEAT: This will overwrite the Stub file if $StubExePath already exists on target
        Copy-File -Path "$scriptDirectory\$ActiveSetupFileName" -Destination "$StubExePath" -ContinueOnError $false
    }   
    
    If (!(Test-Path $StubExePath)) { Throw "ERROR: ActiveSetup Stub file [$($ActiveSetupFileName)] is missing." }
    
    If ($Purge) {
        Write-Log "Removing old $ActiveSetupKey on all other User hives on machine..."
        #Cleans out previous ActiveSetup Key in each user profile (for overkill lovers)
        Remove-RegistryKeyFromAllHives $ActiveSetupKey
    }
    
    #set $StubPath according to file Extension of $StubExePath
    If       ($StubExePath.Substring($StubExePath.Length-3,3) -eq "exe") {
        $StubPath="$StubExePath $Arguments"
    } ElseIf ($StubExePath.Substring($StubExePath.Length-3,3) -eq "vbs") { 
        $StubPath="$envWinDir\System32\wscript.exe //nologo `"$StubExePath`" $Arguments"
    } ElseIf ($StubExePath.Substring($StubExePath.Length-3,3) -eq "cmd") { 
        $StubPath="$envWinDir\System32\CMD.exe /C `"$StubExePath`" $Arguments"
    } ElseIf ($StubExePath.Substring($StubExePath.Length-3,3) -eq "ps1") { 
        $StubPath="$envWinDir\System32\WindowsPowerShell\v1.0\powershell.exe `"$StubExePath`" $Arguments"
    } ElseIf ($StubExePath.Substring($StubExePath.Length-3,3) -eq ".js") { 
        $StubPath="$envWinDir\System32\wscript.exe //nologo `"$StubExePath`" $Arguments"
    } Else { Throw "Unsupported ActiveSetup Stub file" }


    #TBD: use TK's Set-RegistryKey when things work, but might be overkill
    if (!(Test-Path $ActiveSetupKey)) {md $ActiveSetupKey -force} #force =create multiple levels at a time
    Write-Log "ActiveSetup StubPath     =$StubPath"
    set-itemproperty -path $ActiveSetupKey -name Stubpath -value $StubPath -force #Force=overwrite
    Write-Log "ActiveSetup Version      =$Version"
    set-itemproperty -path $ActiveSetupKey -name Version -value $Version -force #Force=overwrite
    Write-Log "ActiveSetup Description  =$Description"
    set-itemproperty -path $ActiveSetupKey -name '(Default)' -value $Description -force
    If ($Locale) { 
        Write-Log "ActiveSetup $Locale  =$Locale"
        set-itemproperty -path $ActiveSetupKey -name Locale -value $Locale -force }
    If (!($IsInstalled)) { 
        Write-Log "ActiveSetup $IsInstallede  =$IsInstalled"
        set-itemproperty -path $ActiveSetupKey -name IsInstalled -value $IsInstalled -force }
    #"%BITS6432DIR%\REG.EXE" DELETE "%HKCU_ACTIVESETUPKEY%" /v Version /f 1>nul 2>nul


    Write-Log "Exporting just-created Active Setup Key..."
    Execute-Process -FilePath "$envWinDir\System32\Reg.exe" -Arguments "EXPORT `"$ActiveSetupKey4Reg`" `"$envTemp\${installName}_ActiveSetup_KEY.log`" /y" -WindowStyle Minimized
    If (Test-Path "$envTemp\${installName}_ActiveSetup_KEY.log") {
        Type "$envTemp\${installName}_ActiveSetup_KEY.log" | Write-Log
        Del "$envTemp\${installName}_ActiveSetup_KEY.log" -Force -ErrorAction SilentlyContinue
        Write-Log "Export of key complete"
    }


    #CAVEAT: This "$RunningAsSystem" chunk is highly likely to be moved to another function
    $SIDCollection="LocalServiceSid","LocalSid","NetworkServiceSid","NetworkSid","NTAuthoritySid","LocalSystemSid"
    [bool]$RunningAsSystem=$false
    foreach ($Sid in $SIDCollection) {
        If ([System.Security.Principal.WindowsIdentity]::GetCurrent().User.IsWellKnown(
            [System.Security.Principal.WellKnownSidType]::$Sid)) {$RunningAsSystem=$true}
    }


    #Run ActiveSetup for Current User that is installing (This includes Citrix) but not SMS/SCCM
    If ($RunningAsSystem) { 
        Write-Log "INFO: System Account detected: Not Running ActiveSetup Stub for Current User."
    } Else {
        Write-Log "Launching StubPath for Current User..." # And test StubPath
        #&$StubPath #The term 'C:\Windows\System32\wscript.exe //nologo "c:\TEMP\MyApp_v1r1_HKCU.vbs"' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. ()
        #Execute-Process -FilePath $StubPath #NG b/c we need to separate out the arguments.
        Invoke-Item $StubPath   #Not what I wanted but it works
    } 
    Write-Log "Set-ActiveSetup done.`n"
}


Viewing all articles
Browse latest Browse all 1769

Latest Images

Trending Articles



Latest Images