【问题标题】:Show previous instance of RCP application显示 RCP 应用程序的先前实例
【发布时间】:2011-12-20 18:57:17
【问题描述】:

我有一个仅在第一次运行时运行的 rcp 应用程序,当用户尝试重新执行该应用程序时,第二个实例充当客户端,它通过套接字对其参数进行编码并发送到充当服务器的第一个实例然后默默退出。第一个实例接收并解码该消息,然后就像使用这些参数调用它一样。

到目前为止,我为在两个实例之间传递参数制定了内部协议规范。

我无法将第一个实例(RCP 应用程序)放在前面。它仅处于最小化状态,

这是我之前question的延续

我对上一篇文章所做的更改是应用程序类的启动方法

public Object start(IApplicationContext context) throws Exception {
        if (!ApplicationInstanceManager.registerInstance()) {
            return IApplication.EXIT_OK;
        }
        ApplicationInstanceManager
                .setApplicationInstanceListener(new ApplicationInstanceListener() {
                    public void newInstanceCreated() {
                        Display.getDefault().asyncExec(new Runnable() {
                            public void run() {
                                System.out.println("New instance detected...");

                                //Display.getCurrent().getActiveShell()
                                        .forceActive();// this gives null
                                                        // pointer exception
                                                        // hence commented
                            }
                        });
                    }
                });
        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();
        }
    }

下面一行阻止我把应用程序带到前面

Display.getCurrent().getActiveShell().forceActive();

在getActiveShell()处产生空指针异常

如何最大化前一个实例或将其置于前面

【问题讨论】:

    标签: eclipse eclipse-rcp


    【解决方案1】:

    我编写了一个实例管理器来将我的 RCP 限制为单个实例。

    这是Application.java 中的代码,在start 方法中:

        if (!ApplicationInstanceManager.registerInstance()) {
            return IApplication.EXIT_OK;
        }
    
        ApplicationInstanceManager
                .setApplicationInstanceListener(new ApplicationInstanceListener() {
                    public void newInstanceCreated() {
                        Display.getDefault().asyncExec(new Runnable() {
                            public void run() {
                                if (DEBUG)
                                    System.out.println("New instance detected...");
                                Display.getCurrent().getActiveShell().forceActive();
                            }
                        });
                    }
                });
    

    这是监听器界面:

    public interface ApplicationInstanceListener {
    
         public void newInstanceCreated();
    
    }
    

    这是 Manager 类:

    public class ApplicationInstanceManager {
    
        private static final boolean DEBUG = true;
    
        private static ApplicationInstanceListener subListener;
    
        /** Randomly chosen, but static, high socket number */
        public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331;
    
        /** Must end with newline */
        public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\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());
                if (DEBUG)
                    System.out
                            .println("Listening for application instances on socket "
                                    + SINGLE_INSTANCE_NETWORK_SOCKET);
                Thread instanceListenerThread = new InstanceListenerThread(socket);
                instanceListenerThread.start();
                // listen
            } catch (UnknownHostException e) {
                EclipseLogging.logError(RabidPlugin.getDefault(),
                        RabidPlugin.PLUGIN_ID, e);
                return returnValueOnError;
            } catch (IOException e) {
                return portTaken(returnValueOnError, e);
    
            }
            return true;
        }
    
        private static boolean portTaken(boolean returnValueOnError, IOException e) {
            if (DEBUG)
                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) {
                EclipseLogging.logError(RabidPlugin.getDefault(),
                        RabidPlugin.PLUGIN_ID, e);
                return returnValueOnError;
            } catch (IOException e1) {
                EclipseLogging
                        .logError(
                                RabidPlugin.getDefault(),
                                RabidPlugin.PLUGIN_ID,
                                "Error connecting to local port for single instance notification",
                                e);
                return returnValueOnError;
            }
        }
    
        public static void setApplicationInstanceListener(
                ApplicationInstanceListener listener) {
            subListener = listener;
        }
    
        private static void fireNewInstance() {
            if (subListener != null) {
                subListener.newInstanceCreated();
            }
        }
    
        public static void main(String[] args) {
            if (!ApplicationInstanceManager.registerInstance()) {
                // instance already running.
                System.out.println("Another instance of this application "
                        + "is already running.  Exiting.");
                System.exit(0);
            }
            ApplicationInstanceManager
                    .setApplicationInstanceListener(new ApplicationInstanceListener() {
                        public void newInstanceCreated() {
                            System.out.println("New instance detected...");
                            // this is where your handler code goes...
                        }
                    });
        }
    
        public static class InstanceListenerThread extends Thread {
    
            private ServerSocket socket;
    
            public InstanceListenerThread(ServerSocket socket) {
                this.socket = socket;
            }
    
            @Override
            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())) {
                                if (DEBUG)
                                    System.out.println("Shared key matched - "
                                            + "new application instance found");
                                fireNewInstance();
                            }
                            in.close();
                            client.close();
                        } catch (IOException e) {
                            socketClosed = true;
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 或者,您可以使用任何可用端口,并将该端口写入其他人可以读取的文件。请注意,forceActive() 是操作系统可能无法完全遵循的请求。
    • @raghav:不是。向应用程序添加一个静态布尔值,
    • @Gilbert Display.getCurrent().getActiveShell().forceActive();正在生成空指针异常
    【解决方案2】:

    在您的 IApplication 启动后,您还可以使用 org.eclipse.osgi.service.datalocation.Location.isSet()org.eclipse.osgi.service.datalocation.Location.lock() 检查并锁定 OSGi 实例位置

    通常使用以下代码从您的激活器中检索位置:

        public Location getInstanceLocation() {
        if (locationTracker == null) {
            Filter filter = null;
            try {
                filter = context.createFilter(Location.INSTANCE_FILTER);
            } catch (InvalidSyntaxException e) {
                // ignore this. It should never happen as we have tested the
                // above format.
            }
            locationTracker = new ServiceTracker(context, filter, null);
            locationTracker.open();
        }
        return (Location) locationTracker.getService();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      相关资源
      最近更新 更多