문제

필요 시작하 1-3 외부 프로그램에서 Java 응용 프로그램이 있는 경로를 사용자에 의해 정의됩니다.나는 몇 가지 요구 사항:

  1. 나는 원하지 않는 프로그램을 실행하는 경우 그것은 이미 실행

  2. 나는 원하지 않는 모든 프로그램에서 초점을 훔치는 내 Java 응용 프로그램

  3. 나는 걱정하지 않는 어떤 경우에는 그들의 실패를 시작하거나지 않습니다.그들만이 자동으로 실패합니다.

여기에 나는 지금까지:

ProcessBuilder pb = new ProcessBuilder(userDefinedPath1);
try {
    pb.start();
}
catch (Exception e) {
    // Something went wrong, just ignore
}

그리고 나서 반복하는 3 번 더 다른 두 경로입니다.이와 같이 시작게 될 것으로 예상하고 충족하는 세 번째 요건이지만 실패에 처음 두.

는 가장 좋은 방법은 무엇입니까?

편집:

  1. 내가 없어의 이니다.그들은 세 번째 파티입니다.또한,그들은 있었을 시작하거나 중지에 의 사용자가 수동으로습니다.

  2. 정확한 의 이름을 실행 파일(예를들면"blah.exe")그리고 그들 것이다 동일하지만,경로를 실행 파일을 반드시 하지 않습니다.

  3. 는 배치 파일 래퍼가 가능하지 않습니다 여기에.

  4. 다른 애플 리케이션 자바 애플 리케이션,다만 보통 오래된 Windows 실행 파일.

도움이 되었습니까?

해결책

나는 당신을 제어 할 수 없이 다른 두 개의 앱을...았다면,이되지 않을 것이 너무 나쁜-그냥 그들을 듣고 소켓우 소켓을 사용할 수 있습니다.

다음 솔루션을 수 있습니다 실제로 있어 독립적이다.를 관리할 수 있습을 전체 시스템을 통해 배치 파일 중요한 헌납자이었습니다.를 작성하는 배치 파일을 파일을 생성을 시작할 때까지 그것을 삭제할 때 그것이 중지됩니다.유닉스 시스템을 사용하여 이 기술은 많은--그들이 부르는 파일을 파일 잠금보다 더 자주하지 않습니다.

는 경우에만 응용 프로그램이 시작한 다른 앱에,당신은 단순히 수는 경우에 당신은 그것을 시작했는지,그래서 난 이것이 가능한 또는지 묻는다,그래서 나는다고 가정하면 사용자의 시작을 통해 이러한 프로그램 일부를 다른 메커니즘이 있습니다.

면을 제어할 수 있는 권한이 없습을 통해 실행의 다른 앱과할 수 없더라도 작성하는 배치 파일을 실행,그 다음 당신은 할 수 없는 당신이 원하는 무엇(노트,응용 프로그램을 항상 사용하여 배치 파일,는 경우에도 사용자 시작하여 그들을 손).

나는 그냥 아주-설 될 수 있습을 얻는 프로세스 상태와 분석,하지만 당신이 무엇인지 정확히 알아야 하는 다른 애플 리케이션에서 호출 PS,이것이 정말 하는 것입니다.또한,모든 자바 애플 리케이션을 가지고 있는 경향이 있습니다 같은 정확한 서명을에서 대부분의 프로세스 상태 출력물을 만들 수 있는 이 쓸모가 없다.

문제는 경우 이러한 프로그램 중 하나로 시작되었 외부에,당신은 거의 아무 방법을 식별하는 사지 않는 한 당신이 그것을 알고 정확한 프로세스 상태의 서명 및 그럼에도 색다른.

다른 팁

나는 Linux의 두 가지 답변을 제공합니다.

이미 실행중인 경우 프로그램을 실행하지 마십시오. Main.java라는 파일에 넣으십시오.

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

class JustOneLock {
  FileLock lock;
  FileChannel channel;

