1

very noob here. Basically what I wanna do is that as soon as I run my program, it opens a txt file. Then starts a while loop that only ends whenever I close the file.

I know this is definitely more complex to do, if possible, than what I wrote down here, but I hope to learn something new :)

#include <iostream>
#include <windows.h>
using namespace std;

main()
{
        system("test.txt"); //open my file

        while(ProcessIsRunning()) //???
        {
                cout << "Process is currently running...";
                Sleep(1000);
        }
        
        cout << "Process has stopped running"; //when I close my file, exits while and outputs this

}
cppnoob
  • 11
  • 1
  • 3
    Where did you get the idea that `system("test.txt")` opens a file? Is your actual problem "I want to open a file in a different program and wait until that program closes it"? – molbdnilo Dec 04 '20 at 10:22
  • It's very unclear what you're asking for, if you want to open a file, look at `std::fstream`, but what do you mean by 'close the file'? You mean closing it inside your program, closing it externally? – Kaldrr Dec 04 '20 at 10:23
  • @molbdnilo apparently it works and opens my txt file. And what I wanna do is opening a file from my program and making my program wait until the process of the file I opened stops running – cppnoob Dec 04 '20 at 10:29
  • @Kaldrr closing the file externally, like with the red X. I simply want my program to run another program (in this case a txt file), and make it wait in a while loop until the process of the file I opened stops running. – cppnoob Dec 04 '20 at 10:31
  • You need the user to close the text file and hence the program, by physically clicking on the red X button of the window in which you are visualising the text file in your operative system, have I understood correctly? Then, you have to create a `while` loop with an always true condition, and put an `if` statement inside this loop, with a `break;` statement the moment the file is not open anymore – Giogre Dec 04 '20 at 10:43
  • @cppnoob It doesn't open a file, it executes "test.txt" as a shell command. If you're running Windows, it will try to execute the action associated with ".txt" files, which is opening it with Notepad by default. The function you're really looking for is [`ShellExecute`](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea) – molbdnilo Dec 04 '20 at 10:44
  • 2
    @cppnoob it looks to me like you're misunderstanding how 'reading a file' works in applications, it seems like you want a text editor like Notepad/Visual Studio Code to open and display the file to you, while you're waiting for it to close. Reading a file doesn't work like this in C++, it just allows you to read a file as a stream of bytes. If you want to open it externally, you need to start a child process with appropriate arguments, it will open the file in Notepad/VS Code/whatever you want, and wait for it to finish. – Kaldrr Dec 04 '20 at 10:51
  • @Kaldrr I don't want my program to read the text file, and whatever is written in. I want my program to run my txt file (like if I opened it manually), then whenever I manually close the txt file by clicking the red X, automatically recognize that the process of that txt file has stopped running. Sorry if I may not explain well but I'm very new to coding in general – cppnoob Dec 04 '20 at 11:26
  • 1
    @cppnoob There is no such concept of "executing a file" in computer science. Either this file is READ BY a program, or either this file IS an program (an executable) and therefore can be run. – A. Gille Dec 04 '20 at 12:51
  • @cppnoob What you want to do is implementing a program that watches a specific file being open/closed by external program. Something like: https://stackoverflow.com/questions/931093/how-do-i-make-my-program-watch-for-file-modification-in-c. OR, you want your program to run an external text-editor and to exit whenever the text-editor has terminated. – A. Gille Dec 04 '20 at 12:54

1 Answers1

0

The following code is for Windows only.

bool EditFileExternallyBlocking(const TCHAR *FilePathName)
{
    SHELLEXECUTEINFO ShellExecuteInfo;

    ShellExecuteInfo.cbSize = sizeof(ShellExecuteInfo);
    ShellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShellExecuteInfo.hwnd = NULL;
    ShellExecuteInfo.lpVerb = _T("edit");
    ShellExecuteInfo.lpFile = FilePathName;
    ShellExecuteInfo.lpParameters = NULL;
    ShellExecuteInfo.lpDirectory = NULL;
    ShellExecuteInfo.nShow = SW_SHOWDEFAULT;

    if (!ShellExecuteEx(&ShellExecuteInfo)) {
        return false;
    }

    if (ShellExecuteInfo.hProcess == NULL) {
        return false;
    }

    WaitForSingleObject(ShellExecuteInfo.hProcess, INFINITE);
    CloseHandle(ShellExecuteInfo.hProcess);
    return true;
}

bool EditFileExternallyPolling(const TCHAR *FilePathName, const std::function<void()> &Callback)
{
    SHELLEXECUTEINFO ShellExecuteInfo;

    ShellExecuteInfo.cbSize = sizeof(ShellExecuteInfo);
    ShellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShellExecuteInfo.hwnd = NULL;
    ShellExecuteInfo.lpVerb = _T("edit");
    ShellExecuteInfo.lpFile = FilePathName;
    ShellExecuteInfo.lpParameters = NULL;
    ShellExecuteInfo.lpDirectory = NULL;
    ShellExecuteInfo.nShow = SW_SHOWDEFAULT;

    if (!ShellExecuteEx(&ShellExecuteInfo)) {
        return false;
    }

    if (ShellExecuteInfo.hProcess == NULL) {
        return false;
    }

    while (WaitForSingleObject(ShellExecuteInfo.hProcess, 0) == WAIT_TIMEOUT) {
        Callback();
    }

    CloseHandle(ShellExecuteInfo.hProcess);
    return true;
}

int main()
{
    std::cout << "Blocking way: \n";
    std::cout << std::boolalpha << EditFileExternallyBlocking(_T("G:\\test_text_file.txt")) << '\n';
    std::cout << "Process has stopped running\n\n";

    std::cout << "Polling way: \n";
    std::cout << std::boolalpha << EditFileExternallyPolling(_T("G:\\test_text_file.txt"),
        []() {
            std::cout << "Process is currently running...\n";
            Sleep(1000);
        }
    ) << '\n';
    std::cout << "Process has stopped running\n\n";

    return 0;
}

Output

Blocking way:
true
Process has stopped running

Polling way:
Process is currently running...
Process is currently running...
Process is currently running...
Process is currently running...
Process is currently running...
Process is currently running...
Process is currently running...
true
Process has stopped running

Other possible return values for WaitForSingleObject should be handled at release time.


References

Sprite
  • 3,222
  • 1
  • 12
  • 29