c# Deleting a file in System32 folder - c#

im trying to delete a specific file in system32 but as thats where all the important files is, its very hard to delete things from there. The only way i can do it so far is if i go into the propertys and change the permissions so i have full control over that file and then delete it.
I am trying to do this programmaticly, ive tried numerous ways of changing the permissions on a file but i just get the error "unauthorised", even in elevated cmd using commands like takeown/ it doesnt work, i know if i can do it in cmd, i can do it programmaticly so that would work too.
any help is appriciated

You should elevate the permissions due to UAC. Below is a sample which checks if the current user running the app has elevated rights, if not, exits and re-runs the app with Admin rights.
WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);
if (!hasAdministrativeRight)
{
RunElevated(Application.ExecutablePath);
this.Close();
Application.Exit();
}
private static bool RunElevated(string fileName)
{
//MessageBox.Show("Run: " + fileName);
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
processInfo.FileName = fileName;
try
{
Process.Start(processInfo);
return true;
}
catch (Win32Exception)
{
//Do nothing as user cancelled UAC window.
}
return false;
}
Take ownership of the file and delete
new Process() { StartInfo = new ProcessStartInfo("cmd.exe", #"/k takeown /f C:\Windows\System32\testfile.txt && icacls C:\Windows\System32\testfile.txt /grant %username%:F") }.Start();
File.Delete(#"C:\Windows\System32\testfile.txt");

Further research showed that there is a much better way of doing this. Carry on;
Create Application Manifest
By doing this, you don't need to check for admin rights in the app and restart if required. By default, app will launch with the elevated credentials. Simple Add > New Item > Application Manifest to project and uncomment following line ;
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Set File Access Permission in Code and Delete File
There should be a lincense.txt file in System32 folder. We can delete it with the following;
FileInfo insInfo = new FileInfo(#"C:\Windows\System32\license.txt");
FileSecurity insFileSecurity = insInfo.GetAccessControl();
insFileSecurity.AddAccessRule(new FileSystemAccessRule(System.Environment.UserDomainName + "\\" + System.Environment.UserName, FileSystemRights.FullControl, AccessControlType.Allow));
insInfo.SetAccessControl(insFileSecurity);
File.Delete(#"C:\Windows\System32\license.txt");
NOTE : Once you set the application.manifest with requirement of elevated permissions, Visual Studio may want to restart with Administrator rights when you start debugging. Simply allow it to restart, your project will be loaded automatically and you can start debugging.
NOTE FOR CLICK-ONCE APPLICATIONS : When elevated permissions are set in the manifest, clickonce applications deny to compile. To fix this, right click on the application project and go to Security tab. Uncheck "Use Click-once Application Security" option and you are good to go.
Hope this helps

Related

run shell command (manage-bde) as administrator from C#

I need to run "manage-bde" shell command from C# code.
The main application process is already running as administrator and is Elevated.
I used code from : UAC self-elevation example on MS website for confirming the app process is elevated.
(http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3)
However, when I try to run manage-bde from the C# code, I get "System can't find file specified".
Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\System32\\manage-bde.exe";
p.StartInfo.UseShellExecute = true;
p.Start();
As a workaround, I tried to create a batch file that runs the command.
string batchFileName = DateTime.Now.Ticks + ".bat";
StreamWriter writer = new StreamWriter(batchFileName);
writer.WriteLine("manage-bde");
writer.Flush();
writer.Close();
Process p = new Process();
p.StartInfo.FileName = batchFileName;
p.StartInfo.UseShellExecute = true;
p.Start();
The batch file is written , and executed successfully; However, the command "manage-bde" is not recognized.
I changed the code to use the verb "runas" and use admin password and that works, but I want the batch file to work without the need for providing the admin password. The current logged in user is already administrator on the computer but the batch file is not getting executed with the existing admin privileges . I need the batch file to execute and manage-bde to run successfully.
Your help or advice will be very highly appreciated :)
ps: some commands other than manage-bde work fine without need for admin runas.
The reason of the behavior I encountered was the Windows File System Redirector.
In most cases, whenever a 32-bit application attempts to access %windir%\System32, the access is redirected to %windir%\SysWOW64
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx
My application build was 32 bits. Whenever it tried to access System32 windows automatically redirected it to SysWow64 which does not contain "manage-bde.exe". I changed the build to 64 bits and then the application could access manage-bde.exe from System32
Even if you're running as the Administrator user, you're not fully elevated if UAC is running. Meaning that you'll have either the UAC prompt come up or you'll be prompted for a password.
The only real way you could get around that is to run your application elevated first, or to write a service that runs with elevated permissions to start your new process.
The alternative of course is to disable UAC, but that is undesirable in most situations.

C# Remove Readonly From Main Application Folder

I'm trying to build an application with an auto / self updater. The file will check for updates then immediately download the files and replace the necessary files. I've been trying to put this into an installer package, but am running into a problem with the Application Folder being read only. I've tried removing the readonly parameter using code from multiple SO this one, but after the program is installed, the folder remains read only.
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
string path = this.Context.Parameters["targetdir"];
path = path.Substring(0, path.Length - 1);
DirectoryInfo di = new DirectoryInfo(path);
di.Attributes &= ~FileAttributes.ReadOnly;
di.Refresh();
}
catch (Exception e)
{
}
}
I've tried putting this in the Commit method as well. The path is definitely being pulled (MessageBox.Show showed the correct path).
Do I need to be doing something different to change the application's main folder?
I don't see why the updater process matters in the context of this question, but here is how it is working:
User launches the updater app as a sort of "portal" to the main application.
The updater checks the server for an update specific to that device.
The new files are downloaded and all files are replaced that aren't currently locked.
The exe then calls a helper exe and closes itself. The helper exe updates the remaining files (IE the updater itself)
The helper then launches the main application.
You're not looking to remove the Read-only flag, you're looking for elevated permissions to write in that folder - it's not read only to begin with.
To that end you can run your installer app with "RunAs":
// launcher code
if (CheckIfUpdateAvailable()){
ProcessStartInfo startInfo = new ProcessStartInfo ("MyUpdater.exe");
startInfo.Verb = "runas";
System.Diagnostics.Process.Start (startInfo);
Application.Quit();
}
the process spawned by launcher will have the rights to write in your app folder
and your updater has to be an executable you deploy along with your app - you'll find it hard to overwrite a running executable's file
or you could switch to ClickOnce and this comes for free. Granted - there are some minor limitations on what you can do with a ClickOnce installer.
http://support.microsoft.com/kb/981778
I ended up doing a self-elevation (restart run-as) for the updater. This will only ask for permission if there is an update available.
// During update process:
if (!IsAdministrator())
{
// Launch itself as administrator
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Application.ExecutablePath;
proc.Verb = "runas";
try
{
Process.Start(proc);
}
catch
{
// The user refused to allow privileges elevation.
// Do nothing and return directly ...
return false;
}
Application.Exit();
}
public static bool IsAdministrator()
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
Another solution that is working, although not entirely how I would like it, is to go through each project's properties -> Security -> Enable ClickOnce security settings and then building the installer. This is annoying because it asks for permission every time the file runs on a UAC account. However, it is working and doesn't require some looping exe launching.

Permission issue running .exe from ASP.NET web application

We have a .exe which we need to execute at the time an order is placed on a website. When
we test this locally it works fine using IIS Express. When we move it to IIS, it fails. We assume this is a permissions error as if we set the App Pool to run as the administrator then the script works again. The question we have is how do we execute the .exe as the administrator whilst the App Pool is ApplicationIdentity? We are using the following code:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = executablePath,
Arguments = argumentList,
Domain = domain,
UserName = userName,
Password = securePassword,
UseShellExecute = false,
LoadUserProfile = true
}
};
process.Start();
process.WaitForExit();
process.Close();
The .exe is trying to write to the Users AppData folder which is why it fails. It is a 3rd party app so we cannot change the source code.
EDIT: Just to clarify also, when we specify the username and password in procmon it still appears to run from ISUR.
We fixed this by enabling User profile on IIS AppPool and setting permission for the IIS user on the folder it was trying to write to.
We sue ProcMon to find where the program was failing and the folder it was trying towrite to was C:\Windows\System32\config\systemprofile
i dont remember actually, but one of them is working 100% ( i had this issue before)
just let me know ehich one of them is the correct one.

