1

我正在使用 C# 应用程序来启动 Java Web 应用程序。我希望我的 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”只是启动另一个名为“javaw”的进程,然后“javaws”关闭。有没有办法 A) 等待所有子进程也完成,或 B) 等待特定的子进程?

--

我发现了这个相关的帖子: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 Web 应用程序。

4

2 回答 2

5

您可以从正在运行的进程列表中获取所需的进程,然后等待退出:

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的进程 ID并将其与所有正在运行的进程的父 ID 进行比较。这是完整的代码:(扩展方法来自这里

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));
    }
}
于 2011-02-15T13:15:03.347 回答
2

查看一些文档,您似乎可以将“-wait”作为参数传递给 javaws 以使其等到应用程序退出。 http://download.oracle.com/javase/1.5.0/docs/guide/javaws/developersguide/javaws.html

于 2011-02-08T20:57:42.920 回答