如何将Eclipse-RCP应用程序限制为单个实例? [英] How to restrict Eclipse-RCP application to a single instance?

查看:151
本文介绍了如何将Eclipse-RCP应用程序限制为单个实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想限制我的Eclipse-RCP应用程序到一个单一的实例。这样,我的意思是,一旦用户第一次打开应用程序,它会侦听一个端口,而对于第二个访问,它应该打开前一个实例,而不是显示一个警告消息,如已经有一个实例正在运行



我的RCP应用程序代码:



ApplicationInstanceListener.java接口代码

  public interface ApplicationInstanceListener 
{
public void newInstanceCreated();
}

ApplicationInstanceManager.java代码

  import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;


public class ApplicationInstanceManager {
private static ApplicationInstanceListener subListener;

/ **随机选择,但静态,高套接字号* /
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 2020;

/ **必须以换行符结尾* /
public static final String SINGLE_INSTANCE_SHARED_KEY =$$ NewInstance $$ \\\
;

/ **
*注册该应用程序实例。
*
* @return如果是第一个实例,如果没有则为false。
* /
public static boolean registerInstance(){
// returnValueonerror应为true,如果宽松(允许应用程序运行在网络错误)或false(如果严格)。
boolean returnValueonerror = true;
//尝试打开网络套接字
//如果成功,收听套接字的新实例消息,返回true
//如果无法打开,连接到现有的并发送新的实例消息, return false
try {
final ServerSocket socket = new ServerSocket(SINGLE_INSTANCE_NETWORK_SOCKET,10,InetAddress
.getLocalHost());
System.out.println(侦听套接字上的应用程序实例+ SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new Thread(new Runnable(){
public void run(){
boolean socketClosed = false;
while(!socketClosed){
if socket.isClosed()){
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader (新的InputStreamReader(client.getInputStream()));
String message = in.readLine();
if(SINGLE_INSTANCE_SHARED_KEY.trim()。equals(message.trim())){
System.out.println(Shared key matched - new application instance found);
fireNewInstance();
}
in.close();
client.close();
} catch(IOException e){
socketClosed = true;
}
}
}
}
});
instanceListenerThread.start();
// listen
} catch(UnknownHostException e){
System.out.println(e.getMessage());
return returnValueonerror;
} catch(IOException e){
System.out.println(Port is already taken。Notify first instance);
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(),SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println(成功通知第一个实例);
返回false;
} catch(UnknownHostException e1){
System.out.println(e.getMessage());
return returnValueonerror;
} catch(IOException e1){
System.out.println(连接到单实例通知的本地端口时出错);
System.out.println(e1.getMessage());
return returnValueonerror;
}

}
返回true;
}

public static void setApplicationInstanceListener(ApplicationInstanceListener listener){
subListener = listener;
}

private static void fireNewInstance(){
if(subListener!= null){
subListener.newInstanceCreated();
}
}
}

Application.java代码

  import org.eclipse.equinox.app.IApplication; 
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;

/ **
*此类控制应用程序执行的所有方面
* /
public class Application implements IApplication {

/ *
*(非Javadoc)
*
* @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app。
* IApplicationContext)
* /
public Object start(IApplicationContext context)throws Exception {
if(!ApplicationInstanceManager.registerInstance()){
//实例已经运行。
System.out
.println(此应用程序的另一个实例已经在运行,退出);
MessageDialog
.openInformation(新的Shell(),信息,
此应用程序的另一个实例已经在运行。
System.exit(0);
}
显示display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if(returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}

}

/ *
*(非Javadoc)
*
* @see org.eclipse。 equinox.app.IApplication#stop()
* /
public void stop(){
if(!PlatformUI.isWorkbenchRunning())
return;
final IWorkbench workbench = PlatformUI.getWorkbench();
final显示display = workbench.getDisplay();
display.syncExec(new Runnable(){
public void run(){
if(!display.isDisposed())
workbench.close();
}
});
}
}

我采用了一个简单的RCP应用程序,视图为一个模板
上述代码工作正常,但不会打开以前的实例,如 skype或Windows媒体播放器,尽管它显示如下所示的警报



如何在第二次运行应用程序时显示或打开上一个实例?

解决方案

我有一个应用程序做同样的事情。诀窍在于新实例无法将旧实例带到前端。但是,旧实例可以在接触新实例后将其自身带到前端。



所以你的旧实例需要调用

  PlatformUI.getWorkbench()。getActiveWorkbenchWindow()。getShell()。forceActive();通知新实例后,

对于我的应用程序,新实例不会显示错误消息,它只是透明地关闭,旧的实例会自动备份。


I would like to restrict my Eclipse-RCP application to a single instance. By this, I mean that once a user opens the application for the first time, it listens on a port and for the second access it should open the previous instance instead of showing a warning message like "already an instance is running"

