Feature Request: User settings function


Sometimes you need to change user settings when deploying packages and it would be nice to have a function for this. The dream scenario would be if the function could handle these things.
  • Add HKCU registry keys for users.
  • Copy custom files/scripts to a folder on the client and then run this from the users context.
  • Run the above file/script for the current logged in user.
The first two things is possible with scripts and Active Setup but the last one is a bit more complex which I'm not sure how to solve. I have seen other Client Management systems handle this but I don't know if it's possible with scripting only. If it isn't possible then the two first things would be nice anyway.

file attachments

Closed Apr 14, 2015 at 1:05 PM by mmashwani
We have moved to a new homepage! You can now find us as http://psappdeploytoolkit.com.

We have also moved to a new repository on GitHub and this request has been migrated there. Please post all new relevant details on the issue listed on GitHub.


That_annoying_guy wrote Aug 28, 2014 at 3:37 PM

Hi HampusN,

I am not one of the 2 developers but where I work, we do plan to use the toolkit once we have modified and augmented it heavily. We currently have 2 CMD wrappers and we want to replace them with this PowerShell wrapper.

One of the features we need to build is exactly what you want and more. I think one of our CMD wrappers can do "per-user" stuff by just dropping in a CMD/VBS/PS1/EXE in a sub-folder of the package and the wrapper will create the Active-setup for it on its own. Either-way that is the plan for us.

Our ETA for this function is about 3 to 6 months since the modifications are only done by me when I have time until it reaches critical mass. I would be bringing-in this function to the project as an extension. You can then using it your own AppDeployToolkitExtensions.ps1. It's up to the 2 developers if then want to bring it in proper or not.

BTW: Active Setup runs "the above file/script for the current logged in user", not as system.
Bonus Info: MS tried to kill Active Setup but MSI has problems using its own Per-User stuff for copying files the the user's profile. Using Active-Setup is way less resource intensive than forcing a /FU on the MSI.

HampusN wrote Aug 28, 2014 at 4:53 PM

Srry if I wasn't clear with my 3rd point. I mean Active Setup keys doesn't run for the currently logged in user until he logs off and then on again. It's not very practical to tell the users they need to log off then on again for their application to work.

I like your idea with a dropfolder which the script reads from but I'm not sure it's totally necesessary. A function where you specify the script/file should be as simple. Maybe you would have to create two different function. One which adds HKCU keys. And one where you specify a script or file. This function needs to do one extra step where it copys the file to a local folder and then run it from this folder.

That_annoying_guy wrote Aug 28, 2014 at 5:39 PM

In our wrappers we do run the Active Setup for the profile of the installer on the spot.
We also know that's a bad idea if the Installer is System/SCCM because it just pollutes the profile for nothing.

Actually we have create a few:
  • One to generate Version stamps based on date and time (needed for re-installs to re-trigger Active setups)
  • One to check the folder and create the ActiveSetup in the HKLM hive.
  • One to remove the Active-setup in the HKLM hive for uninstalls.
As for the file copy, we have something for that already which makes it moot. We create custom ARP entries for each packages so that we get uninstall logs for everything. To do that we copy all the files needed to an UNINSTALL folder. In that UNINSTALL folder is where we store the files triggered by ActiveSetup.

Like I said, we have a lot of work ahead: Rolling logs, Pre/Post inventory, sanity checks, custom ARP entries with parent-child support, etc. Most of it is overkill but it's what we have in the CMD wrappers so to get buy-in we need to re-create it all in PowerShell. And I'll release what I can as extensions to this project.

mmashwani wrote Aug 29, 2014 at 3:16 PM

I have a VBScript which does all of what you are describing above. I've been meaning to convert this to PowerShell code for a while now and probably will do so in the next two to three weeks and share it with the community here. In the mean time, here is the VBScript for you viewing pleasure or if you want to take a crack at converting to PowerShell yourself.

pjgeutjens wrote Sep 2, 2014 at 8:12 AM

Can I play devil's advocate and indicate 2 things?

1) MSI does not really have problems copying files to user folders on self-heal as long as either the original install source is available (ok, that can be a problem), or DuplicateFile table gets used correctly and the relevant files are placed in a machine-reachable location

2) essentially setting up an ActiveSetup consists of 3 regkeys in HKLM, so is a specific function needed? And if it would be, would something like

Set-ActiveSetup -Key -StubPath -Version -Description

