Is there a way I can get a list of all open applications and a list of all open files? For the files I only need the files that I opened (documents etc) not OS's open system files. The same for the applications (only browsers, document processors etc).
I already tried various functions from the Windows API like EnumWindows but I couldn't get what I wanted.
An example of what my ultimate goal would be, is to have lists like this:
Applications
Microsoft Word,
Notepad,
Mozilla Firefox
Files
foo.txt,
foo.mp3,
foo.doc
What I need is just the names, I don't need handles etc (even though I'm sure I'll have to use them to get what I want)
You can get a list of running processes with their information
public static string ListAllProcesses()
{
StringBuilder sb = new StringBuilder();
// list out all processes and write them into a stringbuilder
ManagementClass MgmtClass = new ManagementClass("Win32_Process");
foreach (ManagementObject mo in MgmtClass.GetInstances())
{
sb.Append("Name:\t" + mo["Name"] + Environment.NewLine);
sb.Append("ID:\t" + mo["ProcessId"] + Environment.NewLine);
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
The only method (That I know) to see if the process is opened by user or system is to check it's owner. If it's system, then it's not run by user:
//You will need to reference System.Management.Dll and use System.Management namespace
public string GetProcessOwner(string processName)
{
string query = "Select * from Win32_Process Where Name = \"" + processName + "\"";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
string owner = argList[1] + "\\" + argList[0];
return owner;
}
}
return "NO OWNER";
}
For the list of opened files, It is possible to do using Managed Code which is somehow hard. Here is an example on codeproject demonstrating the same matter
You can have a list of running processes with Process.GetProcesses(): http://msdn.microsoft.com/en-us/library/1f3ys1f9.aspx
But you can have the file they have open if they exposes some automation interface you know.
Related
I have below code to format a USB drive. Code works fine with Admin account, but if I run the exe using Non Admin account, it returns 3 (Access Denied).
I want to format a drive in Non-Admin mode. Any help?
I visited this link https://social.msdn.microsoft.com/Forums/en-US/1e192745-9d58-4507-93f0-ceacbc0cde96/wmi-win32volume-format-method-returns-access-denied?forum=windowsgeneraldevelopmentissues , but no help
ManagementObjectSearcher searcher = new ManagementObjectSearcher(#"select * from Win32_Volume WHERE DriveLetter = '" + driveLetter + "'");
foreach (ManagementObject vi in searcher.Get())
{
var result = vi.InvokeMethod("Format", new object[] { fileSystem, quickFormat, clusterSize, label, enableCompression });
if (Convert.ToInt32(result) != 0)
{
throw new Exception("Error while formating drive");
}
}
Have you tried "Right Click> Compatibility> Change All User Settings> Run As Administrator"?
If this is the solution, you can do this with the code.
Probably, this question - answer, can answer your problem.
How do I force my .NET application to run as administrator?
I want to find which processes are using a particular dll using C# and WMI. Tried 3 approaches...
Getting CIM_DataFile object for the file and then get related processes.. It works for system dlls but not for My application dll.. It wont show any process associated with that even though process explorer shows the same.
Enumerating through all the processes and then enumerating through the process modules to find the DLL is being used or not.. Here also same issue.. working for system dlls but not for my application dlls.
Getting CIM_ProcessExecutables objects and getting DLLS/EXE and its linked processes... here also same thing is happening...
Is there anything im missing?
enter code here
using System;
using System.Management;
// Search the processes which have a certain file open
class App
{
public static void Main()
{
WhoHasThisFileOpen("c:\\\\users\\\\pawarnit\\\\source\\\\repos\\\\myprogram\\\\myprogram\\\\bin\\\\debug\\\\differentDllFile.dll");
Console.ReadLine();
}
static void WhoHasThisFileOpen(string objectQry)
{
SelectQuery query = new SelectQuery("select name from cim_datafile where name = '" + objectQry +"'" );
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(query))
{
foreach (ManagementObject mo in searcher.Get())
{
Console.WriteLine("File Name: {0} \nIs currently opened by:",
mo.Properties["Name"].Value);
// Get processes having this File open
foreach (ManagementBaseObject b in mo.GetRelated("Win32_Process"))
{
ShowProcessProperties(b.ToString());
b.Dispose();
}
}
}
}
static void ShowProcessProperties(string objectClass)
{
using (ManagementObject process = new ManagementObject(objectClass))
{
process.Get();
PropertyDataCollection processProperties = process.Properties;
Console.WriteLine("ProcessID: {0,6} \tCommandLine: {1}",
processProperties["ProcessID"].Value,
processProperties["CommandLine"].Value);
}
}
}
How do I determine the owner of a process in C#?
public string GetProcessOwner(int processId)
{
string query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
return argList[1] + "\\" + argList[0];
}
}
return "NO OWNER";
}
I detailed studied and implemented the code as given above. This code works fine but only gets the owner names of those processes which are 32 bits. The method return "no owner" for 64 bits processes.
Please help me, how I can get the processes owner names for both 32 bit processes and 64 bit processes.
No, that code works "fine". It also works when your code is 32bit but the target process is 64bit, so no issue here as well.
Possible reasons why you could get "NO OWNER":
You are trying to get the owner for which you have no permission (e.g. you are running as non-privileged user, but trying to get the owner of a privileged one).
You are trying to get the owner of a pseudo process (e.g. "System", with PID 4, or "System Idle Process" with PID 0).
BTW, also services have owners (regarding #weismat comment).
I have created a C# application to rename printers on a Citrix server (Server 2008 R2).
The reason for this is because every time a user logs on the printer gets forwarded to the server and gets a unique name(For example Microsoft XPS Document Writer (from WI_UFivcBY4-wgoYOdlQ) in session 3) and from within some applications thats an issue since the printer is pointed to the name and by that you need to change the printer setting everytime you logon a session.
The program itself works like a charm and the printer gets the names I desire.
However the issue is after that the printers have been renamed Windows does not seem to be able to identify them anymore. For example if I try to change default printer i get an error saying "Error 0x00000709 Double check the printer name and make sure that the printer is connected to the network."
var query = new ManagementObjectSearcher("SELECT * FROM Win32_Printer where name like '%(%'");
ManagementObjectCollection result = query.Get();
foreach (ManagementObject printer in result)
{
string printerName = printer["name"].ToString();
if (printerName.IndexOf('(') > 0)
{
printer.InvokeMethod("RenamePrinter", new object[] { printerName.Substring(0, printerName.IndexOf('(')).Trim() + " " + userName }); //userName is provided as an inputparameter when running the application
}
}
Am I missing anything? Are there anything else i need to do when renaming?
I cant seem to find any info regarding this case at all.
i thing this codeproject is what your looking for. But after some own experiences with the printers in C# i can only say it does not make fun and it can be really frustrating
Code with small modifications:
//Renames the printer
public static void RenamePrinter(string sPrinterName, string newName)
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = #"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\\", "\\\\") + "'";
ManagementObjectSearcher oObjectSearcher =
new ManagementObjectSearcher(oManagementScope, oSelectQuery);
ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();
if (oObjectCollection.Count == 0)
return;
foreach (ManagementObject oItem in oObjectCollection)
{
int state = (int)oItem.InvokeMethod("RenamePrinter", new object[] { newName });
switch (state)
{
case 0:
//Success do noting else
return;
case 1:
throw new AccessViolationException("Access Denied");
case 1801:
throw new ArgumentException("Invalid Printer Name");
default:
break;
}
}
}
Still works great in 2022, thank you. Just had to change type
int
to
UInt32
to avoid new Exception:
UInt32 state = (UInt32)oItem.InvokeMethod("RenamePrinter", new object[] { newName });
switch (state)
{...
How to kill specific process running under specific user account. using C#?
Thanks,
var processes = from p in Process.GetProcessesByName(nameOfTheProcess)
where p.StartInfo.UserName == nameOfTheUser
select p;
foreach(Process p in processes) p.Kill();
EDIT: as Fredrik pointed out, the UserName property is not set for processes obtained by GetProcesses. Here's a modified version that uses WMI to get the username (GetProcessOwner method found here) :
static void KillProcessByNameAndUserName(string processName, string userName)
{
var processes = from p in Process.GetProcessesByName(processName)
where GetProcessOwner(p.Id) == userName
select p;
foreach(Process p in processes) p.Kill();
}
static string GetProcessOwner(int processId)
{
string query = “Select * From Win32_Process Where ProcessID = “ + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod(“GetOwner”, argList));
if (returnVal == 0)
return argList[0];
}
return “NO OWNER”;
}
In order to get the username, you have to grab the security context of the process from the Win32 API.
Call the OpenProcessToken() function via P/Invoke using the process handle found in the .Net Process class from the code you already have above. You will obtain a structure that contains a SID for the owner of the process. Be prepared for errors such as Access Denied, since you may not have access rights to obtain this information for all processes, such as those that are not yours. From there, you have to convert the SID to a name. There are a few ways to do this, but LookupAccountSid() function (again, via P/Invoke) will get the username for you.
In framework 2.0, a bunch of stuff was added to help with dealing with security descriptors (System.Security.AccessControl namespace), however, I don't see anything that will help you in dealing with the P/Invoke complexities there.
See pinvoke.net for information on using the Win32 API from C#.