Как ограничить приложение Eclipse-RCP одним экземпляром? - PullRequest
3 голосов
/ 25 декабря 2011

Я хотел бы ограничить свое приложение 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;

    /** 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 код

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();
                        }
                });
        }
}

Я взял простое приложение RCP с представлением в качестве шаблона. Приведенный выше код работает нормально, но не открывает предыдущий экземпляр, например Skype или Windows Media Player , несмотря на то, что он показывает предупреждение, как показано ниже enter image description here

Как показать или открыть предыдущий экземпляр при втором запуске приложения?

Ответы [ 4 ]

1 голос
/ 17 января 2012

У меня есть приложение, которое делает то же самое. Хитрость в том, что новый экземпляр не может перенести старый экземпляр на передний план. Но старый экземпляр может выйти на передний план после контакта с новым экземпляром.

Итак, вашему старому экземпляру нужно позвонить

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

после уведомления нового экземпляра. Для моего приложения новый экземпляр не отображает сообщение об ошибке, он просто прозрачно закрывается, а старый экземпляр снова всплывает.

0 голосов
/ 17 декабря 2013

В основном вы можете иметь такие функции, как Eclipse.Eclipse поддерживает файл .lock для блокировки рабочего пространства.Аналогичным образом вы можете создать пустой файл .lock в своей рабочей области.

При запуске каждого экземпляра необходимо проверить наличие файла .lock, а затем продолжить работу соответствующим образом.Если файл отсутствует, вы должны создать его, чтобы другой экземпляр обнаружил, что рабочее пространство заблокировано.

0 голосов
/ 04 января 2012

я думаю, вы должны просто заменить вам уже запущенный экземпляр.
я не знаю, может ли эта или эта ссылка помочь, но это все, что я получил

очень надеюсь, что это поможет

0 голосов
/ 27 декабря 2011

Взгляните на эту статью: Один экземпляр приложения RCP . Автор описывает тот же шаблон использования серверного сокета, о котором вы спрашиваете.

...