Description
One driver left a mess in the registry (even when I uninstalled it from the system). If I check the security setting it will not display anything in “Group or user names”. And when I check the owner it shows only “Unable to display current owner.”. When I want to delete the registry keys I have to:
Take the ownership.
Add group.
Delete the key.
The problem is that each registry has several sub keys and I have to repeat the process on each key. Inherit permission option will not work in Registry Editor. And yes, I am running Registry Editor in administrator mode.
Problem
I wanted to write a simple C# code that would loop and delete all keys. I have found some code samples, but in my case any OpenSubKey call would fail with error:
System.Security.SecurityException: Requested registry access is not allowed.
How can I change the ownership if any call of OpenSubKey function would fail? Is there any other command where I can claim the ownership and then delete the registry key?
Thank you for the support
Just as you knew to run the Registry Editor as an administrator in order to ensure that you would have the appropriate privileges to modify/delete registry keys, you need to do the same thing for your C# application.
Because you forgot to do this, the System.Security.SecurityException is being thrown as a reminder. As the exception message says, you do not have the privileges to modify/delete the registry key(s).
To solve the problem, you must execute your C# application with administrative privileges. You can either do this manually, or add a manifest to your application that will cause it to automatically demand administrative privileges.
This is half an answer.
This knowledge base article explains how to take ownership of a key that you don't have access to.
In short, you need to enable the "Take Ownership" privilege and open the key with WRITE_OWNER access. You can then set the owner.
Note that this only works when you run your code as an Administrator.
However, I don't know if you can do this in C# using the built in functions, or if you would need to use interop to call the native APIs. If the latter, it would probably be quicker to use C/C++.
Or you could use the SubInAcl tool. It can take ownership of files, registry keys, etc.
To be clear you right click and run as administrator when you talk about running it in administrator mode - this is elevated privilege and it wont happen by simply double clicking. Even if you login as admin you must right click and run as administrator to get elevated.
My problem I fixed by writing to CURRENT_USER and not LOCAL_MACHINE now I see that your problem is not actually solved by elevation and granting. Your security descriptors stored in the Registry were probably corrupted by garbage writes from the AWOL driver or whatever happened. This means you wont be able to do much, including fix yourself or a new user.
You may not be able to run CCleaner either until we clear the permissions issue. However you can boot into safe mode and run sfc /scannow and chkdsk - the sfc fixed one persons issue similar however it may be risky so do at own risk but it looks promising and I probably would have already done the scannow before I tried anything else. Safemode +sfc/scannow
I would backup data and wipe it ASAP much faster. I did find instructions for various OS on the matter of corrupt security descriptors - for Win 8 and 7 so you should not have problems and look like they will require Safe Mode
Good Luck!
Related
I've been working on this issue for about 6 hours now and feel like I'm getting nowhere. I have a vbscript to write to the windows registry that I want to use during the installation of a .net Visual Studio program. It writes to the Local Machine part of the registry, so permissions have to be edited to accomplish that. The code in question is as follows:
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, WScript.ScriptFullName & " /elevate", "", "runas", 1
WScript.Quit
End If
The code works perfectly when I just run the script from my desktop, and does exactly what I need it to do. But when I run the setup.exe that includes the script (even if I run setup.exe from my desktop), I get an Object Required error from the WScript code above. I need to know either 1) why I am getting this error and how to allow access to the WScript object, or if that is impossible 2) how to give my script the proper admin privileges required to write to the Local Machine Registry without using WScript.
If you are running this script as a VBScript custom action, then Windows Installer uses a custom VB script host. Unlike wscript.exe and cscript.exe, this host does not provide the WScript object, so any references to it will fail. You could choose to launch it as an EXE action via wscript.exe instead. I would not recommend this, at least not without reading my third paragraph.
Also, as a general recommendation, you should avoid elevating within a custom action, as doing so leads to the potential of multiple UAC prompts during a single installation. So to write to per-machine areas of the registry you should prefer using the Registry view, and thus entries in the Registry table. If you need custom values, note that you can specify property references in the view/table, and they will be evaluated when writing the values.
If you absolutely need to write to the registry through a custom action, consider carefully the rollback scenarios, and prefer to use an action that is "deferred in system context," as this kind of custom action will have access to administrative privileges if the installation is per-machine. Note that deferred custom actions do not have access to most properties.
I want to track a setting system-wide on the target machine- it is a run time counter that keeps track of how many times my client runs my software. I decided to put this value in the registry, but I really want to track how many times it is run for the whole system, not just for the current user account.
I would expect to use HKLM to track this at a machine level, but UAC doesn't like this nowdays.
Is there a correct way to read and write a setting that is machine-wide?
HKLM isn't for this type of use (since Windows XP at least).
Use the %PROGRAMDATA% folder instead (which you can also get via the WinAPI function SHGetKnownFolderPath with FOLDERID_ProgramData (SHGetFolderPath with CSIDL_APPDATA on Windows versions prior to Vista). It's specifically designed for application data that is global to all users of the machine. (On Windows 7, this is the C:\ProgramData folder by default.) Your application should create a directory beneath there and store the counter information in a file in that location instead.
(It also means you don't have to defeat the purpose of UAC by allowing public write access to the registry in inappropriate locations.)
From Environment.SpecialFolder Enumeration:
CommonApplicationData The directory that serves as a common repository for application-specific data that is used by all users.
Have a "CommonApplicationData\Your Company Name\Your Product Name" folder created in your setup program and change the ACL for the folder to allow limited user full control permissions (the inherited permission is read only for limited users). You can do this via the LockPermissions MSI table, or if your setup program does not support LockPermissions, create a custom action to change the ACL.
You also need to handle potential edit conflicts created by fast user switching.
I need to set permissions on a file, so that all users on the system can read and write to it. This is related to an installer, so I do not know the user names ahead of time. The installer runs as admin, so the log file requires admin access afterwards. So I need to explicitly set the permissions, during the install, so that referencing programs don't need to be run as admin.
In essence, I'm looking for a solution that can give me the equivalent of chmod777 in Windows.
I would prefer a solution that works for both Win7 and WinXP. I would like a solution that is through command line, which I can then script. Or a solution using C# or java.
All modern Windows OS's have a build-in group called "Everyone" that is the equivalent of the UNIX "other" permissions. Even non-logged-in users are part of the Everyone group. From there you can give "Everyone" read, write, and modify ("change") permissions. You could, if you were completely insane, give Everyone "full control" but that actually allows them to take ownership and change the permissions, so please don't do that :)
To actually apply these permissions you can use a number of techniques
From a command-line, you can run cacls <file name> /g Everyone:RWC
In .NET you can create an ACL for the NT Account with WellKnownSidType.WorldSid then apply it to a file, as in this article: http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/c513ca26-9bf8-4e39-a993-4ebf90aaece6/
You can use WMI, as per How to change file permissions with WMI? (should work in any WMI-enabled language)
You could use the native Win32 file permission APIs (via P/Invoke or JNI).
In C#, you can get an NTAccount object, and get the file's FileSecurity object, and use the FileSecurity object's AddAccessRule method to set permissions.
See the MSDN forum post below for more detailed instructions.
http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/c513ca26-9bf8-4e39-a993-4ebf90aaece6/
Application2 was orginally developed an application for WinXP. Now I have to contend with User Account Control (UAC) on Win7. The Application2 runs fine on Win7 as long as the user is logged into an Administrator account and they select "Run as administrator." However, I am trying to evaluate whether it is possible to refractor Application2 so that it does not require an Administrator account and "Run as administrator." I would also like to avoid any dialog boxes requiring users to make a choice if possible.
Application2 features that currently require "Run as administrator"
Create System Data Sources (ODBC)
Read/write/delete registry keys
Copy/delete files in C:\Program Files\MyApp
Encypt/decrypt files in C:\Program Files\MyApp
Start .exe processes located in a shared folder on a remote machine
Start VBScript processes that install Office Add-ins and read/write/delete registry keys
Copy/delete/modify files in C:\Program Files\MyApp\MyData
Number 6 can be solved by relocating this folder to My Documents (its location is stored in the registry*), or granting the user "Full control" permissions to C:\Program Files\MyApp\MyData, or letting Win7 make the necessary modifications in the VirtualStore folder.
Numbers 3 and 4 is more difficult to deal with because Application1 has to read files in C:\Program Files\MyApp. Application1 will not be using "Run as administrator," and I need to do more research to figure out how the VirtualStore folder can be used to bridge the gap between Application2 and Application1.
As for the other points, I am trying to figure out options:
Please let me know if/how it is possible to perform these actions under a non-Administrator user account and without "Run as administrator."
Please let me know if any of the actions are impossible without being an Administrator.
Feel free to point out any technical mistakes that I may have made in the contents of this question.
Again, I am trying to avoid dialog boxes during application runtime.
*Thinking out loud here: I would need to delete C:\Program Files\MyApp\MyData after copying to C:\My Documents\MyData, and I would need to modify the registry key storing the folder path, maybe these steps could be done during installation.
Discoveries
On Windows 7, even without "Run as administrator" you can:
Create/delete User Data Sources
Create/modify/delete files in C:\Users\Public\Documents or C:\Users\currentuser\Documents
Create/delete registry keys in HKEY_CURRENT_USER
Furthermore, I believe it is dangerous to have a Windows 7 application without a UAC Application Manifest file. Because, if you don't have one, Windows 7 decides for you whether to run the application in Compatibility Mode or not. If you have one, you can specify how your application needs to run.
No, you can't do these things without getting elevated. The point of UAC is not to stop you from doing this, it is to let the user know that you're about to do this. An obvious and valuable property of UAC is that it doesn't provide a backdoor to do these things anyway without the user knowing about it. This is not a problem, it is a feature.
What you describe doesn't strike me as something that needs to happen frequently. This should not wear out the user. If that's an issue, you can run it from a scheduled task using an admin account.
The best thing to do is to change your application - only slightly, mind you - so that it will run as a non-elevated user. To help you do that, I have to point out some subtleties.
For example, point 1, "read and write registry keys", is overly general. Applications that are non elevated can and do read and write registry keys with no problem at all. The restriction is that you can't write registry keys in HKLM. So you can avoid UAC issues if you change your code to use a key under HKCU, or if you refactor some of your code into an admin/config/setup app that runs elevated and writes keys to HKLM, and an ordinary app that reads those keys but never writes them.
Point 2 and 3 are both "can't write to anything under Program Files." Change your code so that the files you need to copy/delete/encrypt/decrypt are not under Program Files. AppData is a popular (per user) location for this.
Stay away from the whole virtualization thing and deliberately trying to use the Virtual Store. It confuses users tremendously. Instead, gain a firm understanding of the behaviours that non-elevated apps can't execute, and adjust your code to perform the (very similar) replacement behaviours, such as using HKCU instead of HKLM or AppData instead of Program Files.
I have a few questions related:
1) Is possible to make my program change filetype association but only when is running? Do you see anything wrong with this behavior?
2) The other option that I'm seeing is to let users decide to open with my application or restore default association ... something like: "capture all .lala files" or "restore .lala association". How can I do this? What do you think that is the best approach?
Regarding file associations, I've wrote an answer earlier that at least covers the "How".
This should also point you to the right direction how to handle backup and restore. With direct registry access through c#, there will be no need to use .reg files, so you are free to back up the previous value however you like in your app, and also restore it from there.
The key question here is: Should you change file associations randomly? At least asking the user up-front would obviously be necessary (as you also indicated).
Furthermore, Vista users with UAC enabled, or non-privileged users of other Windows versions may not have the required permission to change global file associations. The (un)installation procedure of your program may be the only place where this can succeed.
EDIT
As Franci Penov indicated in his answer, there is a way to change local file associations on a per-user basis, even for non-admins (that's why I spoke of "global associations" in the previous paragraph). He also mentioned mentioned why going there is not overly advisable.
You can implement an "on the fly" file association change by associating a small executable with that file extension that upon start will check if your main application is running and pass the file name to it or if it's not running it'll invoke the "regular" associated application.
The main advantage of this approach is that you need to muck with the registry only once.
The main drawbacks of this approach are:
you need a helper process
the application that "owns" these file extensions can detect the change and complain to the user, prompting "repair" thus getting you out of the picture.
Alternatively, you could change the file association upon your main program start. This will work even for non-admin users. while file associations are stored in HKEY_CLASSES_ROOT, there's a small trick - HKCR is actually a map of both HKEY_LOCAL_MACHINE\SOFTWARE\Classes and HKEY_CURRENT_USER\SOFTWARE\Classes. Thus, you can temporarily register the file extension for the current user in HKCU and "shadow" the original association from HKLM.
Of course, I would advise against this approach though, as it takes just one crash in your application to make that association permanent and since very few applications know how to deal with file associations in HKCU, chances are it'll be an unrecoverable situation for the original application.
It can probably be done but I think it would end up being cumbersome. All file type associations are stored in the registry so you would have to write/revert registry entries every time your app starts and stops. Also, depending on how frequently you do it the new associations may not be picked up in Windows explorer immediately.
The associations are listed under HKEY_CLASSES_ROOT in the registry and can be mapped a whole myriad of ways (mime types/progIDs/etc).
Many apps I have seen ask if you want to associate certain file types with the application during install time, and give you the ability to opt-out and leave the current settings.
I don't think I'd recommend "on the fly" file type associations
1) you get to define the file types that are in the Open Dialog file type droplist.
Outside of that, it's possible to change the filetype default on application open, and then replace during application close, as file type association are just a registry setting.
As for wrong, I wouldn't. First reason is that it's not the standard behavior of applications. The second reason is that if your application or PC exits unexpectedly, you run the risk of not returning the association to it's original setting.
2) Windows by default allows user to choose these options utilizing the right-click and the "open with" command.