I have to 2 process excel. For example:
1) example1.xlsx
2) example2.xlsx
How to kill first "example1.xlsx"?
I use this code:
foreach (Process clsProcess in Process.GetProcesses())
if (clsProcess.ProcessName.Equals("EXCEL")) //Process Excel?
clsProcess.Kill();
That kill a both.
I wanna kill just one...
Thank you.
The ProcessMainWindow Title will do it for you, it appends "Microsoft Excel - " to the name of the file:
So essentially (quick code):
private void KillSpecificExcelFileProcess(string excelFileName)
{
var processes = from p in Process.GetProcessesByName("EXCEL")
select p;
foreach (var process in processes)
{
if (process.MainWindowTitle == "Microsoft Excel - " + excelFileName)
process.Kill();
}
}
Use:
KillSpecificExcelFileProcess("example1.xlsx");
Edit: Tested and verified to work.
kd7's post is an awesome answer and works well, just two things to add,
MainWindowTitle format is - "Filename.xlsx - Excel"
If your excel document is not visible then your MainWindowTitle will be ""
using the "" for MainWindowTitle will kill all zombie excel process'.
If your current code is working, this amendment should kill the first process it finds with the name "EXCEL".
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL"))
{
clsProcess.Kill();
break;
}
}
If you want to kill a specific process, you're going to have to give a bit more information.
Excel will always be a single process, AFAIK. The same process/windows opens multiple documents inside it. What you want to do is use Excel automation to CLOSE the document you want to. Perhaps this will get you started. http://support.microsoft.com/kb/302084
Hope this helps.
Copy and paste this. Its done!
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
You need to check file handles, that are opened by process and then kill it.
How to check which file handles process is holding: How do I get the list of open file handles by process in C#?
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL") && HasFileHandle(fileName, clsProcess))
{
clsProcess.Kill();
break;
}
}
Try getting the main window title
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL")&& clsProcess.MainWindowTitle =="example")
{
clsProcess.CloseMainWindow();
break;
}
}
just did a quick search on Google, try Process.MainWindowTitle() to get the title of the Excel process, and decide which one is that you want to kill.
I am not sure about this method, but hope this will help:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowtitle.aspx
Use below logic to prevent Zombie Excel processes in Task Manager
List<int> GetAllExcelProcessID()
{
List<int> ProcessID = new List<int>();
if (currentExcelProcessID == -1)
{
List<System.Diagnostics.Process> currentExcelProcessList = System.Diagnostics.Process.GetProcessesByName("EXCEL").ToList();
foreach(var item in currentExcelProcessList)
{
ProcessID.Add(item.Id);
}
}
return ProcessID;
}
int GetApplicationExcelProcessID(List<int> ProcessID1, List<int> ProcessID2)
{
foreach(var processid in ProcessID2)
{
if (!ProcessID1.Contains(processid)) { currentExcelProcessID = processid; }
}
return currentExcelProcessID;
}
void KillExcel()
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetProcessById(currentExcelProcessID);
process.Kill();
}
List<int> ProcessID1 = GetAllExcelProcessID();
excel = new Excel.Application();
List<int> ProcessID2 = GetAllExcelProcessID();
currentExcelProcessID = GetApplicationExcelProcessID(ProcessID1, ProcessID2);
In the namespace section add this using statement.
using System.Diagnostics;
This example instantiated Excel with this:
_Application excel = new _Excel.Application();
This method kills the right Excel task by using the window handle.
public void Kill()
{
Int32 ExcelHwnd = excel.Hwnd;
Process[] localExcel = Process.GetProcessesByName("EXCEL");
foreach (Process Pgm in localExcel)
{
// xlMinimized keeps the screen from flashing when the user interface is made
// visible with the excel.visible needed to set the MainWindowHandle
excel.WindowState = XlWindowState.xlMinimized;
excel.Visible = true;
if ((Pgm.ProcessName == "EXCEL") && (ExcelHwnd == Pgm.MainWindowHandle.ToInt32()))
{
Pgm.Kill();
}
}
}
This worked without fail.
Related
I've build a Windows service with C# which get all running applications on my computer (Notepad,...). I've tryed this following code but it doesn't work :
Thank you all for your help!
Process[] processes = Process.GetProcesses();
using (TextWriter tw = new StreamWriter(#"C:\Users\Public\Documents\Info.txt"))
{
foreach(Process p in processes)
{
if(!String.IsNullOrEmpty(p.MainWindowTitle))
{
tw.WriteLine(p.MainWindowTitle);
}
}
}
That's why you are checking MainWindowTitle on your code. You have to know MainWindowTitle has value just for those processes which they have GUI like notepad or skype or ...
To identify all the process name it's better to check ProcessName property to get the process name.
So I recommend you to change your code like this:
using (TextWriter tw = new StreamWriter(#"C:\Users\Public\Documents\Info.txt"))
{
foreach (Process p in processes)
{
if (!String.IsNullOrEmpty(p.ProcessName))
{
var processTitle= !string.IsNullOrEmpty(p.MainWindowTitle) ? p.MainWindowTitle: "N/A";
tw.WriteLine(string.Format("Process Name: {0} \t\t Process GUI Title:{1}",p.ProcessName, processTitle));
}
}
}
I have the following code snippet in C# to open a PowerDesigner Model and I would like to close / exit the PowerDesigner application instance but I do not know how?
PdCommon.Application pdApplication = null;
try{
//Creating PD Application object...
pdApplication = new PdCommon.Application();
//Opening the relevant models of a dedicated directory
String[] files = System.IO.Directory.GetFiles(ldmSourceDirectory);
foreach (String curFile in files){
if(curFile.EndsWith(".cdm")){
pdApplication.OpenModel(#curFile, PdCommon.OpenModelFlags.omf_DontOpenView);
}
}
//Doing some operations...
}finally{
if (pdApplication != null){
//Closing models
foreach (PdCDM.Model curPDModel in pdApplication.Models){
curPDModel.Close(false);
}
//But how can I close the application?
pdApplication = null;
}
}
As commented by pascal, you should close the model, the workspace, and then, kill the process. DonĀ“t forget to add PdWSP (workspace model) reference, and System.Diagnostics using declaration. The process name may be different depending on the PD version.
PdCommon.Application pd = new PdCommon.Application();
var pdm = (PdPDM.Model)pdApplication.OpenModel(fileName);
var wsp = (PdWSP.Workspace)pdApplication.ActiveWorkspace;
pdm.Close(false);
wsp.Close(true);
pd = null;
// close powerdesigner processes
foreach(var process in Process.GetProcesses().Where(pr => pr.ProcessName == "PdShell16"))
{
process.Kill();
}
I write my app in C# and I have one problem. I have some executable file for example "spotify.exe". This app is running and i have to get title of window.
I am new in C# and I can't do this.
Could you help me?
Use the MainWindowTitle property of the Process class :
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
if (!string.IsNullOrEmpty(process.MainWindowTitle))
{
Console.WriteLine("Window title of {0} : {1}", process.ProcessName, process.MainWindowTitle);
}
}
EDIT:
Note that processes without a Form (e.g. console applications, background processes) will return an empty string for their MainWindowTitle .
Get the process - Process [] localByName = Process.GetProcessesByName("notepad");
Get the title - string Title = process.MainWindowTitle
As an example, to get the Spotify window title;
var procs = Process.GetProcessesByName("Spotify");
foreach (var p in procs)
{
if (!string.IsNullOrEmpty(p.MainWindowTitle))
{
Label1.Text = p.MainWindowTitle;
}
}
I have code which starts Word application instance as follows
Microsoft.Office.Interop.Word.Application app = new Microsoft.Office.Interop.Word.Application();
app.Caption = "abcd_" + DateTime.Now.Ticks.ToString();
I now need to know process id of the word instance that was started.
I cannot use FindWindow to get window handle and GetWindowThreadProcessId to get process id from handle as the code does not work on Windows server 2008.
I get all word processes by using Process.GetProcessesByName("WINWORD").
Is there any property of Process which can give me value that we set in app.Caption ?
If not, is there any other property of Word.Application which I can set and later on read from Process array to identify correct instance of Word ?
You Could use the Process.MainWindowTitle property to judge if the process is by your code.
But there's some limitation:
When you using new Microsoft.Office.Interop.Word.Application(), the word windows is not visible by default. When it's hidden, the Process.MainWindowTitle is empty. So you show set it visible before you get the Pid.
After you open a document, the MainWindowTitle will change to the document's file name.
Here's my code:
static void Main(string[] args)
{
string uniCaption = Guid.NewGuid().ToString();
Word.Application oWordApp = new Word.Application();
oWordApp.Caption = uniCaption;
oWordApp.Visible = true;
Process pWord = getWordProcess(uniCaption);
//If you don't want to show the Word windows
oWordApp.Visible = false;
//Do other things like open document etc.
}
static Process getWordProcess(string pCaption)
{
Process[] pWords = Process.GetProcessesByName("WINWORD");
foreach (Process pWord in pWords)
{
if (pWord.MainWindowTitle == pCaption)
{
return pWord;
}
}
return null;
}
What about that (untestet):
Updated
Word.Application wdapp;
try
{
Process wordProcess = System.Diagnostics.Process.Start("Path to WINWORD.EXE");
wdApp = (Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
}
catch (COMException)
{
Type type = Type.GetTypeFromProgID("Word.Application");
wdapp = System.Activator.CreateInstance(type);
}
The wdApp should be the started word.
And you get the process id through wordProcess instance.
I write an application that starts a 3rd party program that downloads a media stream from a tv channel on my program. The program I am using is rtmpdump.exe. They run as independent processes like this:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = path + rtmpdump;
startInfo.Arguments = rtmpdump_argument;
startInfo.WorkingDirectory = path;
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process p = Process.Start(startInfo);
But I would like to name these processes, so if my program crashes or has to be restarted, then I can check the names of the current processes to see if for example there is one called "BBC World - News at 7". Something like that to identify which has already been started and is currently running. Is it possible? I can't find a way to set a friendly name.
Extending what Alexei said - you could create a Dictionary< int, string > to keep track of the process ID / descriptive name that you create. Maybe you should write this out to a file in case your program crashes - but you'd need some special startup handling to deal with processes exiting.
On startup you'd want to read in the file, and check current processes to see if they match with what you have, and remove any processes that no longer exist (wrong process id or exe name). You might want to do that every time you create a new process and write to the file.
You can't change process names, but instead you can:
use Process.Id to identify processes (Id: "...system-generated unique identifier of the process...")
get process command line and see if there anything interesting (may need some PInvoke / WMI for that - How to read command line arguments of another process in C#?).
Here is some code that you could use.
public class ProcessTracker {
public Dictionary<int, string> Processes { get; set; }
public ProcessTracker() {
Processes = new Dictionary<int, string>();
}
public void AddProcess(Process process, string name) {
Processes.Add(process.Id, name);
}
//Check if what processes are still open after crash.
public void UpdateProcesses() {
List<Process> runningProcesses =
Process.GetProcesses().ToList();
Processes = Processes
.Where(pair => runningProcesses
.Any(process => process.Id == pair.Key))
.ToDictionary(pair => pair.Key, pair => pair.Value);
}
//Use this to see if you have to restart a process.
public bool HasProcess(string name) {
return Processes.Any(pair => pair.Value != name);
}
//Write the file on crash.
public void ReadFile(string path) {
if (!(new FileInfo(path).Exists))
return;
using (StreamReader reader = new StreamReader(path)) {
foreach (string line in reader.ReadToEnd()
.Split(new[] {"\n"}, StringSplitOptions.RemoveEmptyEntries)) {
string[] keyPair = line.Split(',');
Processes.Add(int.Parse(keyPair[0]), keyPair[1]);
}
}
}
//Read the file on startup.
public void SaveFile(string path) {
using (StreamWriter writer = new StreamWriter(path, false)) {
foreach (KeyValuePair<int, string> process in Processes) {
writer.WriteLine("{0},{1}",
process.Key, process.Value);
}
}
}
}
Writing the process information to a file (or a memory mapped file) might be the way to go;
However, you could also look into windows messaging. i.e. send a message to each process; and have them reply with their "internal name".
Basically you have everything listen in on that queue; You first send a command that orders the other process to report their internal name, which they then dump into the message queue along with their own process id;
See MSMQ
I had the same question to myself, for my solution created a new class -
MyProcess which inherits from Process and added a property - ProcessId.
In my case I store the ProcessId on a db which is acossiated to other data. Based on the status of the other data I decide to kill the process.
Then I store process on a dictionary which can be passed to other classes if needed where can be access to kill a process.
So when I decide to kill a process, I pull the process from the dictionary by ProcessId and then kill it.
Sample below:
public class Program
{
private static Dictionary<string, MyProcess> _processes;
private static void Main()
{
// can store this to file or db
var processId = Guid.NewGuid().ToString();
var myProcess = new MyProcess
{
StartInfo = { FileName = #"C:\HelloWorld.exe" },
ProcessId = processId
};
_processes = new Dictionary<string, MyProcess> {{processId, myProcess}};
myProcess.Start();
Thread.Sleep(5000);
// read id from file or db or another
var pr = _processes[processId];
pr.Kill();
Console.ReadKey();
}
}
public class MyProcess : Process
{
public string ProcessId { get; set; }
}