How can I restart IIS from C# code running as a user who is an administrator?

Typically (in Windows 7), installing a program will ask for permission to modify the system. As an administrator, I can give the authorization without supplying a password.
I'm trying to figure out how to take an administrator action (restart IIS) from C# code running as a user who is AN administrator, but the not THE "Administrator" account.
To run a process as elevated you can use the runas verb.
Process elevated = new Process();
elevated.StartInfo.Verb = "runas";
elevated.StartInfo.FileName = "Whatever.exe";
elevated.Start();
For restarting IIS (as mentioned before) use iisreset.
Hope you find this useful.
For anyone still looking for this, here is code that I use to help me out with this.
private static void DoIISReset()
{
Process iisReset = new Process();
iisReset.StartInfo.FileName = "iisreset.exe";
iisReset.StartInfo.RedirectStandardOutput = true;
iisReset.StartInfo.UseShellExecute = false;
iisReset.Start();
iisReset.WaitForExit();
}
Hope this helps!
Try to execute the IISReset command from C#
http://technet.microsoft.com/en-us/library/cc758159(WS.10).aspx
iisreset /noforce
Using ProcessStart
System.Diagnostics.Process.Start(#"C:\Windows\System32\iisreset.exe");
If you're using AD Authentication and you're an administrator this should work
System.Diagnostics.Process.Start(#"C:\Windows\System32\iisreset.exe");
This code help to you but you can get Access Denied.
For you to not get Access Denied:
Right Click Project
Add New İtem
Add Application Manifest File
Change this section
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
To this
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There are two ways to do this but fr both you need to run VS as administration.
This code will prompt in an empty cmd for some time and will close the window automatically.
Process iisReset = new Process();
iisReset.StartInfo.FileName = "iisreset.exe";
iisReset.StartInfo.RedirectStandardOutput = true;
iisReset.StartInfo.UseShellExecute = false;
iisReset.Start();
iisReset.WaitForExit();
this code will also restart IIS and it will prompt CMD with few processing.
Process.Start(#"C:\WINDOWS\system32\iisreset.exe", "/noforce");
Here is a link to how this is done in power shell
http://www.computerperformance.co.uk/powershell/powershell_service_start.htm
Another possibility would be to use WMI
http://www.motobit.com/tips/detpg_vbs-wmi-restart-service/
Here is another way directly in #
http://www.csharp-examples.net/restart-windows-service/
I hope this helps....

Write Access to Program Files folder

my application include a self-updater executable that is used to update the application.
One of the first steps the updater is performing is to check that it does have write permission to the application folder
IPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, _localApplicationCodebase);
if (!SecurityManager.IsGranted(perm))
{
OnProgressChanged("Security Permission Not Granted \n The updater does not have read/write access to the application's files (" +
_localApplicationCodebase + ")",MessageTypes.Error);
return false;
}
OnProgressChanged("Updater have read/write access to local application files at " + _localApplicationCodebase);
return true;
When executing under Win7/Vista, this code pass (meaning that according to CAS, the code does have write access), however when I try to write files, I got an Access Denied (and I confirmed that the files are NOT in use)
I understand that Vista/Win7 UAC is preventing users from writing files in the program files folders. However, what I don't understand is why the permission is granted if in reality it is not
Regards,
Eric Girard
PS : If I run the same code using 'Run As Administrator', it works fine
The important thing to know about UAC is that by default, no code runs with Administrator privileges and thus cannot write to the Program Files directory. Even if you are logged in as an administrator, the apps are launched with standard user privliges.
There are two ways around this. You can have the user start the app with the Run As Administrator menu item. But this relies on the user to remember something. The better was is to embed a manifest into your executable that requests administrator privileges. In the manifest, set requestedExecutionLevel to requireAdministrator. This will cause UAC to prompt the user for admin credentials as soon as the app starts.
As Daniel said, the best solution is to put the updating functionality in a separate application. Your primary app will have an manifest that sets the requestedExecutionLevel to "asInvoker" and your updater app with request "requireAdministrator". Your primary app can run with standard privileges. But when the update needs to happen, use Process.Start to launch the updater application that requires the user to enter the admin credentials.
The best way to write an auto updater is to have a secondary application. The first program calls the second with elevated privileges, prompting UAC. Then the second application can install the patches.
I'm not sure if this is what you're trying to do, but I've found this post helpful. The included code let's you detect if you're app is running on Vista, if UAC is enabled and if user is elevated.
http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html
then restart your app with runas to let user elevate permissions
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Application.ExecutablePath;
Process.Start(processInfo);

Categories