batch-filenotepad++7ziplaunchsilent

How to use Notepad++ as editor for 7zip, without showing a console window?


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:

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.


Solution

  • 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.