1

This question could be generalized as: How to launch a given process with any intermediate process spawned having the same lifetime as the launched process, and without showing a console window. Specific arguments must be passed to the final process, but no arguments can be passed in the initial call.

To use Notepad++ as editor for 7zip you would need to launch notepad++.exe with the -multiInst command line parameter, otherwise it instantly closes and forwards arguments to the existing instance. Since 7zip picks up the changes you did to its temp file when the invoked program closes, you never get a chance to edit it.

Problem is, 7zip doesn't allow you to enter arguments for whatever program you're configuring as editor.

Obvious solutions that don't work, already tried:

  • Call a batch file, but then I'm stuck with an unsightly (and easy to close accidentally) console window for the duration of the edition - not acceptable.
  • Call a batch file which uses start to call Notepad++ : the console window does close, but unfortunately the batch executor process which is what Notepad++ was watching is gone, so it thinks you're already done editing, i.e. back to the initial problem.
  • Use wscript, which doesn't show a console window. Tracking the process lifetime is complex however (Wait for program to complete) and it makes you rely on old tech in maintenance mode that has a malware connotation.

How would you go about this? No solution I've tried myself or read about has been fully satisfying.

Note: this is not exactly the same question as Execute Batch File without Command line visible since this has the added requirement that whatever launcher used must stay open for the whole lifetime of the launched process, and that you can't pass command line arguments to the launcher.

Gabriel Morin
  • 667
  • 8
  • 13
  • I know this is kind of old, but did you ever find a solution? I'm facing the exact same problem right now. – wlfbck Jan 25 '21 at 11:40
  • 1
    @wlfbck As it turns out, I did. I've now shared the code I'm using in an answer. Hope it helps! – Gabriel Morin Feb 06 '21 at 06:11
  • there are lots of duplicates: [How to run a batch file without launching a “command window”?](https://superuser.com/q/140047/241386), [Execute Batch File without Command line visible](https://stackoverflow.com/q/23557720/995714), [How do I create a Windows Batch file that does not show the Command Prompt when executed?](https://superuser.com/q/233348/241386) – phuclv Feb 06 '21 at 08:14
  • Does this answer your question? [Execute Batch File without Command line visible](https://stackoverflow.com/questions/23557720/execute-batch-file-without-command-line-visible) – phuclv Feb 06 '21 at 08:15
  • @phuclv I've gone through most of those answers. Most of them rely on wscript which is a technology in maintenance mode which I wouldn't recommend for a long-term solution, and that I dislike due to its association with malware. Furthermore none of those answers covers the issue with 7zip itself, and some of them assume you can pass arguments, which you can't in this case. – Gabriel Morin Feb 07 '21 at 21:07
  • This question is also different because of the requirement that whatever is used as the launcher must STAY open while you are editing the file so 7zip picks up the changes when you're done. – Gabriel Morin Feb 07 '21 at 21:14
  • `Call a batch file which uses start to call Notepad++ : doesn't work, the called batch file closes immediately so Notepad++ thinks you're already done` - `start /wait` would cure that. – Stephan Feb 08 '21 at 12:19
  • @Stephan Please re-read the title of my question. `start /wait` will keep the batch console window open. – Gabriel Morin Feb 11 '21 at 04:08
  • Re-read your question yourself. You can either have the script wait for a program to finish or continue without waiting. You can't have both at the same time. You can [hide the window](https://stackoverflow.com/search?q=%5Bbatch-file%5D+hide+window) though. – Stephan Feb 11 '21 at 08:34

1 Answers1

1

I ended up writing my own utility which I'm tentatively calling NoConsoleProgramLauncher to serve as an intermediate between 7z and Notepad++. It's rough first draft code, but I thought sharing it might still be useful since this question has been without answer for three years.

#include <fstream>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <filesystem>

HINSTANCE hInst;

void launchProcess(std::wstring commandLine);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    //Get current executable's location
    HMODULE hModule = GetModuleHandleW(NULL);
    WCHAR executableFolder[MAX_PATH];
    GetModuleFileNameW(hModule, executableFolder, MAX_PATH);
    std::experimental::filesystem::v1::path path(executableFolder);
    path.remove_filename();
    path.append(L"NoConsoleProgramLauncher_Arguments.txt");
    std::wifstream infile(path);
    std::wstring commandLine;
    std::getline(infile, commandLine);
    commandLine += L" ";
    commandLine += lpCmdLine;
    launchProcess(commandLine);
}

void launchProcess(std::wstring commandLine)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Start the child process. 
    if (!CreateProcess(NULL,   // No module name (use command line)
        &commandLine[0],        // Command line - C++ 11 guarantees that string's internal buffer is contiguous and null-terminated.
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        CREATE_NO_WINDOW,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi)           // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Close process and thread handles. 
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

Basically, if you've done a minimum of C++ coding before, it's a matter of pasting this into a new Visual Studio 2017 Windows Desktop Application project, fixing up the includes if needed, and building.

As you can see in the source code, when launched the executable looks for a file in the same folder as itself named "NoConsoleProgramLauncher_Arguments.txt", and calls the command line it finds in there. As specified in the question, no console window will be shown, and the program will wait for the spawned process to terminate before exiting, so 7zip keeps waiting to pick up the changes.

This is what I put in my NoConsoleProgramLauncher_Arguments.txt file:

"C:\Program Files (x86)\Notepad++\notepad++.exe" -multiInst -nosession

And in the 7zip configuration, I've set the editor to point to my NoConsoleProgramLauncher.exe program.

The real solution would of course be to gently pester the 7z authors about this, or better, submit a pull request to 7z to implement passing arguments to your editor of choice.

Gabriel Morin
  • 667
  • 8
  • 13