I need the process ID for a program that is already running on the computer. How would I go about doing this? (The process isn't started from Process.Start())
Use GetProcessesByName or just GetProcesses with a bit of LINQ, depending on how you intend to identify the program.
using System;
using System.Diagnostics;
using System.ComponentModel;
void Example()
{
// Get all processes running on the local computer.
var localProcesses = Process.GetProcesses();
//Get all processes with a name that contain "Foo" in the title
var fooProcess = localProcesses.Where(p => p.MainWindowTitle.Contains("Foo"));
// Get all instances of Notepad running on the local computer.
var notepad = Process.GetProcessesByName("notepad").Single();
}
Once you have the Process object, you can get its ID with the Id property.
var id = process.Id;
Related
I try to close running user apps (Application Programs) in windows by C# like word, forxitReader, whatsApp , etc.
I try to make a desktop App to secure an online exam like Safe Exam Browser.
My senario is:
1 - get the process of them only as a list (not System programs.)
2 - Kill them by Process.kill();
But I don't know how to do the first step.
How can I get a list of these programs only?
I understand you need to check the process owner to know if its a system or non-system process, and to my knowledge there is no way to get the process owner via .NET api, but you can get active process and their owner in powershell via
Get-Process -IncludeUserName
Now doing this in C# is a bit tricky because out of the box, the Process class is lacking and making CLI calls is complicated, but I was able to write this solution with only Cake.Powershell nuget package.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management.Automation;
using (var powershell = PowerShell.Create())
{
List<string> illegalProcesses = new List<string>() { "dota2" };
powershell.AddScript("Get-Process -IncludeUserName");
var results = powershell.Invoke();
var nonSystemResults = results.Where(x => !x.Properties["Username"].Value.ToString().StartsWith("NT AUTHORITY"));
foreach (var result in results)
{
var processOwner = result.Properties["Username"].Value as string;
if (processOwner != null && !processOwner.StartsWith("NT AUTHORITY"))
{
var processName = result.Properties["Name"].Value as string;
if (illegalProcesses.Contains(processName))
{
var processID = result.Properties["ID"].Value as int?;
var doomedProcess = Process.GetProcessById(processID.Value);
doomedProcess?.Kill();
}
}
}
}
I've made the assumption that system processes are the ones owned by users that start with NT AUTHORITY but you might find for your particular use case you want different filters. That said there are tons of properties you can get on processes that should allow you to write your own filters.
I want to make a C# program that deletes a file in system32. The program can delete a file in an normally accessed area such as the desktop but won't find a file in system32, how would I give the program access to system32?
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string filepath = #"C:\Windows\System32\New.txt";
if (File.Exists(filepath))
{
File.Delete(filepath);
}
else
{
Console.WriteLine("File not found");
Console.ReadLine();
}
}
}
}
To begin with you SHOULD NOT delete files from system 32 folder, these files usually belong to OS and should not be tempered with.
Anyways ! i would not ask why you have this requirement but windows User Account Control (UAC) will not allow you perform this operation just like that, You will need to elevate the permissions and take ownership of the file as shown below :
//take ownership of the file, code assumes file you want to delete is toBeDeleted.txt
ProcessStartInfo processInfo = new ProcessStartInfo("cmd.exe", #"/k takeown /f C:\Windows\System32\toBeDeleted.txt && icacls C:\Windows\System32\toBeDeleted.txt /grant %username%:F");
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
processInfo.FileName = fileName;//path of your executable
try
{
Process.Start(processInfo);
// a prompt will be presented to user continue with deletion action
// you may want to have some other checks before deletion
File.Delete(#"C:\Windows\System32\toBeDeleted.txt");
return true;
}
catch (Win32Exception)
{
//Do nothing as user cancelled UAC window.
}
When you run this a prompt will be presented to user to confirm this action, if you want to avoid this you'll need to run your entire host process with elevated permissions by Creating and Embedding an Application Manifest (UAC) to require the 'highestAvailable' execution level: this will cause the UAC prompt to appear as soon as your app is started, and cause all child processes to run with elevated permissions without additional prompting.
Hope this helps !
I am sending messages to a listener windows service. Within the message is a process id. I want to use the process id to attach it to my windows service in order to access a folder on the server.
I cannot see how to set a process id only get one
int nProcessID = Process.GetCurrentProcess().Id;
You can not assign an ID to a process, it is only set by the operating system. You can however search for one by name:
int yourProcess = Process.GetProcessesByName( "YourListener.exe" )[0].Id;
Enhancing a bit the answer of #BillyDvd, I suggest you getting the name of your process instead of hardcoding it, this way, you can change it in your project structure safely:
var name = Process.GetCurrentProcess().ProcessName; // always fix, like "myapp.rms"
var myProcess = Process.GetProcessesByName(name)[0].Id; // variable, given new by Windows OS on every start of your app: 44580, 36960, 38184, ...
I'm using the TraceEvent library to capture ETW traces, but I'm not able to determine the name of the process that caused an event.
Here is what I have so far:
var session = new TraceEventSession(sessionName, null);
session.EnableProvider(MyEventSource.Log.Guid, TraceEventLevel.Informational,
options: TraceEventOptions.Stacks);
Task.Delay(1000).ContinueWith(t => session.Stop()); // for testing, deal with it (⌐■_■)
var src = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session);
TraceLog.CreateFromSource(src, etlxFile, null);
var log = TraceLog.OpenOrConvert(etlxFile);
var process = log.Events.First().ProcessName;
// breakpoint
When the breakpoint at the end is hit, process is "". ProcessID is a proper PID, but that's the only useful information I could find from the processes in the log.
I expected process names to be captured by the log. Am I doing something wrong, or is this API just not available on my OS (Windows 7)?
I truly believe that process name is not being captured by the ETW log. Etw system event contains only process ID field. Although TraceEvent library declares this one as a part of TraceEvent, this one actually is being populated based on executable image filename and process ID, which is implemented differently for all 4 TraceEventSource implementations.
Another observation is that I was never able to have this one populated (my OS is Windows 8.1).
The simple repro is to use SimpleEventSourceMonitor sample from Microsoft TraceEvent Library Samples package.
If you suspect that this is an issue, then it is better ask its owners Vance Morrison and Cosmin Radu.
This can be done by enabling the kernel provider, and then maintaining a lookup of process id to process name. Here's a rough example - no error checking, but you get the idea.
// create a lookup collection for future use
var pidToProcessName = new Dictionary<int, string>();
var session = new TraceEventSession(...);
// enable the kernel provider - note! this most come first
session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
...
session.Source.Kernel.ProcessStart += ProcessStart;
session.Source.Dynamic.All += TraceEvent;
...
session.Source.Procces();
void ProcessStart(ProcessTraceData obj)
{
if(obj.OpCode == TraceEventOpcode.Start)
{
pidToProcessName[obj.ProcessID] = obj.ProcessName;
}
}
void TraceEvent(TraceEvent obj)
{
// pull the process name from our lookup
var processNameOfEvent = pidToProcessName[obj.ProcessID];
}
I'm trying to extract text from a Creo 2.0 Window Title. The text will be used to create a folder titled the same as the part number that is opened and in the Window Title. The issue I have is that I can iterate through, and find all the Window Titles of open applications using process.MainWindowTitle, but for some reason, Creo doesn't have a Main Window Title. It also doesn't have the text using any other "process." functions. I figure that the information has to be somewhere if it's in the title bar like other normal programs, but I'm just not going at it the right way. Is there another process using C# that I can use to try and accomplish this?
Let me know if I need to give any other information. Thank you for the help!
It may not necessarily be available via the Process object. Explorer.exe, for example, has the current folder name in the title bar but this is not the MainWindowTitle. Another option is to use UI Automation to inspect the UI and report the window's title. Depending on which version of .Net you are targeting, you can reference UiaComWrapper (which has more information and better perf, I believe) or UIAutomationClient and UIAutomationTypes. A short sample that prints all window titles:
using System;
using System.Diagnostics;
using System.Windows.Automation;
static void Main(string[] args)
{
var windows = AutomationElement.RootElement.FindAll(TreeScope.Descendants,
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
foreach(AutomationElement window in windows)
{
var props = window.Current;
var proc = Process.GetProcessById(props.ProcessId);
Console.WriteLine("{0} {1} {2}", props.ProcessId, proc.ProcessName, props.Name);
}
}
Note that you need to run this elevated if you want to get information on elevated processes.