0

I'm using a launcher to start a jar in c++ that I took from here: https://github.com/foolo/windows-jre-laucher

My folders and files are like this:

.\launcher.exe

.\lib\MyApp-1.6.0-jar-with-dependencies.jar

.\lib\MyApp-1.6.1-jar-with-dependencies.jar

It works great but I'd like to change so that it checks the "lib" folder, and for every file that matches the regex ".*-.\..\..-.*jar" (or any other way to match my jars) then compares the versions of each and deletes all the older ones (there should only be one old one).

Here is the current launcher.cpp code:

#define JAVAPATH       L"jre\\bin\\java.exe"
#define ARGS           L"--class-path lib/*;* app.Launcher"

#include <windows.h>
#include <stdio.h>
#include <shlwapi.h>
#define BUFSIZE 512
wchar_t buf[BUFSIZE];

void cdToApplication() {
    wchar_t path[MAX_PATH];
    int len = GetModuleFileNameW(NULL, path, MAX_PATH);
    if (len > 0 && len < MAX_PATH) {
        path[len-1] = 0;
        if (PathRemoveFileSpecW(path) != 0) {
            SetCurrentDirectoryW(path);
        }
    }
}

int main() {
    cdToApplication();
    STARTUPINFOW si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    LPCWSTR cmd = JAVAPATH;
    WCHAR args[] = JAVAPATH L" " ARGS;
    if (CreateProcessW(cmd, args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi) == 0) {
        swprintf_s( buf, BUFSIZE, L"Could not run %s\nerror code: %lu\ncommand line: %s", cmd, GetLastError(), args );
        MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
        return 0;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitCode = 0;
    if (GetExitCodeProcess(pi.hProcess, &exitCode) != 0) {
        if (exitCode != 0) {
            swprintf_s( buf, BUFSIZE, L"%s\nfailed with exit code %lu\ncommand line: %s", cmd, exitCode, args );
            MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
        }
    }
    else {
        swprintf_s( buf, BUFSIZE, L"%s\nterminated with unknown exit code\ncommand line: %s", cmd, args );
        MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
}

I did try some code with std::filesystem but it didn't compile, I'm using MingW64 with g++ 10.2.0. I tried adding the code from the 2017 solution here : How can I get the list of files in a directory using C or C++?

Here is the code modified to try and use std::filesystem

#define JAVAPATH       L"jre\\bin\\java.exe"
#define ARGS           L"--class-path lib/*;* app.Launcher"

#include <windows.h>
#include <stdio.h>
#include <shlwapi.h>

#include <string>
#include <iostream>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#define BUFSIZE 512
wchar_t buf[BUFSIZE];

void cdToApplication() {
    wchar_t path[MAX_PATH];
    int len = GetModuleFileNameW(NULL, path, MAX_PATH);
    if (len > 0 && len < MAX_PATH) {
        path[len-1] = 0;
        if (PathRemoveFileSpecW(path) != 0) {
            SetCurrentDirectoryW(path);
        }
    }
}

int main() {
    cdToApplication();
    
    std::string path = "/lib";
    for (const auto & entry : fs::directory_iterator(path))
        std::cout << entry.path() << std::endl;
    
    STARTUPINFOW si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    LPCWSTR cmd = JAVAPATH;
    WCHAR args[] = JAVAPATH L" " ARGS;
    if (CreateProcessW(cmd, args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi) == 0) {
        swprintf_s( buf, BUFSIZE, L"Could not run %s\nerror code: %lu\ncommand line: %s", cmd, GetLastError(), args );
        MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
        return 0;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitCode = 0;
    if (GetExitCodeProcess(pi.hProcess, &exitCode) != 0) {
        if (exitCode != 0) {
            swprintf_s( buf, BUFSIZE, L"%s\nfailed with exit code %lu\ncommand line: %s", cmd, exitCode, args );
            MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
        }
    }
    else {
        swprintf_s( buf, BUFSIZE, L"%s\nterminated with unknown exit code\ncommand line: %s", cmd, args );
        MessageBoxExW(NULL, buf, L"Message", MB_OK | MB_ICONERROR, 0);
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
}

Here is the error when just using std::filesystem:

$ g++ -o launcher.o -c launcher.cpp
launcher.cpp:11:21: error: 'filesystem' is not a namespace-name
   11 | namespace fs = std::filesystem;
      |                     ^~~~~~~~~~
launcher.cpp: In function 'int main()':
launcher.cpp:30:31: error: 'fs' has not been declared
   30 |     for (const auto & entry : fs::directory_iterator(path))
      |                               ^~

But when using std::experimental::filesystem it does work for the first step: g++ -o launcher.o -c launcher.cpp but it crashes at the second step:

$ g++ -o launcher.exe -static -s -mwindows launcher.o resources.res -lshlwapi
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.text+0x1be): undefined reference to `std::experimental::filesystem::v1::__cxx11::directory_iterator::operator*() const'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.text+0x1fe): undefined reference to `std::experimental::filesystem::v1::__cxx11::directory_iterator::operator++()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.text$_ZNSt12experimental10filesystem2v17__cxx1116filesystem_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10error_code[_ZNSt12experimental10filesystem2v17__cxx1116filesystem_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10error_code]+0x93): undefined reference to `std::experimental::filesystem::v1::__cxx11::filesystem_error::_M_gen_what()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.text$_ZNSt12experimental10filesystem2v17__cxx1118directory_iteratorC1ERKNS2_4pathE[_ZNSt12experimental10filesystem2v17__cxx1118directory_iteratorC1ERKNS2_4pathE]+0x28): undefined reference to `std::experimental::filesystem::v1::__cxx11::directory_iterator::directory_iterator(std::experimental::filesystem::v1::__cxx11::path const&, std::experimental::filesystem::v1::directory_options, std::error_code*)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.text$_ZNSt12experimental10filesystem2v17__cxx114pathC1INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES3_EERKT_[_ZNSt12experimental10filesystem2v17__cxx114pathC1INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES3_EERKT_]+0x60): undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.rdata$.refptr._ZNSt12experimental10filesystem2v17__cxx1116filesystem_errorD1Ev[.refptr._ZNSt12experimental10filesystem2v17__cxx1116filesystem_errorD1Ev]+0x0): undefined reference to `std::experimental::filesystem::v1::__cxx11::filesystem_error::~filesystem_error()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: launcher.o:launcher.cpp:(.rdata$.refptr._ZTVNSt12experimental10filesystem2v17__cxx1116filesystem_errorE[.refptr._ZTVNSt12experimental10filesystem2v17__cxx1116filesystem_errorE]+0x0): undefined reference to `vtable for std::experimental::filesystem::v1::__cxx11::filesystem_error'
collect2.exe: error: ld returned 1 exit status
Dazgol
  • 1
  • 1
  • Depending on compiler and language-version used, [`std::filesystem`](https://en.cppreference.com/w/cpp/filesystem) could be helpful, especially its [iterator](https://en.cppreference.com/w/cpp/filesystem/directory_iterator) could be used to find files matching a specific pattern. – Some programmer dude Aug 14 '21 at 22:52
  • I did try some code with std::filesystem but it didn't compile, I'm using MingW64 with g++ 10.2.0. I tried adding the code from the 2017 solution here : https://stackoverflow.com/questions/612097/how-can-i-get-the-list-of-files-in-a-directory-using-c-or-c As I said I'm not really a C++ dev, I did some C but only very basic C++ about 10 years ago... – Dazgol Aug 14 '21 at 23:03
  • You appear to be asking different questions here. 1) Something about a self-updating Java application not working. 2) A problem with compiling C++ code. Please restrict your self to asking a single question in a Question. (And if you are not asking about the first thing, your question has about 10 paragraphs of irrelevant stuff that can be deleted. We don't need to know *why* you are modifying that C++ code ...) – Stephen C Aug 14 '21 at 23:20
  • I also noticed that the compilation errors don't match the code that you have shown us. If you want help with getting some code to compile, you need to show us the actual code. – Stephen C Aug 14 '21 at 23:22
  • My question is 2 folds because I wanted to state my goal, which is self-updating my app, but I was having issues because of my Launcher in C++, I can delete everything that's not about the C++ launcher. I've added the little code I took from said other stackoverflow post, it was just a test to see if I could at least list the files. I don't know how it really works. – Dazgol Aug 14 '21 at 23:30
  • OMG, you are using 3 technologies here? C++, Java and CMD? Are you sure about the technology choices you have made to solve this problem? I would consider a batch language, such as Batch, PowerShell or, even, VBScript / JScript. These are included with Windows and can be scripted with a text editor and do not require additional software installation. – Stephen Quan Aug 14 '21 at 23:48
  • @StephenQuan I had to use CMD to delete the file after shutdown because it can't delete itself while running, I don't really want to have a batch file just for that. Can java send a powerShell command? – Dazgol Aug 14 '21 at 23:51
  • I think you should try to reexpress your problem. Since your last comment indicates that your core application is Java. What I don't understand is why you're bothering with C++? Or must your application use both C++ and Java? From your code snippet, I could not identify why you could not use a scripting language, but, that means, you need to rework your question and explain your criteria more clearly. – Stephen Quan Aug 16 '21 at 02:19

0 Answers0