4

I have the Following Code

log.Info("Starting jar");
System.Diagnostics.ProcessStartInfo si = new ProcessStartInfo(procName);
si.RedirectStandardOutput = true;
si.RedirectStandardError = true;
si.UseShellExecute = false;
si.CreateNoWindow = false;
si.WorkingDirectory = System.IO.Directory.GetParent(Application.ExecutablePath) + "\\" + Properties.Settings.Default.rootDirectory;

//start a new process for Client
Process process = new Process();
process.StartInfo = si;
process.Start();
String name = process.ProcessName;
javaClientProcessId = process.Handle;
int javaProcessID = process.Id;

by using this code I am getting cmd as process name where in taskManager it showing as java.exe. From code it give 5412 as process.id and 1029 as process.Handle where as 6424 is the process id of java.exe
Is there any other method from I can get same Process ID which is in the TaskManager

NOTE procName is the path to a Bat file in which it run a jar file.

EDITED

When I execute the following code it gives the error from process.Kill() line.

if (process != null)
{
     process.Kill();
     process.Close();
     process.Dispose();
}

Cannot process request because the process (6504) has exited

Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
madan
  • 773
  • 13
  • 38
  • Which process id do you want to get? the process id from cmd.exe or from java.exe? Your batch file starts cmd.exe which then starts java.exe. When you want to get the pid from java.exe don't use your batch file. – user743414 May 02 '14 at 11:17
  • when i kill java .exe from taskmanager it close the command Prompt.@ Thanks for reply – madan May 02 '14 at 11:19
  • Yes, because cmd.exe then ends. You start a batch and wait till batch ends --> cmd.exe started and execute batch and waits till it ends --> batch starts java.exe and wait till it ends. When you kill java.exe everything ends. :P – user743414 May 02 '14 at 11:20
  • any proper pid which kill the process of both java and cmd – madan May 02 '14 at 11:23
  • You could kill the cmd.exe process then the whole child process tree is killed too. Take a look at process explorer there you can see this tree. – user743414 May 02 '14 at 11:24
  • there is no cmd.exe process in my task manager – madan May 02 '14 at 11:28
  • Maybe you're right. It's possibe that cmd.exe just spawns and starts java.exe like you startting your batch. Your batch isn't a child process from your c# app. Then you need the java.exe process id to kill that process. To get it just execute in c# what you execute in your batch. – user743414 May 02 '14 at 11:29
  • please check I had edited my Question. – madan May 02 '14 at 11:43
  • Are you looking for the Process.GetProcessesByName method?: http://msdn.microsoft.com/en-us/library/vstudio/z3w4xdc9 – Simon Mourier May 05 '14 at 06:23
  • Get the KillProcessAndChildren() method from http://stackoverflow.com/questions/5901679/kill-process-tree-programatically-in-c-sharp (required a reference to System.Management) and call KillProcessAndChildren(javaProcessID); It will kill main process, and all its children. – user2316116 May 05 '14 at 17:00

3 Answers3

2

Here is my code snippet

try
{
    Process[] javaProcList = Process.GetProcessesByName("java");
    foreach (Process javaProc in javaProcList)
    {
        javaProc.Kill();
        javaProc.Close();
        javaProc.Dispose();

        Console.WriteLine("StopJar -Java Process Stopped ");
        log.Debug("StopJar -Java Process Stopped ");
     }
 }
 catch (Exception exp)
 {
     log.Error("StopJar - Unable to kill Java Process", exp);
     Console.WriteLine("Error while closing: " + exp.Message);
  }
madan
  • 773
  • 13
  • 38
0

You have to iterate all running process. Then kill all processes with the parentProcess is your cmd.exe Process. Here a code sample.

using System.Diagnostics;

using System.Runtime.InteropServices;

class Program {

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);

    [DllImport("kernel32.dll")]
    private static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32.dll")]
    private static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [StructLayout(LayoutKind.Sequential)]
    private struct PROCESSENTRY32 {
        public uint dwSize;
        public uint cntUsage;
        public uint th32ProcessID;
        public IntPtr th32DefaultHeapID;
        public uint th32ModuleID;
        public uint cntThreads;
        public uint th32ParentProcessID;
        public int pcPriClassBase;
        public uint dwFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szExeFile;
    }

    public static class helper {
        public static Process[] getChildProcesses(int parentProcessID) {
            var ret = new List<Process>();
            uint TH32CS_SNAPPROCESS = 2;

            IntPtr hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
            if (hSnapshot == IntPtr.Zero) {
                return ret.ToArray();
            }
            PROCESSENTRY32 procInfo = new PROCESSENTRY32();
            procInfo.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));
            if (Process32First(hSnapshot, ref procInfo) == false) {
                return ret.ToArray();
            }
            do {
                if ((int)procInfo.th32ParentProcessID == parentProcessID) {
                    ret.Add(Process.GetProcessById((int)procInfo.th32ProcessID));
                }
            }
            while (Process32Next(hSnapshot, ref procInfo));

            return ret.ToArray();
        }
        public static void killChildProcesses(int parentProcessID) {
            foreach (var p in getChildProcesses(parentProcessID))
                p.Kill();
        }
    }
0

1) Try to run java directly without bat file

Process p = new Process();  
ProcessStartInfo si = new ProcessStartInfo();  
si.Arguments = @"-jar app.jar";  
si.FileName = "java";  
p.StartInfo = si;  
p.Start();  
Console.WriteLine(p.Id);  
if (!p.HasExited) 
   p.Kill();  

Note, that if you do not want to use try..catch you'll have to use WaitForExit() or HasExited to wait for termination to complete, otherwise you might see that "process has exited" exception again.

More details How to kill a process without getting a "process has exited" exception?

2) If you should use a bat-file then get the KillProcessAndChildren() method from Kill process tree programmatically in C# (required a reference to System.Management) and call

KillProcessAndChildren(javaProcessID); 

It will kill main process, and all its children.

3) And of course, you can still use your original code and enumerate all processes by name

Process[] pp = Process.GetProcessesByName("java");
foreach (Process p in pp) 
    p.Kill();

pp = Process.GetProcessesByName("cmd");
foreach (Process p in pp)
    p.Kill();

but if you have multiple processes of java/cmd, this will delete all of them which might be not a good idea.

Community
  • 1
  • 1
user2316116
  • 6,726
  • 1
  • 21
  • 35