Change registry value permission command line or NSIS - windows

I'm trying to grant ordinary users write access to a registry value I created.
They cannot have write access to the parent key.
Through regedit, it's simple:
1. Select value
2. Edit Permissions (change accordingly)
3. OK
However I'm struggling to do the same via command line or NSIS.
The command regini has a very nice method for changing key permissions. If this worked for changing value permissions, I could easily script it into my installer.
The NSIS plugin AccessControl has a very nice method for changing key permissions but no evidence of changing value permissions.
In this case, the key is HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run which I will not modify the permissions of.
How can I change only the permissions of the value I've created? How can I do this just as regedit allows, but silently through command line or NSIS?
The value would be something like:
[HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"My Value"="C:\Please\Let\Me\Change\Permissions\Sadface.exe"
Note, this is for scripted software installer which build script will run on Mac, Linux and Windows (NSIS allows this). Recommendations for bundling special dlls or Windows executable is OK so as long as they're easily bundled and chained against at install time. Solutions including tools such as Windows SDKs cannot be accepted unless the footprint is small and so as long as the DLLs can easily be bundled and included into a LGPL 2.1 project. e.g. installing users will have to run this, so solutions need to be reasonably portable/distributable.

As #Noodles mentions in the comment above, it's not possible to change value permissions, so no solution exists. Registry editor is actually providing the key permissions, which is observable by looking at the Window title, and which is undesired for this particular solution.

Related

After aborting the installer if i try to install again, installer is still pointing to old path

I am trying to install a installer developed using InstallShield 2008. While installing after selecting the destination path i am aborting the installation.
When i try to install again by default it is taking the destination path as previously given path which was provided before aborting the installation.
And also it is not allowing me to install in different path.
For Example:
*Step1 : Installation starts
Step2: Destination path as C:\Installer
Step3: Click next and abort installation
Step4: Start the installation again
Step5: Provide Different destination path as C:\Installer1*
Here installation is failed. Because destination is still pointing to Step2
My question is from where Installer is taking the old path.?
Persisted Path: The technicalities appear to be relatively straightforward: the old path is read back either from the registry or from disk each time the setup is launched, and a custom action in the setup's GUI sequence must have persisted the path "somewhere" during the first run (this is erroneous design, see technical comment below). Reading back the value can be done by using AppSearch (built-in MSI feature) or by means of a custom action.
Registry / Disk: As to finding where the value is read from. The easiest would be to just search the registry first for the literal path. Just open regedit.exe and search for the path there. You can also look for the custom action that does the persisting (or the AppSearch or custom action that does the retrieval) and see if it is a script with code you can see - then you should be able to see where it has persisted the path. Use Orca or a similar tool to view the Custom Action table. The custom action can also be compiled and undecipherable. Do you have the setup source? The path can also be persisted to disk, but the registry is most commonly used. Remember to search both HKCU and HKLM.
Involved Debugging: I can't see why you would, but it is also possible to use ProcMon.exe to monitor what registry locations your MSI reads and / or writes to. This is involved debugging and should never be needed for something this simple. Just mentioning it as a technical option. Generally the last resort we have to figure out the strangest problems.
Technical Comment: MSI setups are not supposed to write anything to the registry or disk from the setup's user interface sequence (setup dialogs). All changes should be made from the installation sequence (InstallExecuteSequence) which also generally runs with elevated rights - the user interface normally runs with user rights. This InstallExecuteSequence sequence is kicked off from the last dialog in the GUI sequence, and runs the file copy and system change operations. Control then returns to the GUI sequence to show the setup complete dialogs. It is also possible to run the setup silently, in which case the InstallUISequence never runs and all custom actions inserted there fail to run. Accordingly custom actions should be present in the InstallExecuteSequence as well as the InstallUISequence if they are to run in silent mode. This potential design flaw is a very common silent deployment error which occurs when setups are not designed properly for silent running. Remember that all corporate deployment runs silently. Setup GUI is highly overrated (in my opinion - a "fact" that could change in the future).
It is still possible for an MSI setup to write to the registry or disk from the InstallUISequence by using a custom action to do so. Such a custom action would normally not have access to write to HKLM or to protected parts of the disk - unless the whole setup runs elevated because it was launched from an elevated command prompt (for example), or launched by an admin who elevates it via the UAC prompt.
In other words: this setup is badly designed, but I guess that is clear already.

Windows installer is too clever, tries to repair when tester deletes config file

Our application is deployed to the target machine with an msi file. All works nicely. Our tester has gone through his plan, and one of the tests requires deleting the application's configuration file. The application is designed to alert the user with a dialog on startup saying "missing config". However, what happens is that - somehow! - the software starts the installer again and retrieves the missing file from the msi! Which is nice, but not what we want. How do we disable that behaviour?
without going into much depth of the windows installer mechanics (if you interested in that there a plenty of articles about this), the shortcut of the software is probably advertised, which means the windows installer checks if everything is in its place before the software is started.
if you can edit the msi, make the shortcut non advertised.
if you can't, install it with DISABLEADVTSHORTCUTS
e.g. msiexec /i myMsi.msi DISABLEADVTSHORTCUTS=1
please note that this is only a quick (and dirty) workaround,
to fix this proper you need to understand the whole windows installer advertising (also called repair or self resiliency) mechanism.
but explaining all the causes and the mechanism of the repair is far beyond this answer and there are quite some articles and posts about that on the internet (and especially on MSDN and stackoverflow)
There is a more correct answer to this, and it is NOT DISABLEADVTSHORTCUTS. You set the component id to null in the MSI file to prevent repair of that individual file. See ComponentId comments here:
http://msdn.microsoft.com/en-us/library/aa368007(v=vs.85).aspx
Edit the MSI file with Orca to delete the Componenty ID, and write an uninstall custom action to delete the file at uninstall if it's there.
In addition, that's a redundant test. Windows will restore that file for you if it's missing, so the idea that you need a test to notify that it's missing is pointless. The true test should be that Windows will restore the file if it's lost, and your app needs to do potentially nothing about the missing file.
You don't mention what tool you are using to make your MSI but I'm going to go out on a limb and guess Visual Studio Deployment Projects (.VDRPOJ).
One of the (many) horrible things about this tool was that it fails to expose the foundational concept of components. Instead it makes every file a key file of it's own component and hides the existence of the component from you. I say 'was' because Microsoft killed this project type in VS. There are around 50k people complaining on UserVoice to bring this tool back and I'm guessing that 49,990 of them don't know what a key path is.
Windows Installer has a concept called the component rules and each component has a keypath. The keypath teaches MSI how to handle repair scenarios. But your tool has to allow you to be able to control this to make it work.
Windows Installer is functioning exactly the way it's supposed to function. You just aren't up to speed on what that is.
However, if you want to ignore Windows Installer best practices and continue using the tool you use today, the trick is to install the app.config file as a different file. Then have the application copy the file to the real file name on run. Windows Installer won't service what it didn't install.
Several answers have been provided that can work:
You can install the file with a blank guid. Then you need to remove it on uninstall using the RemoveFile feature. You will also run into issues if you want to replace it during an upgrade. Could be tricky at times.
You can disable the advertised shortcut(s), but this affects too much in my opinion.
Finally you can use my suggestion to install a separate non-advertised shortcut to use to launch the application. Such a shortcut bypasses the self-repair check. It may still be invoked by other means such as missing file associations, COM registration or similar, but those are exception states.
However, my preference is that an application can start without a config file present, if at all possible. I always suggest a good startup routine with "internal defaults" available. The startup routine should also degrade gracefully if faced with any file system access denied conditions.
Most importantly you should place this config file in the userprofile so you can generate the file on first launch for the user in question. It can even be copied from a read-only copy in the main installation directory.
When you generate a file from internal defaults and put it in a userprofile location, the file will have no interference with Windows Installer at all. The issues that results is how to clean up user data on uninstall. I discussed this with Stefan Kruger (MSI MVP) at one point, and I agree with his notion that user data is indeed user data and should not be automatically dealt with by your installer at all. Leave it installed, and clean it up via system administrator tools if necessary - for example logon scripts.

VS2010 Deployment Project: Issues with multi-user-install and registry entry

I have issues setting up my deployment project in Visual Studio 2010. Im using Windows 7 x64. Here's my problem:
The setup is supposed to install my program for all users. During the setup three registry keys are written to the HKEY_LOCAL_MACHINE/Software/Something folder, containing the setup variables for Serial, Name and Organization as values - [COMPANYNAME], [PIDKEY], [USERNAME].
What happens:
User1 (Admin) installs the software, entering his username, serial and company. Everything works. The keys can be found and values read by the program, using Registry.LocalMachine.OpenSubKey(path). The first thing I don't get is that I cannot find the registry entries, using the regedit.exe. Anyway, the code above finds them.
Now, User2 (Non-admin) tries to execute the freshly installed program. The installer is launched again, saying "Wait for ... to configure ...". The user specific folders for User2 are created correctly. The program is started, but the registry keys cannot be found by the program anymore.
Now, finally, User1 tries opening the program again. (The registry entries cannot be found anymore.) Edit: The registry entries are actually there, but its values are empty.
So, my questions:
Why can't I see the registry entries with regedit after the install, although they are obviously there?
(2. Why are the registry entries deleted, when the second user tries launching the program for the first time and how can I avoid that?)
Edit:
2. Why are the registry values set to empty strings, when the second user tries launching the program for the first time and how can I avoid that?
Cheers from Auckland and thanks!
Marc
You might be missing the registry entries if you have a 32 bit package installed on a x64 machine. In this case the registry entries would be redirected under "HKLM\Wow6432Node...". This is the standard behavior for x64 Windows machines. The same happens with the file redirection to Program Files and Program Files(x86).
That is strange. It could happen that the second launch of the installer, a normal automatic repair operation, has removed the registry entries by mistake. To get more details about the actions executed during the second launch I recommend you enable permanent logging on the OS.
http://support.microsoft.com/kb/223300
Wonder why the Find-function didn't find the keys though?
Probably the API used is considering the keys do not exist if all the values are empty. You should check its docs.
Obviously the "second installer" performs the entry again, without having values for that. Do you have an idea how to solve that?
This usually happens if the registry are written with values from public properties. During the automatic repair the properties don't have their initial install values so they are considered to contain an empty string, which is than used to replace the registry values.
The only solution you have is to make a small custom action that runs during repair, as immediate, which searches the registry entries before they get overwritten and places their values in the properties your are using. This way the overwrite operation will use the correct values.

Are dirs in C:\Users\Public\Documents writable to everyone by default?

I want my installer to create a folder in C:\Users\Public\Documents that will be readable and writable to all local users. This includes the right to create files/dirs there, and to modify and delete all existing ones. The installer is being ran as Administrator.
I don't have to programatically set the permissions for my dir, right? Just by creating the dir, it will have the correct permissions I think.
I'm interested in the behavior under XP, Vista and 7.
Note: I'm not hardcoding the path C:\Users\Public\Documents, I'm querying CSIDL_COMMON_DOCUMENTS from the Win API, which can return different values depending on machine and OS. For example on XP it returns a different path.
Edit: here's a relevant discussion. It points to MS docs about the question, but it also looks like those docs may be wrong.
Yes, it inherits rights from the parent folder. Which has write permission for anybody in the INTERACTIVE group. Which includes any logged-in user account.
Use the Security tab in the shell's Properties dialog to review these settings.

Install files to original user's My Docs folder via Inno Setup on Windows Vista/7

In the [Run] section of an Inno Setup script, there's a flag runasoriginaluser that allows the script to run a process as the original user:
the spawned process will execute with
the (normally non-elevated)
credentials of the user that started
Setup initially (i.e., the "pre-UAC
dialog" credentials).
Is there an equivalent flag or workaround for the {userdocs} shell folder constant?
This is apparently a known limitation within Inno Setup (and other installers, generally), but I'm hoping someone knows a workaround.
Excerpt from the Inno Setup help file:
The "user" constants refer to the
profile of the user running Setup.
This user is often not the same as the
currently logged-in user, so use the
"user" constants with caution.
The workaround I came up with was using an external script to perform the data copy and calling the script using the ExecAsOriginalUser function in the wpReady page of the NextButtonClick event function.
I'll provide more details if anyone is interested.
Your approach is not correct.
There two correct ways:
If the installer installs the application for the current (unprivileged) user only, do not require Administrator privileges, by setting PrivilegesRequired to lowest:
[Setup]
PrivilegesRequired=lowest
Then the "user" constants will correctly refer to the current user's folder.
If the installer installs the application for all users, it does not make sense to put some files to folder of one specific users. All users need the files, not just the one. In this case the recommended approach is to install the files to "Common" folder, using the {commonappdata} constant (or similar). And have the application copy the files to the user folder on the first run.
See also How to write to the user's My Documents directory with installer when the user used 'Run As Administrator'.
You can also allow the user choose between these two approaches.
See Make Inno Setup installer request privileges elevation only when needed.
For another similar questions, see
Inno Setup Using {localappdata} for logged in user
Inno Setup always installs into admin's AppData directory
Having that said, you can, as you have found yourself, by execute an external copy utility (copy, xcopy, robocopy) using the ExecAsOriginalUser function (or the runasoriginaluser flag in the [Run] section).
ExecAsOriginalUser(
'cmd.exe', '/c xcopy.exe "sourcefile" "%APPDATA%"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
For more detail on this approach, see a similar question Inno Setup Creating registry key for logged in user (not admin user).
Though, if the installer was started elevated straight away (as opposite to elevating itself), the above won't work. And it cannot work in this scenario anyway. See How to write to the user's My Documents directory with installer when the user used 'Run As Administrator'. For this reason, stick with the approaches described above.

Resources