从c#关闭java进程(在Windows上)

时间:2014-12-03 12:12:37

标签: java c# windows

我使用

从c#启动了一个java程序
...
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = "C:\\path\\to\\jar\\";
startInfo.FileName = "C:\\Windows\\Sysnative\\java.exe";
startInfo.Arguments = "-jar JavaProg.jar";
process = new Process();
process.StartInfo = startInfo;
try {
    process.Start();
}
...

然后该过程持续运行,直到我希望它停止。 java程序有一个关闭钩子,应该能够捕获正常的kill信号。例如,如果我从bat脚本运行jar,然后在cmd窗口中按Ctrl + c将触发关闭挂钩,但关闭cmd窗口将终止进程而不触发关闭挂钩(类似于任务管理器中的End Process) )。

所以为了从C#停止java程序,我尝试了:

process.CloseMainWindow();

process.Kill();

CloseMainWindow方法对java进程没有影响,Kill终止它而不触发关闭钩子。那么我该怎样做才能从C#代码中优雅地关闭java程序? [我是否需要在我的Java程序中进行修改以拦截CloseMainWindow信号?有没有办法模仿C#的cmd窗口上Ctrl + c的行为?我必须在C#和Java代码之间创建一些通信路径,例如管道或套接字吗?]

P.S。 C#代码只是java代码的包装器,以便在Windows上作为服务运行它(我不能为此目的使用RunAsService等现有工具)。

该计划的一般说明: 我的java程序不会创建任何窗口。它有几个线程,主要是在循环中运行,只是等待连接,另一个线程在传入连接上执行特定任务,另一个线程从Web服务器定期更新,并且有关闭钩子。通常,程序从命令提示符(或linux上的终端)运行,并且仅在第一次加载时才接受用户输入,之后可以在没有更多用户输入的情况下再次运行它。程序将日志输出到文件。我的关机钩:

...
shutdownHook = new ShutdownHook();
Runtime.getRuntime().addShutdownHook(shutdownHook);
...
class ShutdownHook extends Thread {
    public void run() {
        // log the shutdown is started
        // terminate classes
        // interrupt and join the other threads
        // log the shutdown is done
    }
}

3 个答案:

答案 0 :(得分:0)

这会尝试关闭所有记事本窗口。请注意,如果要保存,最终会收到提示。

  [DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
  static extern IntPtr SendMessage( IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam );

  static uint WM_CLOSE = 0x10;

  public void CloseWindow( IntPtr hWindow )
  {
     SendMessage( hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero );
  }

  public void test_close()
  {
     foreach ( System.Diagnostics.Process p in System.Diagnostics.Process.GetProcessesByName( "notepad" ) )
     {
        CloseWindow(p.MainWindowHandle);
     }
  }

答案 1 :(得分:0)

执行此操作的最佳方法是让您的C#程序获取Java程序的stdin句柄。这样,C#程序可以随时向Java程序发送消息,Java程序可以监听一条消息,要求它死掉。

这样做的好处是您不必担心关闭挂钩:程序可以在收到关闭消息时执行所需的任何处理。它也更加灵活:如果以后,您希望C#程序发送其他控制消息,可以轻松添加。

在Java方面,您需要一个单独的线程打开System.in并从中读取,并在收到正确的消息时执行您需要的任何关闭。

在C#方面,看起来好像你想要

startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;

然后当你想发送信息时:

process.StandardInput.WriteLine(...some message...);

(但我是一名Java编码员,所以我不确定我是否在这里获得了C#。)

答案 2 :(得分:0)

您需要使用GenerateConsoleCtrlEvent

您可以使用P / Invoke调用此方法。

这将允许您生成一个Ctrl + C事件,Java程序将以与在命令窗口中按Ctrl + C时相同的方式处理该事件。

注意:但是,只有在进程有控制台的情况下,这才有效。 Java在启动时初始化Ctrl + C处理程序,因此您需要确保程序在启动时具有控制台。您可以通过调用调用程序中的AllocConsole来创建控制台,并且java程序将继承控制台。