My RCP Application code:

ApplicationInstanceListener.java interface code

public interface ApplicationInstanceListener
{
    public void newInstanceCreated();
}

ApplicationInstanceManager.java code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;


public class ApplicationInstanceManager {
        private static ApplicationInstanceListener subListener;

    /** Randomly chosen, but static, high socket number */
    public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 2020;

    /** Must end with newline */
    public static final String SINGLE_INSTANCE_SHARED_KEY = "$$NewInstance$$\n";

    /**
     * Registers this instance of the application.
     *
     * @return true if first instance, false if not.
     */
    public static boolean registerInstance() {
        // returnValueonerror should be true if lenient (allows app to run on network error) or false if strict.
        boolean returnValueonerror = true;
        // try to open network socket
        // if success, listen to socket for new instance message, return true
        // if unable to open, connect to existing and send new instance message, return false
        try {
            final ServerSocket socket = new ServerSocket(SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
                    .getLocalHost());
           System.out.println("Listening for application instances on socket " + SINGLE_INSTANCE_NETWORK_SOCKET);
            Thread instanceListenerThread = new Thread(new Runnable() {
                public void run() {
                    boolean socketClosed = false;
                    while (!socketClosed) {
                        if (socket.isClosed()) {
                            socketClosed = true;
                        } else {
                            try {
                                Socket client = socket.accept();
                                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                                String message = in.readLine();
                                if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(message.trim())) {
                                        System.out.println("Shared key matched - new application instance found");
                                    fireNewInstance();
                                }
                                in.close();
                                client.close();
                            } catch (IOException e) {
                                socketClosed = true;
                            }
                        }
                    }
                }
            });
            instanceListenerThread.start();
            // listen
        } catch (UnknownHostException e) {
                System.out.println(e.getMessage());
            return returnValueonerror;
        } catch (IOException e) {
                System.out.println("Port is already taken.  Notifying first instance.");
            try {
                Socket clientSocket = new Socket(InetAddress.getLocalHost(), SINGLE_INSTANCE_NETWORK_SOCKET);
                OutputStream out = clientSocket.getOutputStream();
                out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
                out.close();
                clientSocket.close();
                System.out.println("Successfully notified first instance.");
                return false;
            } catch (UnknownHostException e1) {
                System.out.println(e.getMessage());
                return returnValueonerror;
            } catch (IOException e1) {
                System.out.println("Error connecting to local port for single instance notification");
                System.out.println(e1.getMessage());
                return returnValueonerror;
            }

        }
        return true;
    }

    public static void setApplicationInstanceListener(ApplicationInstanceListener listener) {
        subListener = listener;
    }

    private static void fireNewInstance() {
      if (subListener != null) {
        subListener.newInstanceCreated();
      }
  }
}

Application.java code

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;

/**
 * This class controls all aspects of the application's execution
 */
public class Application implements IApplication {

        /*
         * (non-Javadoc)
         *
         * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.
         * IApplicationContext)
         */
        public Object start(IApplicationContext context) throws Exception {
                if (!ApplicationInstanceManager.registerInstance()) {
                        // instance already running.
                        System.out
                                        .println("Another instance of this application is already running.  Exiting.");
                        MessageDialog
                                        .openInformation(new Shell(), "Information",
                                                        "Another instance of this application is already running.  Exiting.");
                        System.exit(0);
                }
                Display display = PlatformUI.createDisplay();
                try {
                        int returnCode = PlatformUI.createAndRunWorkbench(display,
                                        new ApplicationWorkbenchAdvisor());
                        if (returnCode == PlatformUI.RETURN_RESTART)
                                return IApplication.EXIT_RESTART;
                        else
                                return IApplication.EXIT_OK;
                } finally {
                        display.dispose();
                }

        }

        /*
         * (non-Javadoc)
         *
         * @see org.eclipse.equinox.app.IApplication#stop()
         */
        public void stop() {
                if (!PlatformUI.isWorkbenchRunning())
                        return;
                final IWorkbench workbench = PlatformUI.getWorkbench();
                final Display display = workbench.getDisplay();
                display.syncExec(new Runnable() {
                        public void run() {
                                if (!display.isDisposed())
                                        workbench.close();
                        }
                });
        }
}

I've taken a simple RCP application with view as a template. The above code works fine but doesn't open previous instance like skype or windows media player despite it shows an alert like below

How can I show or open the previous instance upon second run of the application?

解决方案

I have an app that does this same thing. The trick is that the new instance can't bring the old instance to the front. But, the old instance can bring itself to the front after it contacts the new instance.

So your old instance needs to call

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().forceActive();

after it notifies the new instance. For my app, the new instance doesn't show an error message, it just closes transparently and the old instance pops itself back up.

这篇关于如何将Eclipse-RCP应用程序限制为单个实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