C++: Check if a file is running - c++

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
}

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
ShellExecuteExA API
SHELLEXECUTEINFOA structure
WaitForSingleObject API

Related

my program isnt writing to process memory. how do i debug this? im new to wpm and rpm

`
#include <iostream>
#include <windows.h>
#include <Tlhelp32.h>
HANDLE hProc = NULL;
DWORD pID;
bool attachProc(char* procName)
{
PROCESSENTRY32 procEntry32;
procEntry32.dwSize = sizeof(PROCESSENTRY32);
auto hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcSnap == INVALID_HANDLE_VALUE)
{
std::cout << "FAILED to take snapshot of processes\n";
return false;
}
while(Process32Next(hProcSnap, &procEntry32))
{
std::cout << procEntry32.szExeFile << std::endl;
if (procEntry32.th32ProcessID != 996)
{
if (!strcmp(procName, procEntry32.szExeFile))
{
std::cout << "found process " << procEntry32.szExeFile << " with process id " << procEntry32.th32ProcessID << std::endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,procEntry32.th32ProcessID);
pID = procEntry32.th32ProcessID;
if (hProc == NULL)
{
std::cout << "failed getting handle to process" << std::endl;
}
CloseHandle(hProcSnap);
return true;
}
}
}
std::cout << "couldnt find " << procName << "in the process snapshot" << std::endl;
CloseHandle(hProcSnap);
return false;
}
template <class dataType>
void wpm(dataType valToWrite, DWORD adressToWrite)
{
WriteProcessMemory(hProc, (PVOID)adressToWrite, &valToWrite, sizeof(dataType), 0);
}
template <class dataType>
dataType rpm(DWORD adressToRead)
{
dataType rpmBuffer;
ReadProcessMemory(hProc, (PVOID)adressToRead, &rpmBuffer, sizeof(dataType), 0);
return rpmBuffer;
}
int main()
{
DWORD memoryAdress = 0x288469A7A28;
int value = 1
attachProc((char*)"dummy.exe");
while (true)
{
wpm<int>(value, memoryAdress);
}
}
`
i think there is a problem in getting the handle but i dont know where or how do i debug this.
is there any different way on how to get a handle? bestsides FindWindow() because this doesnt work either
i was trying to write process memory but id didnt work for some reason the adress should be good i tested it in cheat engine multiple times

How to find out whether child process still is running?