With appropriate default values do the trick?

3) might not need to make this point here, but the real problem with ActiveSetup i.m.o is the fact there is zero error handling or even error logging/retry capability available out of the box.

HampusN wrote Sep 2, 2014 at 9:45 AM

That is true about MSI. But many things can be done with a MSI package, why even use a powershell wrapper then if you just repackage everything?

I think it makes sense to have two different functions with active setup.
  1. Run a custom script/app. It would be nice to have two functions, one which set and one which deletes. In the background it needs to do this tasks.
    You need to copy the script/app to a local folder which the user have permission to read from.
    You need to set registry keys in Active Setup to run the script from that path.
    You need to remove the key and script/app with the uninstallation script.
  2. Add HKCU values
    It could look something like the normal Set-RegistryKey function but the only difference is that in the background it instead of creating a HKLM value it creates the Active Setup key which add the registry value to the users HKCU.
And yeah, I try to avoid Active Setup as much as possible but sometimes it's just needed. The only problem I know of is that Active Setup won't run until the user log off then on again.

That_annoying_guy wrote Sep 2, 2014 at 2:50 PM

Hi HampusN,

I have a Beta-quality function for you that is almost done. It will do what I proposed minus the "drop-folder" idea. it should trigger for the user profile installing the package. It even copies the file for the StubPath to its final location, if needed.

Currently you can call it like this:
    Set-ActiveSetup -ActiveSetupPath $PathToMyActiveSetup
    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 "$PKGUNINSTALLDIR\MyApp_v1r1_HKCU.JS"
I could add an optional -Description parameter since pjgeutjens mentioned it.
The function I have coded handles the Version automatically.

I hope to post it here today or tomorrow, time permitting. But it's not fully tested as in with a real application. Names of variables might change as well.
CAVEAT: I wrote the function for my modified version of the toolkit. I will make modifications so that it can work in the regular UN-modified version of the toolkit. That way I have one version of the function to support.

HampusN wrote Sep 2, 2014 at 7:16 PM

That is really great! I think the description is nice cause if you set the key to a guid you wont know what it does.

Do you know if it's possible to run this somehow for already logged on users?

That_annoying_guy wrote Sep 2, 2014 at 7:33 PM

The Active Setup key it creates would not have a GUID.
It would be $InstallName instead.
IOW: [HKLM:\Software\Microsoft\Active Setup\Installed Components\$InstallName ]

If by "already logged on users" you mean the guy/account that is installing, yes.
If you mean on a Citrix-box with users already logged-in, no. They would have to logout/login.

pjgeutjens wrote Sep 2, 2014 at 7:44 PM

hey guys,

great effort so far. I'd like to clarify the proposed parameters from my previous post, since I think the use of the Description parameter is not 100% clear

-Key : the name of the registry key under Installed Components, so that would be to override the value of $installName that you used

-StubPath: the command to execute, guess this is obvious, -ActiveSetupPath would be fine too

-Version: I guess it's not needed, unless maybe for override purposes?

-Description: this would determine the value of (Default) for the registry key, since that contains the text you see in the "Setting up personalised settings for:" dialog at logon

There are other possible values (isInstalled and Locale), but I'm not sure they need to be included in the function

That_annoying_guy wrote Sep 2, 2014 at 8:37 PM

