- 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"
}