I am spawning a process in my application:
int status = posix_spawnp(&m_iProcessHandle, (char*)strProgramFilepath.c_str(), NULL, NULL, argsWrapper.m_pBuffer, NULL);
When I want to see if the process is still running, I use kill:
int iReturn = kill(m_iProcessHandle,0);
But after the spawned process has finished its work, it hangs around. The return value on the kill command is always 0. Not -1. I am calling kill from within the code, but if I call it from the command line, there is no error - the spawned process still exists.
Only when my application exits does the command-line kill return "No such process".
I can change this behavior in my code with this:
int iResult = waitpid(m_iProcessHandle, &iStatus, 0);
The call to waitpd closes down the spawned process and I can call kill and get -1 back, but by then I know the spawned process is dead.
And waitpd blocks my application!
How can I test a spawned processes to see if it is running, but without blocking my application?
UPDATE
Thanks for the help! I have implemented your advise and here is the result:
// background-task.cpp
//
#include <spawn.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include "background-task.h"
CBackgroundTask::CBackgroundTask()
{
// Initialize member variables
m_iProcessHandle = 0;
}
CBackgroundTask::~CBackgroundTask()
{
// Clean up (kill first)
_lowLevel_cleanup(true);
}
bool CBackgroundTask::IsRunning()
{
// Shortcuts
if (m_iProcessHandle == 0)
return false;
// Wait for the process to finish
int iStatus = 0;
int iResult = waitpid(m_iProcessHandle, &iStatus, WNOHANG);
return (iResult != -1);
}
void CBackgroundTask::Wait()
{
// Wait (clean up without killing)
_lowLevel_cleanup(false);
}
void CBackgroundTask::Stop()
{
// Stop (kill and clean up)
_lowLevel_cleanup(true);
}
void CBackgroundTask::_start(const string& strProgramFilepath, const string& strArgs, int iNice /*=0*/)
{
// Call pre-start
_preStart();
// Split the args and build array of char-strings
CCharStringAarray argsWrapper(strArgs,' ');
// Run the command
int status = posix_spawnp(&m_iProcessHandle, (char*)strProgramFilepath.c_str(), NULL, NULL, argsWrapper.m_pBuffer, NULL);
if (status == 0)
{
// Process created
cout << "posix_spawn process=" << m_iProcessHandle << " status=" << status << endl;
}
else
{
// Failed
cout << "posix_spawn: error=" << status << endl;
}
// If process created...
if(m_iProcessHandle != 0)
{
// If need to adjust nice...
if (iNice != 0)
{
// Change the nice
stringstream ss;
ss << "sudo renice -n " << iNice << " -p " << m_iProcessHandle;
_runCommand(ss.str());
}
}
else
{
// Call post-stop success=false
_postStop(false);
}
}
void CBackgroundTask::_runCommand(const string& strCommand)
{
// Diagnostics
cout << "Running command: " << COUT_GREEN << strCommand << endl << COUT_RESET;
// Run command
system(strCommand.c_str());
}
void CBackgroundTask::_lowLevel_cleanup(bool bKill)
{
// Shortcuts
if (m_iProcessHandle == 0)
return;
// Diagnostics
cout << "Cleaning up process " << m_iProcessHandle << endl;
// If killing...
if (bKill)
{
// Kill the process
kill(m_iProcessHandle, SIGKILL);
}
// Diagnostics
cout << "Waiting for process " << m_iProcessHandle << " to finish" << endl;
// Wait for the process to finish
int iStatus = 0;
int iResult = waitpid(m_iProcessHandle, &iStatus, 0);
// Diagnostics
cout << "waitpid: status=" << iStatus << " result=" << iResult << endl;
// Reset the process-handle
m_iProcessHandle = 0;
// Call post-stop with success
_postStop(true);
// Diagnostics
cout << "Process cleaned" << endl;
}
Until the parent process calls one of the wait() functions to get the exit status of a child, the child stays around as a zombie process. If you run ps during this time, you'll see that the process is still there in the Z state. So kill() returns 0 because the process exists.
If you don't need to get the child's status, see How can I prevent zombie child processes? for how you can make the child disappear immediately when it exits.

Cast std::thread as HANDLE to call TerminateThread() [duplicate]

