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).
Related
So I have a piece of software I'm hooking into. My problem is that the software has a launcher-like home window. From that home I click "Start" and it opens a second process with the same name. In my task manager they are identical in processes/details.
My program has to hook into this second process and I can only hook after the process exists. There's no way to launch it directly without the home window.
They both have randomized PID's each time. I can't figure out a way to differentiate the two processes. If my program hooks the wrong one it will freeze up the software.
p = Process.GetProcessesByName("programName");//This is specifically just the window name so that we can interact with the client using keystrokes.
System.Diagnostics.Debug.WriteLine("Attempting to hook into the program...");
process = Process.GetProcessesByName("programName").ToList().FirstOrDefault();
if (process == null) {
System.Diagnostics.Debug.Write("Hook failed! Make sure the program is open.");
Application.Exit();
}
if (process != null) {
mreader.ReadProcess = process;//Set the process we want to read to be the one we just got in the above line.
mreader.OpenProcess();//Gets the handle of the process and hook in.
for (int i = 0; i < process.Modules.Count; i++) {
System.Diagnostics.Debug.WriteLine("Module " + i + ": " + process.Modules[i].ModuleName);
if (process.Modules[i].ModuleName == "programcore.dll") {
System.Diagnostics.Debug.WriteLine("programcore.dll found at Module " + i);
iCounter = i;//Set the number programcore is on to our counter so we can hook in each time, even if it moves.
System.Diagnostics.Debug.WriteLine("Success!");
break;
}
}
}
This is how I'm hooking into the client to read/write the memory. Unfortunately both processes have the programcore.dll that I need so I don't know how to tell them apart.
I want to get information about all currently active media playbacks. I found a way to read out all media sessions here:
using Windows.Media.Control;
namespace ConsoleApp1 {
public class Program {
[STAThread]
static void Main(string[] args) {
var gsmtcsm = GlobalSystemMediaTransportControlsSessionManager.RequestAsync().GetAwaiter().GetResult().GetSessions();
foreach (var session in gsmtcsm) {
var mediaProperties = session.TryGetMediaPropertiesAsync().GetAwaiter().GetResult();
Console.WriteLine("{0} - {1}", mediaProperties.Artist, mediaProperties.Title);
}
Console.ReadKey();
}
}
}
Now I want to get the corresponding programs for these sessions. Also, I want to get the window of the program if it exists. My goal is to programmatically move the window if it exists to another screen. The program handle is just used as an identifier.
For example:
I open a random .mp4 file. By default, it is played by Windows Films & TV. Now I want to get the session, program, and window (Films & TV has a window) and move it to another screen (by code)
Another example:
I watch a video on Youtube. Now I want to get the window of the browser I opened Youtube in.
You can find the main window for the app that is running the media session with
var gsmtcsm = GlobalSystemMediaTransportControlsSessionManager.RequestAsync().GetAwaiter().GetResult().GetSessions();
foreach (var session in gsmtcsm)
{
string modelId = session.SourceAppUserModelId;
// Get all processes
Process[] processlist = Process.GetProcesses();
// Create and array to hold matched processes
List<Process> modelProcesslist = new List<Process>();
// Using a direct filter on the Process.GetProcesses() call will raise an exception, you will need to cycle through them
// to find a process that has the same filename as reported by the media session
// The filename may be different to the process name
foreach (Process p in processlist)
{
try
{
if (p.MainModule.FileName.Contains(modelId) && p.MainWindowHandle != IntPtr.Zero)
{
modelProcesslist.Add(p);
}
}
catch(System.Exception)
{
// Couldn't look at the MainModule of this process, move on
}
}
foreach (Process p in modelProcesslist)
{
IntPtr windowHandle = p.MainWindowHandle;
// The main window(s) for apps that have the same name as the source app for the media session
}
}
One big issue will be if the main window is owned by chrome.exe (or any tabbed browser), then the media player is in one of the sub tabs, finding content within a tab of the browser is a whole new level of headache.
Also if you have multiple browser windows open, they will all have the same executable name and get picked up by the above code.
If the app is a dedicated media player, you should be able to use the handle to move the window.
This question already has answers here:
How to get parent process in .NET in managed way
(7 answers)
Closed 5 years ago.
I need to get the name of the program that launched a console application i am making in Visual studio. Any ideas on how i can do this?
I am doing this so i can see for how long robots in out company is running and when they are running.
You can get the parent process of some other process like this:
public static Process GetParentProcess(Process process)
{
string query = "SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = " + process.Id;
using (ManagementObjectSearcher mos = new ManagementObjectSearcher(query))
{
foreach (ManagementObject mo in mos.Get())
{
if (mo["ParentProcessId"] != null)
{
try
{
var id = Convert.ToInt32(mo["ParentProcessId"]);
return Process.GetProcessById(id);
}
catch
{
}
}
}
}
return null;
}
Inside your console app you would use it like
var parent = GetParentProcess(Process.GetCurrentProcess());
From this you can get all information about parent process.
If you can modify the call of the console application, you can give the program name as an argument.
For example my application creates mutex's like so:
MyApplication\\{UserName}
and then my updater program (that updates this application) needs to check whether this has been created or not but it doesn't know the username.
I have the code:
string mutexString = "MyApplication\\User1"
bool isNew;
var mutex = new Mutex(true, mutexString , out isNew);
if(isNew)
{
//Run my program
}
This works fine if I know the username but I would like to know if it is possible for this to work with wildcards?
So from the comments I get the sense that this is impossible so a better solution might be to check the running processes which I achieved like so:
foreach (var process in Process.GetProcesses())
{
if (process.MainWindowTitle.IndexOf("MyApp",StringComparison.InvariantCultureIgnoreCase) >= 0)
{
isNew = false;
}
}
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