Автоматический запуск приложения java-web-start из C # и .NET, .WaitForExit ();не работает как хотелось - PullRequest
1 голос
/ 08 февраля 2011

Я использую приложение C # для запуска веб-приложения Java. Я хотел бы, чтобы мое приложение на C # знало, когда пользователь закрывает приложение Java. Я использую этот код:

var javaws = File.Exists(@"C:\Program Files\Java\jre6\bin\javaws.exe") ? @"C:\Program Files\Java\jre6\bin\javaws.exe" : @"C:\Program Files (x86)\Java\jre6\bin\javaws.exe";

var psi = new ProcessStartInfo(javaws, String.Format("http://{0}:/appstart.jnlp", hostAddress));

Process.Start(psi).WaitForExit();

Этот код успешно запускает Java-программу, однако вызывается WaitForExit() и немедленно возвращается. Я полагаю, что это потому, что «javaws» просто запускает другой процесс под названием «javaws», а затем «javaws» закрывается. Есть ли способ а) дождаться завершения всех дочерних процессов или б) дождаться определенного дочернего процесса?

-

Я обнаружил этот связанный пост: Действительно ли коды выхода javaws неработоспособны? , хотя ответ там предполагает, что 1.6.0_23 это исправило, я вижу точно такое же поведение на моей машине с Java 1.6.0_23. То, что я сейчас ищу, - это обходной путь, чтобы приведенный выше код работал, как и ожидалось. Мне нужно запустить этот файл jnlp, дождаться его завершения, а затем сделать дополнительный код в программе на C #. Приложение Java находится вне моего контроля, поэтому я не могу добавить туда функциональность.

-

Для всех, кому интересно, окончательное решение выглядит так:

var javaws = File.Exists(@"C:\Program Files\Java\jre6\bin\javaws.exe") ? @"C:\Program Files\Java\jre6\bin\javaws.exe" : @"C:\Program Files (x86)\Java\jre6\bin\javaws.exe";
var psi = new ProcessStartInfo(javaws, String.Format("http://{0}:/appstart.jnlp", hostAddress));
Process.Start(psi).WaitForExit();

var javaw = Process.GetProcessesByName("javaw");
javaw.Single(ja => ja.StartTime.Equals(javaw.Max(j => j.StartTime))).WaitForExit();

Это дает дополнительное преимущество, так как ожидает только самый последний запущенный процесс javaw, если на компьютере запущены другие веб-приложения java.

Ответы [ 2 ]

5 голосов
/ 15 февраля 2011

Вы можете получить нужный процесс из списка запущенных процессов, а затем дождаться его выхода:

var javaws = File.Exists(@"C:\Program Files\Java\jre6\bin\javaws.exe") ? @"C:\Program Files\Java\jre6\bin\javaws.exe" : @"C:\Program Files (x86)\Java\jre6\bin\javaws.exe";
var psi = new ProcessStartInfo(javaws, String.Format("http://{0}:/appstart.jnlp", hostAddress));

// make sure child process is already started
Process.Start(psi).WaitForExit();

foreach (Process p in Process.GetProcessesByName("javaw"))
{
   p.WaitForExit();
}

Чтобы убить не только javaw , но и все дочерние процессы, которые вам нужно получитьидентификатор процесса javaws и сравните его с родительским идентификатором всех запущенных процессов.Вот полный код: (метод расширения происходит от здесь )

class Program
{
    static void Main(string[] args)
    {
        var javaws = File.Exists(@"C:\Program Files\Java\jre6\bin\javaws.exe") ? @"C:\Program Files\Java\jre6\bin\javaws.exe" : @"C:\Program Files (x86)\Java\jre6\bin\javaws.exe";
        var psi = new ProcessStartInfo(javaws, String.Format("http://{0}:/appstart.jnlp", hostAddress));

        var parentProc = Process.Start(psi);
        parentProc.WaitForExit();

        foreach (Process p in Process.GetProcesses())
        {
            if (p.Parent().Id == parentProc.Id)
                p.WaitForExit();
        }
    }
}

public static class ProcessExtensions
{
    private static string FindIndexedProcessName(int pid)
    {
        var processName = Process.GetProcessById(pid).ProcessName;
        var processesByName = Process.GetProcessesByName(processName);
        string processIndexdName = null;

        for (var index = 0; index < processesByName.Length; index++)
        {
            processIndexdName = index == 0 ? processName : processName + "#" + index;
            var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
            if ((int)processId.NextValue() == pid)
            {
                return processIndexdName;
            }
        }

        return processIndexdName;
    }

    private static Process FindPidFromIndexedProcessName(string indexedProcessName)
    {
        var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
        return Process.GetProcessById((int)parentId.NextValue());
    }

    public static Process Parent(this Process process)
    {
        return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
    }
}
2 голосов
/ 08 февраля 2011

Глядя на некоторую документацию, кажется, что вы можете передать '-wait' в качестве параметра javaws, чтобы он дождался выхода из приложения.http://download.oracle.com/javase/1.5.0/docs/guide/javaws/developersguide/javaws.html

...