This question already has answers here:
How to get the winapi id of a thread that has been created using the standard library?
(2 answers)
Closed 7 years ago.
Could it be posible to cast or convert a std::thread thread in C++ to a HANDLE in Windows?
I've been trying to manage threads in Windows with WINAPI functions for threads but I can't get it to work...
#include <thread>
#include <string>
#include <iostream>
#include <windows.h>
void Hi(std::string n){
while(true){
std::cout<<"Hi :3 "<<n<<"\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(void){
std::thread first(Hi, "zoditu");
first.detach();
getc(stdin);
//SuspendThread((void*)first.native_handle());
TerminateThread((void*)first.native_handle(), (unsigned long)0x00);
CloseHandle((void*)first.native_handle());
std::cout<<"No D:!!\n";
getc(stdin);
return 0;
}
But seems to do nothing because thread keeps spawning "Hi's" in the console... Could there be a way to "kill" it using WINAPI?
I don't think there is anything wrong with using the value returned by std::thread::native_handle() directly with the Win32 API functions (i.e., a conversion is not required).
The following program works for me. However, it usually (always?) crashes if the thread is terminated while it is actively executing but works just fine if the thread is suspended before terminating. As you are aware and others have pointed out it is generally not a good idea to terminate a thread.
But to answer your question the Win32 API seems to work as expected without any additional conversions. The following program works for me.
Program:
#include <windows.h>
#include <iostream>
#include <string>
#include <thread>
void foo()
{
while (true)
{
std::cout << "foo()\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(void)
{
std::thread first(foo);
bool isFinished = false;
while (!isFinished)
{
char ch = ::getchar();
::getchar(); // Swallow the new line character
if (ch == 'e')
{
isFinished = true;
}
else if (ch == 's')
{
DWORD result = ::SuspendThread(first.native_handle());
if (result != -1)
{
std::cout << "Successfully suspended thread\n";
}
else
{
std::cout << "Failed to suspend thread: failure resson " << ::GetLastError() << "\n";
}
}
else if (ch == 'r')
{
DWORD result = ::ResumeThread(first.native_handle());
if (result != -1)
{
std::cout << "Successfully resumed thread\n";
}
else
{
std::cout << "Failed to resume thread: failure resson " << ::GetLastError() << "\n";
}
}
else if (ch == 'k')
{
DWORD result = ::TerminateThread(first.native_handle(), 1);
if (result != 0)
{
std::cout << "Successfully terminated thread\n";
}
else
{
std::cout << "Failed to terminate thread: failure resson " << ::GetLastError() << "\n";
}
}
else
{
std::cout << "Unhandled char '" << ch << "'\n";
}
}
first.detach();
std::cout << "waiting to exit main...";
::getchar();
std::cout << "exiting...\n";
return 0;
}
Sample Output (comments added by me):
foo()
foo()
foo()
foo()
s
Successfully suspended thread // This was successful since 'foo()' is no longer printing
r
Successfully resumed thread // This was successful since 'foo()' is again printing
foo()
foo()
foo()
foo()
s
Successfully suspended thread // Worked again
k
Successfully terminated thread // Says it works...
r
Successfully resumed thread // Termination must have worked because resuming did not cause 'foo' to start printing
e
waiting to exit main...
exiting...

Is C++'s system() synchronized?

I'm writing a small utility which is supposed to launch several commands in parallel using system() and wait for their results for logging purposes. However, even though I'm calling system() on different threads, by looking at my Activity Monitor I only see one instance of each command at a time. It looks like system is internally synchronized on a mutex, and only one execution is allowed at each time, however this looks like a huge limitation, can someone confirm this behavior? Do you have any ideas on how to solve it?
Update by looking at the threads execution flow, it looks like they're effectively synchronizing on a mutex. Is there an alternative system() which doesn't do that?
I should mention I'm using C++11 (w/ clang and libc++) on Mac OS 10.7.5.
Update code is:
void Batch::run()
{
done.clear();
generator->resetGeneration();
while(generator->hasMoreParameters())
{
// Lock for accessing active
unique_lock<mutex> lock(q_mutex, adopt_lock);
// If we've less experiments than threads
if (active.size() < threads)
{
Configuration conf = generator->generateParameters();
Experiment e(executable, conf);
thread t(&Experiment::run, e, reference_wrapper<Batch>(*this));
thread::id id = t.get_id();
active.insert(id);
t.detach();
}
// Condition variable
q_control.wait(lock, [this] { return active.size() < threads; } );
}
}
void Batch::experimentFinished(std::thread::id pos)
{
unique_lock<mutex> lock(q_mutex, adopt_lock);
active.erase(pos);
lock.unlock();
q_control.notify_all();
}
void Experiment::run(Batch& caller)
{
// Generate run command
stringstream run_command;
run_command << executable + " ";
ParameterExpression::printCommandLine(run_command, config);
if (system(run_command.str().c_str()))
stats["success"] = "true";
else
stats["success"] = "false";
caller.experimentFinished(this_thread::get_id());
}
Just to be clear: the spawning and handling of threads works fine and does what it needs to do, but it looks like you can have just one instance of system() running at a time.
Thanks
POSIX has this to say about system(3):
Using the system() function in more than one thread in a process or when the SIGCHLD signal is being manipulated by more than one thread in a process may produce unexpected results.
Due to the way that SIGCHLD must be blocked during the execution, running system calls concurrently doesn't really work. If you want multiple threads to run external tasks, you'll need to write a bit more code (handling fork/exec/wait yourself).
To whoever comes later, popen did the trick, as it doesn't internally keep a mutex. The code to make it work is
FILE* proc;
char buff[1024];
// Keep track of the success or insuccess of execution
if (!(proc = popen(run_command.str().c_str(), "r")))
stats["success"] = "false";
else
stats["success"] = "true";
// Exhaust output
while(fgets(buff, sizeof(buff), proc) != nullptr);
pclose(proc);
In case this helps, I wrote some fork/exec/wait code in C++ a while back. It captures output into a std::string.
As #Mat points out, fork, exec, and wait aren't really designed to be uses in a multi-threaded process.
So this is more useful if multi-process can be a substitute for multi-threaded in your application.
bool Utility::execAndRedirect(std::string command, std::vector<std::string> args, std::string& output, int& status)
{
int error;
int pipefd[2];
int localStatus;
if (pipe(pipefd) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
return false;
}
pid_t pid = fork();
if (pid == 0)
{
char** argsC;
argsC = new char*[args.size() + 2];
argsC[0] = new char[command.size() + 1];
strncpy(argsC[0], command.c_str(), command.size());
argsC[0][command.size()] = '\0';
for (size_t count = 0; count < args.size(); count++)
{
argsC[count + 1] = new char[args[count].size() + 1];
strncpy(argsC[count + 1], args[count].c_str(), args[count].size());
argsC[count + 1][args[count].size()] = '\0';
}
argsC[args.size() + 1] = NULL;
close(pipefd[0]);
if (dup2(pipefd[1], STDOUT_FILENO) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
if (dup2(pipefd[1], STDERR_FILENO) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
close(pipefd[1]);
if (execvp(command.c_str(), argsC) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
}
else if (pid > 0)
{
size_t BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE + 1];
close(pipefd[1]);
ostringstream oss;
ssize_t num_b;
while ((num_b = read(pipefd[0], buffer, BUFFER_SIZE)) != 0)
{
buffer[num_b] = '\0';
oss << buffer;
}
output = oss.str();
waitpid(pid, &localStatus, 0);
close(pipefd[0]);
}
else
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
return false;
}
if(WIFEXITED(localStatus))
{
status = WEXITSTATUS(localStatus);
//DateTime current = DateTime::now(); //this is a custom class
if(status == 0)
{
return true;
}
else
{
return false;
}
}
else
{
error = errno;
cerr << "Executing command '" << command << "' failed: child didn't terminate normally" << endl;
return false;
}
}

Thread on Windows

I have a small question about threading in Windows. I have the following code :
main.cpp
int main(int ac, char **av)
{
std::vector<Mthread *> mythread;
std::list<std::string> stack;
DWORD id = 0;
stack.push_back("Maison");
stack.push_back("Femmes");
stack.push_back("Fetes");
stack.push_back("Voitures");
stack.push_back("Nounours");
while (id != 5)
{
mythread.push_back(new Mthread());
mythread[mythread.size() - 1]->initThread(&stack, id);
id++;
}
id = 0;
while (id != 5)
{
WaitForInputIdle(mythread[id]->getThread(), INFINITE);
id++;
}
return (1);
}
and Mthread.cpp who is creating my Mthread class.
Mthread::Mthread() {}
Mthread::~Mthread() {}
HANDLE Mthread::getThread(void) const
{
return (this->thread);
}
bool Mthread::initThread(std::list<std::string> *list, DWORD ID)
{
this->save = list;
this->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Mthread::ThreadFunc, (LPVOID)list, 0, &ID);
if (this->thread == NULL)
{
std::cout << "Erreur lors du lancement du thread" << std::endl;
return (false);
}
else
{
return (true);
}
}
void Mthread::ThreadFunc(LPVOID list)
{
std::cout << " is launch" << std::endl;
}
The code is working, but I have a small problem : no string is written on the terminal.
But, if I change my code to :
bool Mthread::initThread(std::list<std::string> *list, DWORD ID)
{
this->save = list;
this->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Mthread::ThreadFunc, (LPVOID)list, 0, &ID);
if (this->thread == NULL)
{
std::cout << "Erreur lors du lancement du thread" << std::endl;
return (false);
}
else
{
std::cout << "OK" << std::endl;
return (true);
}
}
Well "OK" and "is launch" is written 5 times on the terminal. I don't understand why.
When I pass a small string a to cout it seems to be working, but when I don't nothing is written.
short answer: I guess your main() terminates before the threads have a chance to run. add a sleep() or something similar to main.
More complex answer:
- threads and main run independently from eachother. You have to wait in your main until you know you can exit main.
- your program tends to be unsafe since the vector is accessed by all threads without any synchronisation. Read up on locks, mutexes and semaphores!
Before terminating, your program should wait until the threads have finished their job. On windows, take a look at WaitForMultipleObjects.