Java 需要一种以编程方式检查 Windows 服务状态的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/334471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Need a way to check status of Windows service programmatically
提问by Troy
Here is the situation:
这是情况:
I have been called upon to work with InstallAnywhere 8, a Java-based installer IDE, of sorts, that allows starting and stopping of windows services, but has no built-in method to query their states. Fortunately, it allows you to create custom actions in Java which can be called at any time during the installation process (by way of what I consider to be a rather convoluted API).
我被要求使用 InstallAnywhere 8,这是一个基于 Java 的安装程序 IDE,它允许启动和停止 Windows 服务,但没有内置方法来查询它们的状态。幸运的是,它允许您在 Java 中创建可以在安装过程中随时调用的自定义操作(通过我认为是相当复杂的 API)。
I just need something that will tell me if a specific service is started or stopped.
我只需要一些可以告诉我特定服务是启动还是停止的信息。
The IDE also allows calling batch scripts, so this is an option as well, although once the script is run, there is almost no way to verify that it succeeded, so I'm trying to avoid that.
IDE 还允许调用批处理脚本,因此这也是一个选项,尽管脚本一旦运行,几乎无法验证它是否成功,因此我试图避免这种情况。
Any suggestions or criticisms are welcome.
欢迎任何建议或批评。
采纳答案by Yuval
here's what I had to do. It's ugly, but it works beautifully.
这就是我必须做的。它很丑,但效果很好。
String STATE_PREFIX = "STATE : ";
String s = runProcess("sc query \""+serviceName+"\"");
// check that the temp string contains the status prefix
int ix = s.indexOf(STATE_PREFIX);
if (ix >= 0) {
// compare status number to one of the states
String stateStr = s.substring(ix+STATE_PREFIX.length(), ix+STATE_PREFIX.length() + 1);
int state = Integer.parseInt(stateStr);
switch(state) {
case (1): // service stopped
break;
case (4): // service started
break;
}
}
runProcess
is a private method that runs the given string as a command line process and returns the resulting output. As I said, ugly, but works. Hope this helps.
runProcess
是一个私有方法,它将给定的字符串作为命令行进程运行并返回结果输出。正如我所说,丑陋,但有效。希望这可以帮助。
回答by Aaron Digulla
During startup, create a file with File.deleteOnExit().
在启动期间,使用File.deleteOnExit()创建一个文件。
Check for the existence of the file in your scripts.
检查脚本中是否存在该文件。
回答by David
I have been dealing with installers for years and the trick is to create your own EXE and call it on setup. This offers good flexibility like displaying precise error messages in the event an error occurs, and have success-based return values so your installer knows about what happened.
我多年来一直与安装程序打交道,诀窍是创建自己的 EXE 并在安装时调用它。这提供了很好的灵活性,例如在发生错误时显示精确的错误消息,并具有基于成功的返回值,以便您的安装人员知道发生了什么。
Here's how to start, stop and query states for windows services (C++): http://msdn.microsoft.com/en-us/library/ms684941(VS.85).aspx(VB and C# offers similar functions)
以下是如何启动、停止和查询 windows 服务 (C++) 的状态:http: //msdn.microsoft.com/en-us/library/ms684941(VS.85 ) .aspx(VB 和 C# 提供类似的功能)
回答by borq
I have had some luck in the past with the Java Service Wrapper. Depending upon your situation you may need to pay in order to use it. But it offers a clean solution that supports Java and could be used in the InstallAnywhere environment with (I think) little trouble. This will also allow you to support services on Unix boxes as well.
过去我在 Java Service Wrapper 上有过一些运气。根据您的情况,您可能需要付费才能使用它。但它提供了一个干净的解决方案,支持 Java 并且可以在 InstallAnywhere 环境中使用(我认为)没有什么麻烦。这也将允许您支持 Unix 机器上的服务。
回答by borq
A shot in the dark but take a look at your Install Anywhere java documentation.
在黑暗中拍摄,但请查看您的 Install Anywhere java 文档。
Specifically,
具体来说,
/javadoc/com/installshield/wizard/platform/win32/Win32Service.html
/javadoc/com/installshield/wizard/platform/win32/Win32Service.html
The class:
班上:
com.installshield.wizard.platform.win32
Interface Win32Service
All Superinterfaces:
Service
The method:
方法:
public NTServiceStatus queryNTServiceStatus(String name)
throws ServiceException
Calls the Win32 QueryServiceStatus to retrieve the status of the specified service. See the Win32 documentation for this API for more information.
Parameters:
name - The internal name of the service.
Throws:
ServiceException
回答by RealHowTo
You can create a small VBS on-th-fly, launch it and capture its return code.
您可以即时创建一个小型 VBS,启动它并捕获其返回代码。
import java.io.File;
import java.io.FileWriter;
public class VBSUtils {
private VBSUtils() { }
public static boolean isServiceRunning(String serviceName) {
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set sh = CreateObject(\"Shell.Application\") \n"
+ "If sh.IsServiceRunning(\""+ serviceName +"\") Then \n"
+ " wscript.Quit(1) \n"
+ "End If \n"
+ "wscript.Quit(0) \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("wscript " + file.getPath());
p.waitFor();
return (p.exitValue() == 1);
}
catch(Exception e){
e.printStackTrace();
}
return false;
}
public static void main(String[] args){
//
// DEMO
//
String result = "";
msgBox("Check if service 'Themes' is running (should be yes)");
result = isServiceRunning("Themes") ? "" : " NOT ";
msgBox("service 'Themes' is " + result + " running ");
msgBox("Check if service 'foo' is running (should be no)");
result = isServiceRunning("foo") ? "" : " NOT ";
msgBox("service 'foo' is " + result + " running ");
}
public static void msgBox(String msg) {
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}
回答by Wil S
Here's a straignt C# / P/Invoke solution.
这是一个严格的 C#/P/Invoke 解决方案。
/// <summary>
/// Returns true if the specified service is running, or false if it is not present or not running.
/// </summary>
/// <param name="serviceName">Name of the service to check.</param>
/// <returns>Returns true if the specified service is running, or false if it is not present or not running.</returns>
static bool IsServiceRunning(string serviceName)
{
bool rVal = false;
try
{
IntPtr smHandle = NativeMethods.OpenSCManager(null, null, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
if (smHandle != IntPtr.Zero)
{
IntPtr svHandle = NativeMethods.OpenService(smHandle, serviceName, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
if (svHandle != IntPtr.Zero)
{
NativeMethods.SERVICE_STATUS servStat = new NativeMethods.SERVICE_STATUS();
if (NativeMethods.QueryServiceStatus(svHandle, servStat))
{
rVal = servStat.dwCurrentState == NativeMethods.ServiceState.Running;
}
NativeMethods.CloseServiceHandle(svHandle);
}
NativeMethods.CloseServiceHandle(smHandle);
}
}
catch (System.Exception )
{
}
return rVal;
}
public static class NativeMethods
{
[DllImport("AdvApi32")]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, ServiceAccess access);
[DllImport("AdvApi32")]
public static extern IntPtr OpenService(IntPtr serviceManagerHandle, string serviceName, ServiceAccess access);
[DllImport("AdvApi32")]
public static extern bool CloseServiceHandle(IntPtr serviceHandle);
[DllImport("AdvApi32")]
public static extern bool QueryServiceStatus(IntPtr serviceHandle, [Out] SERVICE_STATUS status);
[Flags]
public enum ServiceAccess : uint
{
ALL_ACCESS = 0xF003F,
CREATE_SERVICE = 0x2,
CONNECT = 0x1,
ENUMERATE_SERVICE = 0x4,
LOCK = 0x8,
MODIFY_BOOT_CONFIG = 0x20,
QUERY_LOCK_STATUS = 0x10,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000
}
public enum ServiceState
{
Stopped = 1,
StopPending = 3,
StartPending = 2,
Running = 4,
Paused = 7,
PausePending =6,
ContinuePending=5
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class SERVICE_STATUS
{
public int dwServiceType;
public ServiceState dwCurrentState;
public int dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public int dwCheckPoint;
public int dwWaitHint;
};
}
回答by Mohamed Samy
Based on the other answers I constructed the following code to check for Windows Service status:
根据其他答案,我构建了以下代码来检查 Windows 服务状态:
public void checkService() {
String serviceName = "myService";
try {
Process process = new ProcessBuilder("C:\Windows\System32\sc.exe", "query" , serviceName ).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
String scOutput = "";
// Append the buffer lines into one string
while ((line = br.readLine()) != null) {
scOutput += line + "\n" ;
}
if (scOutput.contains("STATE")) {
if (scOutput.contains("RUNNING")) {
System.out.println("Service running");
} else {
System.out.println("Service stopped");
}
} else {
System.out.println("Unknown service");
}
} catch (IOException e) {
e.printStackTrace();
}
}