I need to develop a piece of code in an old legacy Visual C++ 6.0 system. I am invoking a stand-alone executable via a system call. This exe is supposed to create a file if processing goes OK or not create one if it fails. The name of the file to create is passed to the exe as a command-line argument. When I invoke this exe from a console window, in a certain case it fails to process and does not create the output file. However, when I invoke the same exe through the system call form my VC++ system, it fails but also creates an empty file. I invoke it using

CreateProcess()

. I have two questions:
1. Why is it creating the empty file?
2. To check for success/failure I am currently doing this:

if( _access( strDestFile, 0 ) == -1 ) {
// file does not exist
}

I guess I need to also check if the file is non-empty. What's the easiest way of doing it in VC++ 6.0?

Thanks!

Dani AI

Generated

Quick practical addendum for ’s thread. ’s suggestion to check file size solved the immediate detection need (as confirmed). Two complementary steps make the behavior deterministic and help find the root cause: (1) gather evidence about how and when the empty file is created, and (2) make the wrapper treat the child process outcome as authoritative instead of relying solely on file presence.

Common causes and how to check them:

  • Different working directory or a relative path: the child may be creating the file somewhere else. Pass an absolute path or set lpCurrentDirectory in CreateProcess and reproduce the exact command line from a console to confirm.
  • The child opens/truncates the output early (fopen/CREATE_ALWAYS) and leaves it empty on failure. Process-created temp->rename is the robust fix (see below).
  • Different startup/handle environment when launched from the app (redirected or closed STDOUT/STDERR, inherited handles). Capture child stdout/stderr via STARTUPINFO and bInheritHandles, or run a tool like Sysinternals Process Monitor to see which process creates/truncates the file and exactly when.

A practical wrapper pattern (after CreateProcess returns PROCESS_INFORMATION pi): wait for the process, read its exit code, and only accept the output file on a successful exit; if the exit is nonzero or the file is zero-length, remove it or treat it as failure. Example sketch:

// after CreateProcess that returned PROCESS_INFORMATION pi
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode = 0;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

// If child does not reliably set exit codes, fall back to checking file size via GetFileSizeEx

If the child can be modified, the best practice is: write to a temp filename and atomically rename/move it to the final name only on success (MoveFileEx or ReplaceFile). That removes ambiguity and avoids the empty-file symptom entirely. Also follow ’s debugging suggestion: reproduce both debug and release invocations so behavior differences are visible.

Recommended Answers

All 3 Replies

>> Why is it creating the empty file?
I'd suggest debugging the program and try to see where it fails and why.

You could use
_stat() to check both the file's existence and its size in one go.

Does it behave this way for both debug and release versions?

Good info from mitrmkar. A big +1 for using the debugger to step through the code and find where it is failing and what's going on when the file is being created. Set a break point or run-to-cursor where the test is done and start stepping through code from there.

Also, GetFileSize() might be another option for you.

>> Why is it creating the empty file?
I'd suggest debugging the program and try to see where it fails and why.

You could use
_stat() to check both the file's existence and its size in one go.

_stat worked, thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.