Thank you pjgeutjens,
  • I'll add -Key. No prob.
  • -Version is not needed because Version is a time stamp. You are guaranteed to fire AS even if you uninstall and re-install under a minute!
  • -Description is now added but I'll steal some of your blurb there if you don't mind...
  • RE: -StubPath vs -ActiveSetupPath.
    I use $ASStubPath in the function as the value for StubPath before it goes into the registry. (wscript.exe //nologo "c:\temp\myScript.vbs")
    I use $ActiveSetupPath to point to where the StubPath file is. ("c:\temp\myScript.vbs")
  • If you want me to include -Locale, tell me what Active Setup does with it (how it works) and I'll add it. I've seen it in the AS keys but it always looked useless to me.
  • I cannot see why you'd need -isInstalled. The Version value would just get bumped and fire again.

pjgeutjens wrote Sep 2, 2014 at 9:23 PM


Be aware though the version value has specific format requirements for it to work
Best overview I found is this page: http://www.sepago.de/e/helge/2010/04/22/active-setup-explained

That_annoying_guy wrote Sep 2, 2014 at 11:59 PM

Set-ActiveSetup and Remove-ActiveSetup Functions posted as Extension:

Discussions -> Toolkit Extensions

look for:
Set-ActiveSetup and Remove-ActiveSetup: Per-user changes (as requested) Part2
Set-ActiveSetup and Remove-ActiveSetup: Per-user changes (as requested)

@mmashwani: I plan to use your hive loading idea to clean-out Active Setups out of ALL user .DAT files in a future version. If that's OK with you.

mmashwani wrote Sep 3, 2014 at 1:17 AM

Absolutely, go for it.

sintaxasn wrote Nov 4, 2014 at 2:07 AM

For now, we've implemented the ability to modify the HKCU of all users on a machine. We do however, have this on the radar to be more functional for performing Per User tasks when installing as SYSTEM from SCCM.

That_annoying_guy wrote Nov 4, 2014 at 4:07 PM

Hi sintaxasn,

I hate to burst your bubble on your new Set-HKCURegistrySettingsForAllUsers function but it won't work for users that do not exist yet or Citrix Users that are not logged on.

The only advantage Set-HKCURegistrySettingsForAllUsers has over Active Setup is only if nobody ever logs out or reboots and the changes are registry settings only. Some per-user changes cannot be done on the user's behalf (e.g. shortcut pinning, verbs, custom scripts). And in Citrix, if the changes include files in the profiles, the other users' profiles won't be there to be updated. (advantage Active Setup)

The samples I gave in "Discussions under Toolkit Extensions"
tries to trigger the Active Setup "Payload" (aka "stub") for the user installing it so that the changes take effect for them without needing to log off and log back on. (and does NOT if the installer is SCCM or system)

I would be pleased if you guys stole ideas from them or the entire thing.

Come to think of it; are you guys planning to do some kind of combo between Active Setup and your "force-feeding user hives" idea in the future or offering both solutions?

PS: Thank you on 3.5's new "Refresh-Desktop" and "Refresh-SessionEnvironmentVariables" Functions. I've been wanting to do the Environment Variables refresh idea for years!

sintaxasn wrote Nov 4, 2014 at 4:58 PM

Yup, that's why I said it's only partially addressed and I haven't closed the ticket ;)

We're exploring a number of options with regard to tackling items in the current users context - for users that haven't been created, activesetup remains the best way of doing it.

Stay tuned...

mmashwani wrote Nov 4, 2014 at 5:10 PM

Set-HKCURegistrySettingsForAllUsers will actually work for users that do not exist yet because it modifies the default registry hive. When new users are created, their registry is provisioned from the default registry hive. So for strictly registry based edits, I prefer this method over Active Setup.

mmashwani wrote Nov 4, 2014 at 5:19 PM

For files in the User profile folder, new users get their profile files provisioned from the default profile folder under C:\Users\Default. So if it is a a case of simply adding or deleting a file, you can modify all profiles and then modify the default profile to take care of new users. Anything more complicated than simple addition/deleting of files will of course not work for new users.

mmashwani wrote Nov 4, 2014 at 5:38 PM

Also, not sure what you meant by "Citrix Users that are not logged on." Not too familiar with Citrix, so if something novel happens with Citrix users, I'd be interested to know. Otherwise, Set-HKCURegistrySettingsForAllUsers will modify registry settings for users that are not logged on as long as they have a profile on the system with their registry hive file present.

That_annoying_guy wrote Nov 4, 2014 at 6:13 PM

Modifying the Default profile is polluting the Default profile. I did that years ago and I got into trouble.
I also do not see a Remove-HKCURegistrySettingsForAllUsers unless it's one and the same.

As long as we have multiple methods and one is Active Setup, I'll be happy.

That_annoying_guy wrote Nov 4, 2014 at 6:26 PM

About Citrix:
Our setup has a separate Profile Server (or share). The profiles are copied to the Citrix server only just before the user logs on.

When the user logs off, his profile is copied back to the Profile Server (or share) and the profile is deleted from the Citrix server.

mmashwani wrote Nov 4, 2014 at 7:08 PM

The function can do any registry manipulation as it executes a script block you pass to it.

That_annoying_guy wrote Nov 6, 2014 at 11:14 PM

In case you might need it, I've updated the functions I posted in "Discussions under Toolkit Extensions"

Version: 0.7 - Now uses ToolKit's functions throughout, has better comments, code and consistency. Solved issue to trigger changes for current user.