I have a Problem regarding the Telegram API
Whenever I do a RpcCall, it always give me a TimeoutException except when I do a NonAuth Call.
I can SignIn with a Number already and I set Authenticated to true in my AbsApiState and still can only do NonAuth Calls
Here is my Code:
private void startApi() throws Exception
{
api = new TelegramApi(new MyApiStorage(Moin.config.getProp("useTest").equalsIgnoreCase("true") ? true : false),
new AppInfo(Moin.api_id, "console", "???", "???", "en"),
new ApiCallback()
{
#Override
public void onAuthCancelled(TelegramApi arg0)
{
System.out.println("AuthCancelled");
}
#Override
public void onUpdate(TLAbsUpdates update)
{
System.out.println("Updated | " + update.getClass());
}
#Override
public void onUpdatesInvalidated(TelegramApi arg0)
{
System.out.println("Updatefailed");
}
});
TLConfig config = null;
config = api.doRpcCallNonAuth(new TLRequestHelpGetConfig());
if(config != null)
api.getState().updateSettings(config);
else
throw new Exception("config is null, could not update DC List");
login();
}
private void login() throws IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
TLSentCode code = null;
String defaultNumber = Moin.config.getProp("phoneNumber");
System.out.println("Enter a Phone Number (Default ist " + defaultNumber + "):");
String number = reader.readLine();
if(number.equals(" "))
number = defaultNumber;
System.out.println("Sending to " + number + " ...");
try
{
code = api.doRpcCallNonAuth(new TLRequestAuthSendCode(number, 0, Moin.api_id, Moin.api_hash, "en"));
}
catch (RpcException e)
{
if (e.getErrorCode() == 303)
{
int destDC = 0;
if (e.getErrorTag().startsWith("NETWORK_MIGRATE_"))
{
destDC = Integer.parseInt(e.getErrorTag().substring("NETWORK_MIGRATE_".length()));
}
else if (e.getErrorTag().startsWith("PHONE_MIGRATE_"))
{
destDC = Integer.parseInt(e.getErrorTag().substring("PHONE_MIGRATE_".length()));
}
else if (e.getErrorTag().startsWith("USER_MIGRATE_"))
{
destDC = Integer.parseInt(e.getErrorTag().substring("USER_MIGRATE_".length()));
}
else
{
e.printStackTrace();
}
api.switchToDc(destDC);
code = api.doRpcCallNonAuth(new TLRequestAuthSendCode(number, 0, Moin.api_id, Moin.api_hash, "en"));
}
else
e.printStackTrace();
}
String hash = code.getPhoneCodeHash();
System.out.println("Please Enter the Code:");
String smsCode = reader.readLine();
TLAuthorization auth = api.doRpcCallNonAuth(new TLRequestAuthSignIn(number, hash, smsCode));
api.getState().setAuthenticated(api.getState().getPrimaryDc(), true);
//This is where I get the Error
TLExportedAuthorization test = api.doRpcCall(new TLRequestAuthExportAuthorization(api.getState().getPrimaryDc()));
System.out.println(test.getId());
FileOutputStream stream = new FileOutputStream(Paths.get("").toAbsolutePath().toString() + File.separator + "test.txt");
try
{
stream.write(test.getBytes().getData());
}
finally
{
stream.close();
}
TLState state = api.doRpcCall(new TLRequestUpdatesGetState());
System.out.println(state.getDate() + " | " + state.getPts() + " | " + state.getQts() + " | " + state.getUnreadCount());
TLAbsUser user = auth.getUser();
}
And here the Error:
TelegramApi#1001:Timeout Iteration
TelegramApi#1001:RPC #3: Timeout (14999 ms)
TelegramApi#1001:Timeout Iteration
org.telegram.api.engine.TimeoutException
at org.telegram.api.engine.TelegramApi.doRpcCall(TelegramApi.java:364)
at org.telegram.api.engine.TelegramApi.doRpcCall(TelegramApi.java:309)
at org.telegram.api.engine.TelegramApi.doRpcCall(TelegramApi.java:400)
at org.telegram.api.engine.TelegramApi.doRpcCall(TelegramApi.java:396)
at at.nonon.telegram.telegram.Telegram.login(Telegram.java:165)
at at.nonon.telegram.telegram.Telegram.startApi(Telegram.java:105)
at at.nonon.telegram.telegram.Telegram.<init>(Telegram.java:54)
at at.nonon.telegram.telegram.ApiManager.startNew(ApiManager.java:21)
at at.nonon.telegram.Moin.onApiStart(Moin.java:31)
I took alot of the Code from the telegram-bot (https://github.com/ex3ndr/telegram-bot) but even if I copy paste his Code, it still doesn't work...
Thanks in Advance
this problem happened to me, too. I assume you are on a debian or some other linux box. The problem is Oracle JDK's use of the linux random number generator.
In order to make it work, run your application like this:
java -Djava.security.egd=file:/dev/./urandom -jar foo.jar
... meaning, you have to specify the java.security.egd parameter.
Details can be found here: https://github.com/ex3ndr/telegram-api/issues/9#issuecomment-38175765
and here:
http://www.virtualzone.de/2011/10/javas-securerandomgenerateseed-on-linux.html
It started working for me after I changed the server IP address in MemoryApiState as shown below
public void start(boolean isTest) {
connections = new HashMap<>();
connections.put(1, new ConnectionInfo[]{
new ConnectionInfo(1, 0, isTest ? "149.154.175.10" : "149.154.175.50", 443),
});
}
Your timeout might happen for several reasons - please see my answer to TimeoutException on telegram java client
Related
I implemented a simple bi-directional pipe server in Java using JNA, respectively a client in Powershell.
Basically, I expect the client to connect, send a message to the server and finally get a message back from the server.
The actual results are different though. When I run the server first and then the client, the client waits forever to connect, while the server connects and then waits to read the message from the pipe.
The code in Java for the server, respectively the code in Powershell for the client can be seen below.
Any idea how to solve this issue?
Thanks!
static final int MAX_BUFFER_SIZE = 1024;
static String pipeName = "\\\\.\\pipe\\testpipe";
static HANDLE namedPipe;
public static void main(final String[] args) {
createPipe();
runServerFile();
}
private static void createPipe() {
namedPipe = INSTANCE.CreateNamedPipe(pipeName,
WinBase.PIPE_ACCESS_DUPLEX , // dwOpenMode
WinBase.PIPE_TYPE_BYTE | WinBase.PIPE_READMODE_BYTE | WinBase.PIPE_WAIT,// | WinBase.PIPE_READMODE_MESSAGE | WinBase.PIPE_TYPE_MESSAGE, // dwPipeMode
WinBase.PIPE_UNLIMITED_INSTANCES , // nMaxInstances,
//WinBase.PIPE_UNLIMITED_INSTANCES, // nMaxInstances (255),
Byte.MAX_VALUE, // nOutBufferSize,
Byte.MAX_VALUE, // nInBufferSize,
1000, // nDefaultTimeOut,
null); // lpSecurityAttributes
System.out.println("Created pipe: " + namedPipe.toString() + " invalid_handle = " + WinBase.INVALID_HANDLE_VALUE.toString());
System.out.println("Last error: " + Native.getLastError());
}
private static void runServerFile() {
RandomAccessFile npipeClient = null;
try {
System.out.println("br1");
npipeClient = new RandomAccessFile(pipeName, "rws");
INSTANCE.ConnectNamedPipe(namedPipe,null);
byte[] buffer = new byte[100];
int rd_count;
String recv;
System.out.println("Connected pipe");
do{
System.out.println("Before read");
rd_count = npipeClient.read(buffer);
if(rd_count<0) break;
System.out.println("After read");
recv = new String(buffer,0, rd_count);
System.out.println("Received" + recv);
}while(!recv.equalsIgnoreCase("done"));
System.out.println("Received correct message");
//npipeClient.write("Hello world!".getBytes());
npipeClient.writeUTF("Hello back!");
//npipeClient.getFD().sync();
//INSTANCE.FlushFileBuffers(new HANDLE(npipeClient.getFD().));
System.out.println("Sent: Hello back");
npipeClient.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
param ($ComputerName = '.')
$npipeClient = new-object System.IO.Pipes.NamedPipeClientStream($ComputerName, 'testpipe', [System.IO.Pipes.PipeDirection]::InOut,
[System.IO.Pipes.PipeOptions]::None,
[System.Security.Principal.TokenImpersonationLevel]::Impersonation)
$pipeReader = $pipeWriter = $null
function WriteToPipeAndLog($msg) {
$msg
$pipeWriter.WriteLine($msg)
}
try {
'Client connecting to sever'
$npipeClient.Connect()
'Connected to server'
$pipeReader = new-object System.IO.StreamReader($npipeClient)
$pipeWriter = new-object System.IO.StreamWriter($npipeClient)
$pipeWriter.AutoFlush = $true
Write-Host "Sent: Hello world!"
$pipeWriter.WriteLine('Hello world!')
$pipeWriter.WriteLine('How ya doing')
$pipeWriter.WriteLine('Done')
while (($line = $read.ReadLine()) -ne $null)
{
Write-Host "Received: " $line
}
}
finally {
'Client exiting'
$npipeClient.Dispose()
}
I have around 20 githubs that I update some information for with the koshuke GitHub API:
try {
settings = settingsRepository.findById(1).orElseThrow(() -> new RuntimeException("No settings found"));
GitHub gitHub = GitHub.connect(settings.getUsername(), settings.getToken());
GHRepository repo;
try {
repo = gitHub.getRepository(gitHubModel.getUser() + "/" + gitHubModel.getRepo());
} catch (Exception e) {
e.printStackTrace();
throw new GitHubRepositoryException("Couldn't connect to " + gitHubModel.getLink() + ". Check URL.");
}
There is event that loops around them on every 2-3 seconds, takes one of the githubs, updates it and after 2-3 seconds continues to the next one. After certain amount of updates the code stops at:
repo = gitHub.getRepository(gitHubModel.getUser() + "/" + gitHubModel.getRepo());.
I tried debugging and found out that it stops at certain point and it throws 403 Forbidden:
private <T> T parse(Class<T> type, T instance, int timeouts) throws IOException {
InputStreamReader r = null;
int responseCode = -1;
String responseMessage = null;
try {
responseCode = uc.getResponseCode();
responseMessage = uc.getResponseMessage();
if (responseCode == 304) {
return null; // special case handling for 304 unmodified, as the content will be ""
}
if (responseCode == 204 && type!=null && type.isArray()) {
// no content
return type.cast(Array.newInstance(type.getComponentType(),0));
}
r = new InputStreamReader(wrapStream(uc.getInputStream()), "UTF-8");
String data = IOUtils.toString(r);
if (type!=null)
try {
return setResponseHeaders(MAPPER.readValue(data, type));
} catch (JsonMappingException e) {
throw (IOException)new IOException("Failed to deserialize " +data).initCause(e);
}
if (instance!=null) {
return setResponseHeaders(MAPPER.readerForUpdating(instance).<T>readValue(data));
}
return null;
} catch (FileNotFoundException e) {
// java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in HttpException
// to preserve backward compatibility
throw e;
} catch (IOException e) {
if (e instanceof SocketTimeoutException && timeouts > 0) {
LOGGER.log(INFO, "timed out accessing " + uc.getURL() + "; will try " + timeouts + " more time(s)", e);
return parse(type, instance, timeouts - 1);
}
throw new HttpException(responseCode, responseMessage, uc.getURL(), e);
} finally {
IOUtils.closeQuietly(r);
}
}
Then the exception is consumed and it comes to a point where it calls Thread.sleep and stops there.
Is this because I have exceeded the limit of requests? Somewhere I have read that it is 5000 request a minute and I am not doing that many. Any ideas why is this happening?
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).
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.
Any suggestions or criticisms are welcome.
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.
You can create a small VBS on-th-fly, launch it and capture its return code.
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);
}
}
Based on the other answers I constructed the following code to check for Windows Service status:
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();
}
}
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.
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)
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.
http://wrapper.tanukisoftware.org/doc/english/download.jsp
A shot in the dark but take a look at your Install Anywhere java documentation.
Specifically,
/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
Here's a straignt C# / P/Invoke solution.
/// <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;
};
}
I improvised on the given solutions, to make it locale independent.
Comparing the string "RUNNING" would not work in systems with non-english locales as Alejandro González rightly pointed out.
I made use of sc interrogate and look for the status codes returned by it.
Mainly, the service can have 3 states:-
1 - Not available
[SC] OpenService FAILED 1060: The specified service does not exist as an installed service.
2 - Not running
([SC] ControlService FAILED 1062: The service has not been started)
3 - Running
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 21100code here
So using them in following code, gives us the desired result :-
public static void checkBackgroundService(String serviceName) {
Process process;
try {
process = Runtime.getRuntime().exec("sc interrogate " + serviceName);
Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
StringBuffer buffer = new StringBuffer();
while (reader.hasNextLine()) {
buffer.append(reader.nextLine());
}
System.out.println(buffer.toString());
if (buffer.toString().contains("1060:")) {
System.out.println("Specified Service does not exist");
} else if (buffer.toString().contains("1062:")) {
System.out.println("Specified Service is not started (not running)");
} else {
System.out.println("Specified Service is running");
}
} catch (IOException e) {
e.printStackTrace();
}
}
During startup, create a file with File.deleteOnExit().
Check for the existence of the file in your scripts.
Simply call this method to check the status of service whether running or not.
public boolean checkIfServiceRunning(String serviceName) {
Process process;
try {
process = Runtime.getRuntime().exec("sc query " + serviceName);
Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
while(reader.hasNextLine()) {
if(reader.nextLine().contains("RUNNING")) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
well this is a strange one.
The first save attampt usually works (1 more try max).
but in a heavy load (many saves in a row) the saved file disappears.
if uncommenting the "Thread.sleep" the error is captured otherwise the validation passes succesfully
public void save(Object key, T objToSave) throws FileNotFoundException, IOException {
IOException ex = null;
for (int i = 0; i < NUM_OF_RETRIES; i++) {
try {
/* saving */
String filePath = getFilePath(key);
OutputStream outStream = getOutStream(filePath);
ObjectOutputStream os = new ObjectOutputStream(outStream);
os.writeObject(objToSave);
os.close();
/* validations warnings etc. */
if (i>0){
logger.warn(objToSave + " saved on attamped " + i);
/* sleep more on each fail */
Thread.sleep(100+i*8);
}
//Thread.sleep(50);
File doneFile = new File(filePath);
if (! (doneFile.exists())){
logger.error("got here but file was not witten to disk ! id was" + key);
throw new IOException();
}
logger.info("6. start persist " + key + " path=" + new File(filePath).getAbsolutePath() + " exists="+doneFile.exists());
return;
} catch (IOException e) {
logger.error(objToSave + " failed on attamped " + i);
ex = e;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
throw ex;
}
It is not a java writers issue.
I was not using threads explicitly but in my test I was deleting the folder i was saving to using: Runtime.getRuntime("rm -rf saver_directory");
I found out the hard way that it is asynchronous and the exact delete and create time was changing in mili-seconds.
so the solution was adding "sleep" after the delete.
the correct answer would be using java for the delete and not making a shortcuts ;)
Thank you all.
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).
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.
Any suggestions or criticisms are welcome.
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.
You can create a small VBS on-th-fly, launch it and capture its return code.
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);
}
}
Based on the other answers I constructed the following code to check for Windows Service status:
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();
}
}
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.
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)
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.
http://wrapper.tanukisoftware.org/doc/english/download.jsp
A shot in the dark but take a look at your Install Anywhere java documentation.
Specifically,
/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
Here's a straignt C# / P/Invoke solution.
/// <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;
};
}
I improvised on the given solutions, to make it locale independent.
Comparing the string "RUNNING" would not work in systems with non-english locales as Alejandro González rightly pointed out.
I made use of sc interrogate and look for the status codes returned by it.
Mainly, the service can have 3 states:-
1 - Not available
[SC] OpenService FAILED 1060: The specified service does not exist as an installed service.
2 - Not running
([SC] ControlService FAILED 1062: The service has not been started)
3 - Running
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 21100code here
So using them in following code, gives us the desired result :-
public static void checkBackgroundService(String serviceName) {
Process process;
try {
process = Runtime.getRuntime().exec("sc interrogate " + serviceName);
Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
StringBuffer buffer = new StringBuffer();
while (reader.hasNextLine()) {
buffer.append(reader.nextLine());
}
System.out.println(buffer.toString());
if (buffer.toString().contains("1060:")) {
System.out.println("Specified Service does not exist");
} else if (buffer.toString().contains("1062:")) {
System.out.println("Specified Service is not started (not running)");
} else {
System.out.println("Specified Service is running");
}
} catch (IOException e) {
e.printStackTrace();
}
}
During startup, create a file with File.deleteOnExit().
Check for the existence of the file in your scripts.
Simply call this method to check the status of service whether running or not.
public boolean checkIfServiceRunning(String serviceName) {
Process process;
try {
process = Runtime.getRuntime().exec("sc query " + serviceName);
Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
while(reader.hasNextLine()) {
if(reader.nextLine().contains("RUNNING")) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}