c\c++: how can i test if the file is used on another program?

Pages: 12
i know the file name and folder, but how can i test if is open or used on another program\process?
Last edited on
I don't think standard C++ provides a way of doing that.
i did these
1
2
3
4
5
6
7
8
FILE *text;
        text = fopen ("C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.exe", "r+");
        while(text==NULL)
        {
            DoEvents();
        }
        fclose(text);
        run("C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.exe", "" ,"C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug");

but the OS give me the that error that the file is open... when the 'run()' is called
Last edited on
let me show you the run():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void run(string FileName, string Parameters="", string ActualFolder="")
{
    SHELLEXECUTEINFO ShExecInfo={0};
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = "open";
    ShExecInfo.lpFile = FileName.c_str();
    if(Parameters!="")
        ShExecInfo.lpParameters = Parameters.c_str();
    if(ActualFolder!="")
        ShExecInfo.lpDirectory = ActualFolder.c_str();
    ShExecInfo.nShow = SW_SHOWNORMAL;
    ShExecInfo.hInstApp = NULL;


    ShellExecuteEx(&ShExecInfo);
    if(ShExecInfo.hProcess)
        CloseHandle(ShExecInfo.hProcess);
}

the program that i execute it will close after the work... the SHELLEXECUTEINFO structure can wait(i mean before close the handle) until the process is closed?
1
2
3
4
5
6
7
8
	HANDLE  hFile = INVALID_HANDLE_VALUE;
...
	hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		AbortMessage(_T("This file is missing or already loaded in another instance of Emu42."));
		goto restore;
	}

Excerpt from FILES.C of The sources of Emu42 for Win32 you easily find here: https://hp.giesselink.com/emu42.htm
don't works for what i need.... at least using the Sleep():
Sleep(2000);
will works.... but isn't the best way...
the SHELLEXECUTEINFO structure don't have a flag for wait?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DWORD run(/*...*/){
    //...
    if (!ShellExecuteEx(&ShExecInfo))
        return GetLastError();
    //...
    return ERROR_SUCCESS;
}

DWORD result;
while ((result = run(/*...*/)) == ERROR_SHARING_VIOLATION){
    //tell the user to close the file
    //wait
}
if (result == ERROR_SUCCESS)
    //handle no error
else
    //handle error 
helios the Operation System show us the message box with the error... can i avoid the message box?

but the exe is executed
the SEE_MASK_FLAG_NO_UI flag works like a charm:
https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/ns-shellapi-_shellexecuteinfoa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DWORD run(string FileName, string Parameters="", string ActualFolder="")
{
    SHELLEXECUTEINFO ShExecInfo={0};
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = "open";
    ShExecInfo.lpFile = FileName.c_str();
    if(Parameters!="")
        ShExecInfo.lpParameters = Parameters.c_str();
    if(ActualFolder!="")
        ShExecInfo.lpDirectory = ActualFolder.c_str();
    ShExecInfo.nShow = SW_SHOWNORMAL;
    ShExecInfo.hInstApp = NULL;
    
    if (!ShellExecuteEx(&ShExecInfo))
        return GetLastError();
    
    if(ShExecInfo.hProcess)
        CloseHandle(ShExecInfo.hProcess);
    
    return ERROR_SUCCESS;
}

i'm sorry but can i change these function for boolean?
true for sucess and false for other values
the best was these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define True 0

DWORD run(string FileName, string Parameters="", string ActualFolder="")
{
    SHELLEXECUTEINFO ShExecInfo={0};
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = "open";
    ShExecInfo.lpFile = FileName.c_str();
    if(Parameters!="")
        ShExecInfo.lpParameters = Parameters.c_str();
    if(ActualFolder!="")
        ShExecInfo.lpDirectory = ActualFolder.c_str();
    ShExecInfo.nShow = SW_SHOWNORMAL;
    ShExecInfo.hInstApp = NULL;

    if (!ShellExecuteEx(&ShExecInfo))
        return GetLastError();

    if(ShExecInfo.hProcess)
        CloseHandle(ShExecInfo.hProcess);

    return ERROR_SUCCESS;
}


