In order to get whether the current process is running with administrator privileges, we use the following C# code:
public static bool IsElevated {
get {
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
}
However, I am trying to find whether another separate process is elevated or not.
How do I go about doing that programmatically?
Try this out: https://stackoverflow.com/a/4497572/3049344
var process = Process.GetProcessesByName("YouProcessName").First();
IntPtr tokenHandle;
if (!OpenProcessToken(process.Handle, TOKEN_READ, out tokenHandle))
{
throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error());
}
...
Related
I have a program in which I check if the program is already launched or not.
I use:
if (System.Diagnostics.Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location)).Count() > 1) return;
The check works but the problem is that this doesn't work on a terminal server.
The reason is, is because I check if the process exist in the existing processes.
Example:
If user A is connected to a terminal server and runs program X, user B won't be able to launch the program (because the program X usage of user A will show up in the list)
My question is, how in C#, can I check if the program is already running under the context of the user?
I have discovered the following WMI-code that works in PowerShell, but the problem is that this doesn't work in C#
$owners = #{ }
gwmi win32_process |% {$owners[$_.handle] = $_.getowner().user}
$ps = get - process | select processname,Id,#{ l = "Owner"; e ={$owners[$_.id.tostring()]} }
foreach ($p in $ps) {
if ($p.Owner - eq $env: USERNAME) {
$p
}
}
Would there be a method by editing my existing method to allow this?
I tried to do:
Process[] runningProcesses = Process.GetProcesses();
var currentSessionID = Process.GetCurrentProcess().SessionId;
Process[] sameAsThisSession =
runningProcesses.Where(p => p.SessionId == currentSessionID).ToArray();
if (sameAsThisSession.Contains(System.Diagnostics.Process.GetCurrentProcess()))
{
MessageBox.Show("Program already running!");
}
But this doesn't work. (It does show the processes of the user only though).
Here the code is
protected override void OnStart(string[] args)
{
Thread thr = new Thread(new ThreadStart(run));
thr.Start();
}
static void run()
{
while (true)
{
StreamWriter str = new StreamWriter("D:\\Sarojini.txt", true);
str.WriteLine();
str.WriteLine("**** List of Apllication*********");
str.WriteLine();
str.WriteLine("Service started on:" + DateTime.Now.ToString());
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
str.WriteLine();
str.WriteLine("the current user is " + userName);
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
str.WriteLine("Process::{0} ID::{1} Title::{2}", process.ProcessName, process.Id, process.MainWindowTitle);
}
}
str.Close();
Thread.Sleep(3600000 / 10);
}
}
protected override void OnStop()
{
StreamWriter str = new StreamWriter("D:\\Sarojini.txt", true);
str.WriteLine();
str.WriteLine("the service has been stopped.");
}
here in this code , a text file is created and first line is written on it but the list of running application is not there , where as when i used this code in in windowsFormApllication it is running perfectly. i dont know what is the problem .
This is most likely due to the account you are running the service under not having the correct permissions to use the Process class. When trying to retrieve process names, IDs etc your application needs to have sufficient rights and the default Local System Account is unlikely to meet this.
When you run this code as a Windows Form Application WindowsIdentity.GetCurrent() will return the user who is currently signed in.
When you run this code as a Windows Service WindowsIdentity.GetCurrent() will return the user who setup under the User Account in the Service Setting.
This will show that they are running with different credentials. So, your service may be running under an account that does not have permission to perform the required actions.
To check this:
Go into Services and double-click your service.
Click on The Log On tab
By default Local System Account is checked but you want to select This Account and set a valid account.
This question already has answers here:
How do I force my .NET application to run as administrator?
(12 answers)
Closed 8 years ago.
I am creating an application that monitors another application, if the application get close the former will restart that, and I have to create a folder in c:\ drive , if i simply run the application nothing happens but when i run that as admin it works as required.
What can I do to make this application automatically start as admin without any prompt, as i want to run this application on start up, just like some antivirus programs which do not ever need admin rights.
public bool IsProcessOpen()
{
string name = "aProgram";
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(name))
{
return true;
}
}
return false;
}
private void timer1_Tick_1(object sender, EventArgs e)
{
try
{
bool track = false;
track =IsProcessOpen();
if (!track)
{
Process firstProc = new Process();
firstProc.StartInfo.FileName =Application.StartupPath + "\\" + fileName;
firstProc.EnableRaisingEvents = true;
firstProc.Start();
}
}
catch (Exception)
{
}
}
I dont want that the user gets UAC prompt.
in windows there is something called task scheduler, there one can create the task and give the path to any specific program, choose admin rights and when to start etc. attached screenshots for your reference
My user is an Administrator (I see it in the configuration panel), the below code throws a Win32Exception in which it says Access Denied, how can I change this (Win7 32 bits) ?
static Guid VideoGuid = new Guid("4d36e968-e325-11ce-bfc1-08002be10318");
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
static void Main(string[] args)
{
SafeDeviceHandle handle = null;
try
{
handle = NativeMethods.SetupDiGetClassDevs(ref VideoGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF.PRESENT);
var data = new NativeMethods.SP_DEVINFO_DATA().Initialize();
var param = new NativeMethods.SP_PROPCHANGE_PARAMS().Initialize();
param.ClassInstallHeader.InstallFunction = 0x12;
param.StateChange = NativeMethods.DICS.ENABLE; // 0x01
param.Scope = NativeMethods.DICS_GLOBAL.GLOBAL; // 0x01
param.HwProfile = 0;
RunWin32Method(() => NativeMethods.SetupDiEnumDeviceInfo(handle, 0u, out data));
RunWin32Method(() => NativeMethods.SetupDiSetClassInstallParams(handle, ref data, ref param, (UInt32)Marshal.SizeOf(param)));
RunWin32Method(() => NativeMethods.SetupDiChangeState(handle, ref data));
}
catch
{
var w = new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
if (handle != null && (!handle.IsInvalid))
handle.Close();
}
}
static void RunWin32Method(Func<bool> f)
{
if (!f())
{
Debug.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).Message);
}
}
If you want more code, just ask :-)
Thanks
Recapping the comment trail, a user in the Administrator group doesn't have admin rights on Vista/Server 2008 and later unless the process runs elevated. A manifest is required to get Windows to display the UAC elevation prompt.
This cannot work for programs that are started at login by the Run registry key or the Startup folder. Windows refuses to display the elevation prompt because the user cannot accurately guess exactly what program asked for the elevation. Code-signing the program with a certificate may fix this since that permits Windows to verify and display the program owner, never actually tried that.
Workarounds for such programs are activating it as a service or a scheduled task. Neither of which requires the manifest. The theory behind this seeming oddity is that it already requires elevation to get a service or scheduled task installed.
I found a method for copying ntfs permissions information from one existing folder to a newly created one - I'm not sure if it's doing the work it should do. Maybe one can have a look at the method and give some comments:
private static void CopySecurityInformation(String source, String dest)
{
FileSecurity fileSecurity = File.GetAccessControl(
source,
AccessControlSections.All);
FileAttributes fileAttributes = File.GetAttributes(source);
File.SetAccessControl(dest, fileSecurity);
File.SetAttributes(dest, fileAttributes);
}
Thanks for your help,
Daniel
I tried following the OP suggested pattern for copying a file's ACLs and attributes and found a few issues in our application. Hopefully this information helps others.
According to MSDN, using the File.SetAccessControl() method as shown above will not work.
The SetAccessControl method persists only FileSecurity objects that
have been modified after object creation. If a FileSecurity object
has not been modified, it will not be persisted to a file. Therefore,
it is not possible to retrieve a FileSecurity object from one file and
reapply the same object to another file.
It is necessary to make a new FileSecurity object for the destination file and assign to this a copy of the source FileSecurity object.
Here is an example of a pattern that works from our app.
public static void CopyFile(string source, string destination)
{
// Copy the file
File.Copy(source, destination, true);
// Get the source file's ACLs
FileSecurity fileSecuritySource = File.GetAccessControl(source, AccessControlSections.All);
string sddlSource = fileSecuritySource.GetSecurityDescriptorSddlForm(AccessControlSections.All);
// Create the destination file's ACLs
FileSecurity fileSecurityDestination = new FileSecurity();
fileSecurityDestination.SetSecurityDescriptorSddlForm(sddlSource);
// Set the destination file's ACLs
File.SetAccessControl(destination, fileSecurityDestination);
// copy the file attributes now
FileAttributes fileAttributes = File.GetAttributes(source);
File.SetAttributes(destination, fileAttributes);
}
After fixing the first issue, then we found the owner attribute was not being copied. Instead, the destination file was owned by Administrator in our case. To get around that the process needs to enable the SE_RESTORE_NAME privilege. Check out AdjustTokenPrivileges on pinvoke.net for a complete Privileges class that makes setting privileges easy.
The last thing that we had to deal with was UAC. We needed to restart our app with administrative rights if the user is running under UAC. Here is another example from our app that deals with relaunching the app with elevated privileges.
private static void RelaunchWithAdministratorRights(string[] args)
{
// Launch as administrator
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.UseShellExecute = true;
processStartInfo.WorkingDirectory = Environment.CurrentDirectory;
string executablePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
processStartInfo.FileName = executablePath;
processStartInfo.Verb = "runas";
if (args != null && args.Count() > 0)
{
string arguments = args[0];
for (int i = 1; i < args.Count(); i++)
arguments += " " + args[i];
processStartInfo.Arguments = arguments;
}
try
{
using (Process exeProcess = Process.Start(processStartInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// The user refused to allow privileges elevation. Do nothing and return directly ...
}
Environment.Exit(0);
}
Ours was a console app so we need to pass the args parameter from the Main method to the RelaunchWithAdministratorRights(args). Non-console apps could pass null instead. We call RelaunchWithAdministratorRights from within catch blocks as in:
try
{
...
}
catch (SecurityException)
{
RelaunchWithAdministratorRights(args);
return;
}
In our app we just return after the call to RelaunchWithAdministratorRights to exit the instance of the app that lacked privileges. Depending on your app, you may prefer to throw your way out. Regardless, after returning from RelaunchWithAdministratorRights you don't want this instance to continue processing.
Enjoy!
It does slightly more than just copying the NTFS permissions. It also copies the attributes of the file. I'm not quite certain whether it copies inherited permissions, though, but run it once and you should be able to find out.
Note that copying permissions on and of itself requires special permissions (administrators have these, of course), be sure the process running this method has the required permissions to query, view and set permissions on those objects.