  public boolean isAppActive() throws Exception{
    File file = new File(System.getProperty("user.home"),
            "FireZeMissiles1111" + ".tmp");
    channel = new RandomAccessFile(file, "rw").getChannel();

    lock = channel.tryLock();
    if (lock == null) {
      return true;
    }
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        try {
          lock.release();
          channel.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
    return false;
  }
}

public class Main {
  public static void main(String[] args)throws Exception {
    JustOneLock u = new JustOneLock();

    if (u.isAppActive()) {
      System.out.println("Already active, stop!");
      System.exit(1);
    }
    else {
      System.out.println("NOT active... Do hard work for 5 seconds.");
      try{Thread.sleep(5000);}catch(Exception e){}
    }
  }
}

컴파일하고 실행하십시오. 그런 다음 새 터미널을 열고 다른 터미널을 실행하는 동안 다시 실행하십시오.

Windows에 대한 또 다른 대답

이 프로그램은 이미 현재 시스템에서 실행중인 경우 자체를 실행할 수 없습니다. 이것은 Windows 전용 시스템을위한 것입니다.

import java.io.*;
import java.util.prefs.Preferences;

public class JavaApplication3 {

    public static void main(String[] args){
        if(isRunning()){
            System.out.println("Two instances of this program cannot " +
                    "be running at the same time.  Exiting now");
        }
        else{
            onStart();
            epicHeavyWorkGoesHere();
            onFinish();
        }
    }
    public static void epicHeavyWorkGoesHere(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {}
    }
    public static void onStart(){
        Preferences prefs = Preferences.systemRoot().node("JavaApplication3");
        prefs.put("RUNNINGPID", getCurrentPID());
    }
    public static void onFinish(){
        Preferences prefs = Preferences.systemRoot().node("JavaApplication3");
        prefs.put("RUNNINGPID", "");
    }
    public static boolean isRunning(){
        Preferences prefs = Preferences.systemRoot().node("JavaApplication3");

        if (prefs.get("RUNNINGPID", null) == null || prefs.get("RUNNINGPID", null).equals(""))
            return false;

        if (isProcessIdRunningOnWindows(Integer.parseInt(prefs.get("RUNNINGPID", null))))
            return true;
        return false;
    }
    public static String getCurrentPID(){
        //This function is designed to get the PID from the windows system, it may
        //not work for Linux or Mac.  You'll have to acquire a suitable getCurrentPID function
        try{
            java.lang.management.RuntimeMXBean runtime = java.lang.management.ManagementFactory.getRuntimeMXBean();
            java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
            jvm.setAccessible(true);
            sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
            java.lang.reflect.Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
            pid_method.setAccessible(true);
            return pid_method.invoke(mgmt) + "";
        }
        catch(Exception e){
            throw new RuntimeException("Cannot get the current PID");
        }
    }
    public static boolean isProcessIdRunningOnWindows(int pid){
        //This Function only works for windows, if you want it to work on linux
        //you will have to go find a replacement method that takes the processID
        //as a parameter and spits out a true/false if it is running on the system.
        try {
            Runtime runtime = Runtime.getRuntime();
            String cmds[] = {"cmd", "/c", "tasklist /FI \"PID eq " + pid + "\""};
            Process proc = runtime.exec(cmds);

            InputStream inputstream = proc.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
            String line;
            while ((line = bufferedreader.readLine()) != null) {
                if (line.contains(" " + pid + " ")){
                    return true;
                }
            }
            return false;
        }
        catch (Exception ex) {
            throw new RuntimeException("Cannot run the tasklist command to query if a pid is running or not");
        }
    }
}

위의 코드의 전략은 PID가 시스템에서 실행되는 경우 PID를 마지막 실행에서 유지하는 것입니다. 시작하지 마십시오. 끝나면 재설정하십시오.

기본 설정은 Windows 레지스트리에 저장됩니다 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs

프로그램이 충돌하거나 영원히 매달려 죽으면 자물쇠가 일관되지 않은 상태로 남아 있고 아마도 재부팅에서 살아남을 수도 있기 때문에 파일 잠금을 사용하여 Java 응용 프로그램이 동시에 두 번 실행되지 않도록 조언합니다. 여전히 실행중인 프로그램과 충돌하고 잠긴 파일을 잠금 상태로 유지 한 프로그램의 차이를 어떻게 알 수 있으므로 어떻게 프로그램이 문제를 일으킬 것입니까?

나는 이것이 가장 좋은 방법이라고 확신합니다. 응용 프로그램은 시작시 "서버"가 실행되며 서버의 포트가 이미 가져 오면 응용 프로그램이 닫힙니다.

public static ServerSocket ss;

public static void main (String[] args) {

    ss = null;

    try {
        ss = new ServerSocket(1044);
    } catch (IOException e) {
        System.err.println("Application already running!");
        System.exit(-1);
    }
}

이것이 제가 문제를 해결하기 위해 한 일입니다. 순수한 Java를 사용하는 간단한 해결책입니다.

다음 코드가 한 번 충돌하면 일관되지 않은 상태로 남겨져 있으며 중단되거나 추락 된 프로그램을 다룰 방법이 없습니다.

public void main(String[] args){
    if(isRunning()){
        JOptionPane.showMessageDialog(this, "2 instances of this program cannot be running at the same time. \n Exiting now");
        System.exit(0);
    }else{
        onStart();
    }
}    

public final void onStart(){
    Preferences prefs;
    prefs = Preferences.userRoot().node(this.getClass().getName());
    prefs.put("RUNNING", "true");
}

public final void onFinish(){
    Preferences prefs;
    prefs = Preferences.userRoot().node(this.getClass().getName());
    prefs.put("RUNNING", "false");
}

public boolean isRunning(){
    Preferences prefs;
    prefs = Preferences.userRoot().node(this.getClass().getName());
    return prefs.get("RUNNING", null) != null ? Boolean.valueOf(prefs.get("RUNNING", null)) : false;
}

private void formWindowClosing(java.awt.event.WindowEvent evt) {
    onFinish();
}

보다 프로그램 또는 프로세스가 실행 중인지 확인 (Windows)

이 팁은 주어진 프로그램이 실행 중인지 감지합니다. 좋아, vbscript 때문에 예쁘지는 않지만 구현하기 쉽습니다.

UNIX 기반 시스템 에서이 문제를 다루고 있다면 프로세스 정보를 수집하고 외부 응용 프로그램을 시작하려는 기본 기능을 작성하려고합니다. 이것은 Java의 정신에 위배되지만, 수집하려는 정보의 유형과 응용 프로그램 출시 통제는 JVM 외부에 있습니다.

나는 당신을 올바른 방향으로 가리킬 수있는 Windows 프로그래밍에 대해 충분히 알지 못하지만, 두 번째 기준에 도움이 될 수있는 .NET 언어 또는 일반 C ++로 액세스 할 수있는 Windows API 호출이 있다고 생각합니다. 아마도 당신은 도움을 줄 수있는 비 자바 개발자를 끌어 들이기 위해 질문을 바꿀 수 있습니다.


편집하다:

확인하십시오 쉘 실행 기능 Windows API의. SW_SHOWNOACTIVATE 옵션은 현재 창이 활성 상태를 유지할 수 있도록 보입니다.

모든 시스템에 할 수있는 사소한 일이 하나이며 여기에는 파일 잠금 기능이 포함됩니다.

프로그램이 먼저 실행되면 파일을 만들고 잠그십시오. Lockfile과 같은 이름을 지정하십시오. 타임 스탬프를 생성하고 암호화하십시오. 이것에 이것에 써주하십시오.

동일한 프로그램에서 먼저 실행되면 잠금 파일이 있는지 확인하십시오. 그것을 잠그려고 시도합니다. 이 파일이 잠겨있을 가능성을 무시하십시오. 타임 스탬프를 읽고 확인하십시오. 타임 스탬프가 부주의하게 작다면 (1 시간 전과 같이) 프로그램을 실행하십시오. 타임 스탬프를 다시 작성하면 오류가 발생합니다. 이 경우 이미 열려있는 프로그램이 있다고 가정합니다.

프로그램 종료 에서이 잠금 파일을 삭제하십시오.

Windows XP (Pro?)에서는 '작업 목록'명령을 시작하고 출력을 구문 분석하여 프로세스가 실행 중인지 확인할 수 있습니다. 초점 문제를 피하기 위해 스레드를 사용할 수 있습니다 (저는 생각합니다)

JPS를 사용하여 실행중인 Java 프로그램 상태를 알 수 있습니다. JPS는 Javac, Java 등과 같은 Java 도구 중 하나입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top