used:
1
2
3
4
while(run("C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.exe", "" ,"C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug")!= True)
        {
            DoEvents();
        }

thank you so much for all.. . thank you
Last edited on
the run function it's limited.... but after some search i found the right solution: i need to wait that the process is ended... for that i need the WaitForSingleObject() function with the ShExecInfo.hProcess.... in these case we must use the SEE_MASK_NOCLOSEPROCESS flag.
the SEE_MASK_FLAG_NO_UI flag avoid the message box errors.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
DWORD run(string FileName, string Parameters="", string ActualFolder="", bool WaitUntilFinish=true)
{
    //Always clean the structure instead random values:
    SHELLEXECUTEINFO ShExecInfo={0};

    //The structure size:
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);

    //These flags are for avoid the error messages box and for get the process handle:
    ShExecInfo.fMask = SEE_MASK_FLAG_NO_UI|SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;

    //The program that it's for execute:
    ShExecInfo.lpVerb = "open";
    ShExecInfo.lpFile = FileName.c_str();
    ShExecInfo.nShow = SW_SHOWNORMAL;
    ShExecInfo.hInstApp = NULL;

    //Adding parameters:
    if(Parameters!="")
        ShExecInfo.lpParameters = Parameters.c_str();

    //Adding the Working directory(best is using the program folder):
    if(ActualFolder!="")
        ShExecInfo.lpDirectory = ActualFolder.c_str();

    //Execute the program and if there any error, it will return it:
    if (!ShellExecuteEx(&ShExecInfo))
        return GetLastError();

    //Wait Until process ends:
    if(ShExecInfo.hProcess && WaitUntilFinish==true)
        WaitForSingleObject(ShExecInfo.hProcess, INFINITE);

    //The Process Handle must be destroyed:
    if(ShExecInfo.hProcess)
        CloseHandle(ShExecInfo.hProcess);

    //Executed success(zero):
    return ERROR_SUCCESS;
}

now here how i use it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//......
//compile the *.cpp file to object file:
        string compilerPath = "C:\\Program Files\\mingw-w64\\x86_64-7.2.0-win32-seh-rt_v5-rev1\\mingw64\\bin\\";
        string compiler_exe = "x86_64-w64-mingw32-g++.exe";

        string FileName1 = compilerPath + compiler_exe;
        string parameters = "-Wall -g -std=c++14  -c \"C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.cpp\" -o \"C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.o\"";
        string actualFolder = compilerPath;
        run(FileName1, parameters);

        //creating the exe file using the object file and libraries and dependencies:
        parameters="-o C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.exe C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.o -static-libstdc++ -static-libgcc -fpermissive \"C:\\Program Files\\mingw-w64\\x86_64-7.2.0-win32-seh-rt_v5-rev1\\mingw64\\x86_64-w64-mingw32\\lib\\libgdi32.a\"";
        run(FileName1,parameters);

        //Execute exe file:
        run("C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug\\test.exe", "" ,"C:\\Users\\Cambalinho\\Documents\\CB\\testfolder\\bin\\Debug");
//........... 

like you see, now, i don't use that loops.... because the process must end, for the next call ;)
thank you so much for all
I think this showcases why it's important to explain what you're trying to do.
Helios: i do what i can... maybe i'm learning more how i can express my self...
but sometimes i don't understand somethings and the error, sometimes, can confuse me more
maybe i must focus more on objective and not so much on the error
Last edited on
@Cambalinho
1
2
3
    //Wait Until process ends:
    if(ShExecInfo.hProcess && WaitUntilFinish==true)
        WaitForSingleObject(ShExecInfo.hProcess, INFINITE);

