Как запустить и убить .net DLL из Java? - PullRequest
2 голосов
/ 25 марта 2019

Я работаю над проектом, целью которого является публикация данных в Microsoft Azure.На данный момент издатель opc публикует данные, даже когда сервер opc ua отключен.Он просто публикует последнее известное значение.Это не то, что мы хотим.Также частью проекта является автоматическое обнаружение новых серверов opc ua в сети.Чтобы достичь этого, я написал Java-программу, которая запускает экземпляр издателя opc, если обнаружен новый сервер opc ua.Сначала мне нужно было обновить только опубликованныйnodes.json одного издателя, но, похоже, это работает ненадежно.

OPC Publisher - это приложение .NET, которое может быть построено как dll в visual studio 2017.

Проблема в том, что мой инструмент должен убить процесс издателя, если сервер opc ua отключается.Это действительно убивает процесс Java, но издатель opc просто не остановится.


Я попытался запустить издатель через processbuilder и уничтожить процесс с помощью p.destroy (), который не дал никакого результата.Я также пытался убить задачу, используя pid банки, которую я создал для размещения издателя.


Вот так я запускаю opc publisher:
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "cd \"publisher\" && " + publisherString);
    pb.redirectErrorStream(true);
    Process p = pb.start();

(publisherString isчто-то вроде «опции dotnet opcpublisher.dll»)

Это работает очень хорошо.

Первая попытка уничтожить процесс была p.destroy(); ..., которая вообще не работает.


Вторая попытка состоит в том, чтобы основная программа вызывала вторичный jar, который запускает издателя:
ProcessBuilder publisher = new ProcessBuilder("cmd", "/c", "start", "java", "-jar", "StartPublisher.jar", options);
    publisher.redirectErrorStream(true);
    Process p = publisher.start();

Затем я получаю pid этого jar через JNA int pid = Kernel32.INSTANCE.GetCurrentProcessId(); и позже убиваю его, используя taskkill каквторой процесс:

ProcessBuilder terminator = new ProcessBuilder("cmd.exe", "/c", "taskkill /PID " + pid + " /T /F");
    terminator.redirectErrorStream(true);
    Process t = terminator.start();

Это убивает окно cmd и процесс java, но, как уже упоминалось выше, оно не убивает процесс dotnet.


У меня все вышлоидей как решить эту проблему.Это вообще возможно?Или мне нужны дополнительные библиотеки?Я был бы очень рад, если бы кто-нибудь мог мне помочь.

1 Ответ

1 голос
/ 25 марта 2019

Попробуйте что-то вроде этого, вам нужно знать имя исполняемого файла процесса dotnet.Но если вы это сделаете, вы можете убить его!:)

public static void main(String args[]){
    ArrayList<String> pids = new ArrayList<String>();
    try {
        String EXECUTIBLE_TO_KILL = "MicrosoftEdge.exe";
        ProcessBuilder pb = new ProcessBuilder("tasklist.exe");
        Process p = pb.start();


        InputStream stdout = p.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
        while (br.ready() || p.isAlive()) {
            String line = br.readLine();
            String lineNormalized = line.replaceAll("\\s+", " "); //remove multiple whitespaces.
            String[] table = lineNormalized.split(" ");
            if(table[0].equals(EXECUTIBLE_TO_KILL)){
                pids.add(table[1]); //Get pid from tasklist and add it to list to kill.
            }
        }
    }catch(Exception e){

    }

    if(pids.size() > 0) { // If the executible is in the list. Kill it
        String cmd = "taskkill.exe /F";
        for (String pid : pids) {
            cmd = cmd + " /pid "+pid;
        }
        System.out.println(cmd);
        try{
            //Attempt to kill process.
            //ProcessBuilder will not work here.
            Runtime.getRuntime().exec(cmd).waitFor();
        }catch(Exception e){

        }
    }


}
...