Do you realy like to wait for ever? INFINITE, endlessly? ("... the function will return only when the object is signaled.")
I would have a look at the process' CPU usage and disk IO. When CPU at max and no IO at all for one...two minutes then pull the plug. How to query this data on a PC? No idea, I am a mainframe dinosaur. But "function will return only when the object is signaled" smells like "only on manual intervention".
I would have a look at the process' CPU usage and disk IO. When CPU at max and no IO at all for one
I've never seen anyone code a process termination wait like this. Seems rather silly, honestly.

Waiting infinity for GCC to return seems acceptable to me. I've seen GCC crash, but never hang. Waiting infinity for test.exe may or may not be acceptable, I don't know. Maybe the rest of the caller has been coded assuming the child process succeeded, and if the child hangs the parent may as well also hang, since it's no longer possible for it to succeed. The full paths being hard-coded into the program tell me this is quite likely.
Last edited on
I've never seen anyone code a process termination wait like this.
Look at me and for the first time now you see "this anyone", a rare exemplar ;)

Seems rather silly, honestly.
No, it is not, let me explain. CADAM running on IBM mainframes was sometimes not too stable depending on the release. As the user had no chance to restart a machine the operator had to force it, what was incommoding when it happend too often for so many users. So I've set up a PROP (programmable operator) as "watch dog". A machine using a big share of CPU and doing IO was considered working as it possibly still saved some results. In contrast, without IO for about one minute or two but using CPU it was forced and restarted. And the user was happy he could continue work after a short while without the need to call the mostly quite unfriendly operator.

Also on the PC it is rather silly -- IMO, honestly -- to end a proces immediately when TaskManager reports "no reply". Even in this case it could still work, but so heavily that there is no time left to tell TaskManager "I'm still alive."
A machine using a big share of CPU and doing IO was considered working as it possibly still saved some results. In contrast, without IO for about one minute or two but using CPU it was forced and restarted.
For a whole system this heuristic is usually reasonable, even now. We're talking about a single process, here.

Also on the PC it is rather silly -- IMO, honestly -- to end a proces immediately when TaskManager reports "no reply". Even in this case it could still work, but so heavily that there is no time left to tell TaskManager "I'm still alive."
Quite the contrary, actually. Windows detects that a GUI process is "not responding" because its event loop has stopped processing events. Such processes do have a way to tell the system "I'm still alive": they just need to continue processing events. Console processes don't have event loops, so you'll never see Task Manager report a console process as "not responding".
That said, I don't know what you mean by "end a proces immediately when TaskManager reports 'no reply'". The system never automatically kills non-responding processes, although it may give the user the option to kill them.
For a whole system this heuristic is usually reasonable, even now. We're talking about a single process, here.
IMO it's also reasonable for a single process. BTW, also the CADAM system consisted of several 'disconnected' machines (service "user" without console attached, running in the "background") it was the single process of the interactive "user"/machine that caused trouble and had to be forced/taken off the run-list by operator. (And - sorry - by "user" I do not mean the human one sitting in front of the screen, for me a "user" is a virtual entity consisting of virtual CPU, virtual spooling devices (puncher, reader), virtual printer, with or without real console attached.)

That said, I don't know what you mean by "end a process immediately when TaskManager reports 'no reply'".
Wrong wording, by 'no reply' I meant "not responding". And with immediately I mean instantaneously/at once/in no time. And 'end a process' I mean the options to do so offered by Task-Manager, 'end the task' or 'end the process' or 'end the process structure', interactively.

The system never automatically kills non-responding processes, although it may give the user the option to kill them.
Yes, I know, there is no "programmable operator" on the PC, it's me, on the PC I am the only operator (I hope).

To say it in your words, it seems rather silly, honestly, to distinguish a single process from a virtual single process.
"Do you realy like to wait for ever? INFINITE, endlessly? ("... the function will return only when the object is signaled.")"
why use milliseconds???? i don't need time, but the process ends correctly and go to the next process.. because the 2nd process it's dependent from the 1st process
Pages: 12