- enhancement: when running a program, redirect a data file to its stdin
This commit is contained in:
parent
4da3b6d1fa
commit
7bb59955e6
1
NEWS.md
1
NEWS.md
|
@ -7,6 +7,7 @@ Version 0.7.3
|
||||||
- fix: the "add bookmark" menu item is not correctly disabled on a bookmarked line
|
- fix: the "add bookmark" menu item is not correctly disabled on a bookmarked line
|
||||||
- enhancement: "use utf8 by default" in editor's misc setting
|
- enhancement: "use utf8 by default" in editor's misc setting
|
||||||
- fix: syntax issues not correctly cleared when the file was saved as another name.
|
- fix: syntax issues not correctly cleared when the file was saved as another name.
|
||||||
|
- enhancement: when running a program, redirect a data file to its stdin
|
||||||
|
|
||||||
Version 0.7.2
|
Version 0.7.2
|
||||||
- fix: rainbow parenthesis stop functioning when change editor's general options
|
- fix: rainbow parenthesis stop functioning when change editor's general options
|
||||||
|
|
|
@ -197,12 +197,26 @@ void CompilerManager::run(const QString &filename, const QString &arguments, con
|
||||||
if (mRunner!=nullptr) {
|
if (mRunner!=nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
QChar redirectChar = '0';
|
||||||
|
QString redirectInputFilename;
|
||||||
|
bool redirectInput=false;
|
||||||
|
if (pSettings->executor().redirectInput()
|
||||||
|
&& !pSettings->executor().inputFilename().isEmpty()) {
|
||||||
|
redirectInput =true;
|
||||||
|
redirectChar = '1';
|
||||||
|
redirectInputFilename = pSettings->executor().inputFilename();
|
||||||
|
}
|
||||||
if (pSettings->executor().pauseConsole() && programHasConsole(filename)) {
|
if (pSettings->executor().pauseConsole() && programHasConsole(filename)) {
|
||||||
QString newArguments = QString(" 0 \"%1\" %2").arg(toLocalPath(filename)).arg(arguments);
|
QString newArguments = QString(" %1 \"%2\" %3")
|
||||||
|
.arg(redirectChar)
|
||||||
|
.arg(toLocalPath(filename)).arg(arguments);
|
||||||
mRunner = new ExecutableRunner(includeTrailingPathDelimiter(pSettings->dirs().app())+"ConsolePauser.exe",newArguments,workDir);
|
mRunner = new ExecutableRunner(includeTrailingPathDelimiter(pSettings->dirs().app())+"ConsolePauser.exe",newArguments,workDir);
|
||||||
|
if (redirectInput)
|
||||||
|
mRunner->setRedirectConsoleProgram(true);
|
||||||
} else {
|
} else {
|
||||||
mRunner = new ExecutableRunner(filename,arguments,workDir);
|
mRunner = new ExecutableRunner(filename,arguments,workDir);
|
||||||
}
|
}
|
||||||
|
mRunner->setRedirectInputFilename(redirectInputFilename);
|
||||||
connect(mRunner, &ExecutableRunner::finished, this ,&CompilerManager::onRunnerTerminated);
|
connect(mRunner, &ExecutableRunner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||||
connect(mRunner, &ExecutableRunner::finished, pMainWindow ,&MainWindow::onRunFinished);
|
connect(mRunner, &ExecutableRunner::finished, pMainWindow ,&MainWindow::onRunFinished);
|
||||||
connect(mRunner, &ExecutableRunner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
|
connect(mRunner, &ExecutableRunner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
|
||||||
|
|
|
@ -12,7 +12,8 @@ ExecutableRunner::ExecutableRunner(const QString &filename, const QString &argum
|
||||||
mFilename(filename),
|
mFilename(filename),
|
||||||
mArguments(arguments),
|
mArguments(arguments),
|
||||||
mWorkDir(workDir),
|
mWorkDir(workDir),
|
||||||
mStop(false)
|
mStop(false),
|
||||||
|
mRedirectConsoleProgram(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,26 @@ void ExecutableRunner::stop()
|
||||||
mStop = true;
|
mStop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExecutableRunner::redirectConsoleProgram() const
|
||||||
|
{
|
||||||
|
return mRedirectConsoleProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecutableRunner::setRedirectConsoleProgram(bool newRedirectConsoleProgram)
|
||||||
|
{
|
||||||
|
mRedirectConsoleProgram = newRedirectConsoleProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &ExecutableRunner::redirectInputFilename() const
|
||||||
|
{
|
||||||
|
return mRedirectInputFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecutableRunner::setRedirectInputFilename(const QString &newDataFile)
|
||||||
|
{
|
||||||
|
mRedirectInputFilename = newDataFile;
|
||||||
|
}
|
||||||
|
|
||||||
void ExecutableRunner::run()
|
void ExecutableRunner::run()
|
||||||
{
|
{
|
||||||
emit started();
|
emit started();
|
||||||
|
@ -48,19 +69,31 @@ void ExecutableRunner::run()
|
||||||
}
|
}
|
||||||
env.insert("PATH",path);
|
env.insert("PATH",path);
|
||||||
process.setProcessEnvironment(env);
|
process.setProcessEnvironment(env);
|
||||||
|
if (redirectConsoleProgram()) {
|
||||||
|
process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments * args){
|
||||||
|
args->flags |= CREATE_NEW_CONSOLE;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments * args){
|
process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments * args){
|
||||||
args->flags |= CREATE_NEW_CONSOLE;
|
args->flags |= CREATE_NEW_CONSOLE;
|
||||||
args->startupInfo -> dwFlags &= ~STARTF_USESTDHANDLES;
|
args->startupInfo -> dwFlags &= ~STARTF_USESTDHANDLES;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
process.connect(&process, &QProcess::errorOccurred,
|
process.connect(&process, &QProcess::errorOccurred,
|
||||||
[&](){
|
[&](){
|
||||||
errorOccurred= true;
|
errorOccurred= true;
|
||||||
});
|
});
|
||||||
// qDebug() << mFilename;
|
// qDebug() << mFilename;
|
||||||
// qDebug() << QProcess::splitCommand(mArguments);
|
// qDebug() << QProcess::splitCommand(mArguments);
|
||||||
process.start();
|
if (!redirectConsoleProgram()) {
|
||||||
process.closeWriteChannel();
|
process.closeWriteChannel();
|
||||||
|
}
|
||||||
|
process.start();
|
||||||
process.waitForStarted(5000);
|
process.waitForStarted(5000);
|
||||||
|
if (process.state()==QProcess::Running && redirectConsoleProgram()) {
|
||||||
|
process.write(ReadFileToByteArray(redirectInputFilename()));
|
||||||
|
process.closeWriteChannel();
|
||||||
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
process.waitForFinished(1000);
|
process.waitForFinished(1000);
|
||||||
if (process.state()!=QProcess::Running) {
|
if (process.state()!=QProcess::Running) {
|
||||||
|
|
|
@ -9,6 +9,12 @@ class ExecutableRunner : public QThread
|
||||||
public:
|
public:
|
||||||
ExecutableRunner(const QString& filename, const QString& arguments, const QString& workDir);
|
ExecutableRunner(const QString& filename, const QString& arguments, const QString& workDir);
|
||||||
|
|
||||||
|
const QString &redirectInputFilename() const;
|
||||||
|
void setRedirectInputFilename(const QString &newDataFile);
|
||||||
|
|
||||||
|
bool redirectConsoleProgram() const;
|
||||||
|
void setRedirectConsoleProgram(bool newRedirectConsoleProgram);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void started();
|
void started();
|
||||||
void terminated();
|
void terminated();
|
||||||
|
@ -22,6 +28,8 @@ private:
|
||||||
QString mArguments;
|
QString mArguments;
|
||||||
QString mWorkDir;
|
QString mWorkDir;
|
||||||
bool mStop;
|
bool mStop;
|
||||||
|
QString mRedirectInputFilename;
|
||||||
|
bool mRedirectConsoleProgram;
|
||||||
|
|
||||||
// QThread interface
|
// QThread interface
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1115,11 +1115,11 @@ void MainWindow::runExecutable(const QString &exeName,const QString &filename)
|
||||||
showMinimized();
|
showMinimized();
|
||||||
}
|
}
|
||||||
updateAppTitle();
|
updateAppTitle();
|
||||||
|
QString params;
|
||||||
if (pSettings->executor().useParams()) {
|
if (pSettings->executor().useParams()) {
|
||||||
mCompilerManager->run(exeName,pSettings->executor().params(),QFileInfo(exeName).absolutePath());
|
params = pSettings->executor().params();
|
||||||
} else {
|
|
||||||
mCompilerManager->run(exeName,"",QFileInfo(exeName).absolutePath());
|
|
||||||
}
|
}
|
||||||
|
mCompilerManager->run(exeName,params,QFileInfo(exeName).absolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::runExecutable()
|
void MainWindow::runExecutable()
|
||||||
|
|
|
@ -250,6 +250,7 @@ bool SettingsDialog::setCurrentWidget(const QString &widgetName, const QString &
|
||||||
for (int i=0;i<pGroupItem->rowCount();i++) {
|
for (int i=0;i<pGroupItem->rowCount();i++) {
|
||||||
QStandardItem* pWidgetItem = pGroupItem->child(i);
|
QStandardItem* pWidgetItem = pGroupItem->child(i);
|
||||||
if (pWidgetItem->text() == widgetName) {
|
if (pWidgetItem->text() == widgetName) {
|
||||||
|
ui->widgetsView->setCurrentIndex(pWidgetItem->index());
|
||||||
on_widgetsView_clicked(pWidgetItem->index());
|
on_widgetsView_clicked(pWidgetItem->index());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -835,3 +835,12 @@ bool removeFile(const QString &filename)
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
return file.remove();
|
return file.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray ReadFileToByteArray(const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
if (file.open(QFile::ReadOnly)) {
|
||||||
|
return file.readAll();
|
||||||
|
}
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
|
@ -154,6 +154,7 @@ QString parseMacros(const QString& s);
|
||||||
|
|
||||||
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
|
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
|
||||||
QStringList ReadFileToLines(const QString& fileName);
|
QStringList ReadFileToLines(const QString& fileName);
|
||||||
|
QByteArray ReadFileToByteArray(const QString& fileName);
|
||||||
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
|
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
|
||||||
void StringsToFile(const QStringList& list, const QString& fileName);
|
void StringsToFile(const QStringList& list, const QString& fileName);
|
||||||
void StringToFile(const QString& str, const QString& fileName);
|
void StringToFile(const QString& str, const QString& fileName);
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/ConsolePauser.layout
|
||||||
|
/Makefile.win
|
||||||
|
/ConsolePauser.exe
|
||||||
|
/main.o
|
|
@ -0,0 +1,73 @@
|
||||||
|
[Project]
|
||||||
|
FileName = ConsolePauser.dev
|
||||||
|
Name = ConsolePauser
|
||||||
|
Type = 1
|
||||||
|
Ver = 3
|
||||||
|
ObjFiles =
|
||||||
|
Includes =
|
||||||
|
Libs =
|
||||||
|
PrivateResource =
|
||||||
|
ResourceIncludes =
|
||||||
|
MakeIncludes =
|
||||||
|
Compiler =
|
||||||
|
CppCompiler =
|
||||||
|
Linker =
|
||||||
|
IsCpp = 1
|
||||||
|
Icon =
|
||||||
|
ExeOutput =
|
||||||
|
ObjectOutput =
|
||||||
|
LogOutput =
|
||||||
|
LogOutputEnabled = 0
|
||||||
|
OverrideOutput = 0
|
||||||
|
OverrideOutputName = ConsolePauser.exe
|
||||||
|
HostApplication =
|
||||||
|
Folders =
|
||||||
|
CommandLine =
|
||||||
|
UseCustomMakefile = 0
|
||||||
|
CustomMakefile =
|
||||||
|
IncludeVersionInfo = 0
|
||||||
|
SupportXPThemes = 0
|
||||||
|
CompilerSet = 0
|
||||||
|
CompilerSettings = 000000a000110000000010000
|
||||||
|
UnitCount = 1
|
||||||
|
UsePrecompiledHeader = 0
|
||||||
|
PrecompiledHeader =
|
||||||
|
UseUTF8 = 0
|
||||||
|
StaticLink = 1
|
||||||
|
AddCharset = 1
|
||||||
|
Encoding = AUTO
|
||||||
|
|
||||||
|
|
||||||
|
[VersionInfo]
|
||||||
|
Major = 1
|
||||||
|
Minor = 0
|
||||||
|
Release = 0
|
||||||
|
Build = 0
|
||||||
|
LanguageID = 1033
|
||||||
|
CharsetID = 1252
|
||||||
|
CompanyName =
|
||||||
|
FileVersion = 1.0.0.0
|
||||||
|
FileDescription = Developed using the Dev-C++ IDE
|
||||||
|
InternalName =
|
||||||
|
LegalCopyright =
|
||||||
|
LegalTrademarks =
|
||||||
|
OriginalFilename =
|
||||||
|
ProductName =
|
||||||
|
ProductVersion = 1.0.0.0
|
||||||
|
AutoIncBuildNr = 0
|
||||||
|
SyncProduct = 1
|
||||||
|
|
||||||
|
|
||||||
|
[Unit1]
|
||||||
|
FileName = main.cpp
|
||||||
|
CompileCpp = 1
|
||||||
|
Folder =
|
||||||
|
Compile = 1
|
||||||
|
Link = 1
|
||||||
|
Priority = 1000
|
||||||
|
OverrideBuildCmd = 0
|
||||||
|
BuildCmd =
|
||||||
|
UseUTF8 = 1
|
||||||
|
DetectEncoding = 1
|
||||||
|
Encoding = 0
|
||||||
|
FileEncoding = AUTO
|
|
@ -0,0 +1,217 @@
|
||||||
|
// Execute & Pause
|
||||||
|
// Runs a program, then keeps the console window open after it finishes
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
using std::string;
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define MAX_COMMAND_LENGTH 32768
|
||||||
|
#define MAX_ERROR_LENGTH 2048
|
||||||
|
|
||||||
|
HANDLE hJob;
|
||||||
|
|
||||||
|
LONGLONG GetClockTick() {
|
||||||
|
LARGE_INTEGER dummy;
|
||||||
|
QueryPerformanceCounter(&dummy);
|
||||||
|
return dummy.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONGLONG GetClockFrequency() {
|
||||||
|
LARGE_INTEGER dummy;
|
||||||
|
QueryPerformanceFrequency(&dummy);
|
||||||
|
return dummy.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string GetErrorMessage() {
|
||||||
|
string result(MAX_ERROR_LENGTH,0);
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),&result[0],result.size(),NULL);
|
||||||
|
|
||||||
|
// Clear newlines at end of string
|
||||||
|
for(int i = result.length()-1;i >= 0;i--) {
|
||||||
|
if(isspace(result[i])) {
|
||||||
|
result[i] = 0;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PauseExit(int exitcode, bool reInp) {
|
||||||
|
HANDLE hInp=NULL;
|
||||||
|
if (reInp) {
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
sa.nLength = sizeof(sa);
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
sa.bInheritHandle = TRUE;
|
||||||
|
|
||||||
|
HANDLE hInp = CreateFile("CONIN$", GENERIC_WRITE | GENERIC_READ,
|
||||||
|
FILE_SHARE_READ , &sa, OPEN_EXISTING, /*FILE_ATTRIBUTE_NORMAL*/0, NULL);
|
||||||
|
//si.hStdInput = hInp;
|
||||||
|
SetStdHandle(STD_INPUT_HANDLE,hInp);
|
||||||
|
}
|
||||||
|
//system("pause");
|
||||||
|
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
memset(&si,0,sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
memset(&pi,0,sizeof(pi));
|
||||||
|
|
||||||
|
DWORD dwCreationFlags = CREATE_BREAKAWAY_FROM_JOB;
|
||||||
|
|
||||||
|
|
||||||
|
if(!CreateProcess(NULL, (LPSTR)"cmd /c \"pause\"", NULL, NULL, true, dwCreationFlags, NULL, NULL, &si, &pi)) {
|
||||||
|
printf("\n--------------------------------");
|
||||||
|
printf("\nFailed to execute 'pause' ");
|
||||||
|
printf("\nError %lu: %s\n",GetLastError(),GetErrorMessage().c_str());
|
||||||
|
system("pause");
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
WINBOOL bSuccess = AssignProcessToJobObject( hJob, pi.hProcess );
|
||||||
|
if ( bSuccess == FALSE ) {
|
||||||
|
printf( "AssignProcessToJobObject failed: error %d\n", GetLastError() );
|
||||||
|
system("pause");
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE); // Wait for it to finish
|
||||||
|
if (reInp) {
|
||||||
|
CloseHandle(hInp);
|
||||||
|
}
|
||||||
|
CloseHandle( hJob );
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetCommand(int argc,char** argv,bool &reInp) {
|
||||||
|
string result;
|
||||||
|
reInp = (strcmp(argv[1],"0")!=0) ;
|
||||||
|
for(int i = 2;i < argc;i++) {
|
||||||
|
/*
|
||||||
|
// Quote the first argument in case the path name contains spaces
|
||||||
|
// if(i == 1) {
|
||||||
|
// result += string("\"") + string(argv[i]) + string("\"");
|
||||||
|
// } else {
|
||||||
|
// Quote the first argument in case the path name contains spaces
|
||||||
|
// result += string(argv[i]);
|
||||||
|
// }
|
||||||
|
*/
|
||||||
|
// Quote the first argument in case the path name contains spaces
|
||||||
|
result += string("\"") + string(argv[i]) + string("\"");
|
||||||
|
|
||||||
|
// Add a space except for the last argument
|
||||||
|
if(i != (argc-1)) {
|
||||||
|
result += string(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result.length() > MAX_COMMAND_LENGTH) {
|
||||||
|
printf("\n--------------------------------");
|
||||||
|
printf("\nError: Length of command line string is over %d characters\n",MAX_COMMAND_LENGTH);
|
||||||
|
PauseExit(EXIT_FAILURE,reInp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD ExecuteCommand(string& command,bool reInp) {
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
memset(&si,0,sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
memset(&pi,0,sizeof(pi));
|
||||||
|
|
||||||
|
DWORD dwCreationFlags = CREATE_BREAKAWAY_FROM_JOB;
|
||||||
|
|
||||||
|
|
||||||
|
if(!CreateProcess(NULL, (LPSTR)command.c_str(), NULL, NULL, true, dwCreationFlags, NULL, NULL, &si, &pi)) {
|
||||||
|
printf("\n--------------------------------");
|
||||||
|
printf("\nFailed to execute \"%s\":",command.c_str());
|
||||||
|
printf("\nError %lu: %s\n",GetLastError(),GetErrorMessage().c_str());
|
||||||
|
PauseExit(EXIT_FAILURE,reInp);
|
||||||
|
}
|
||||||
|
WINBOOL bSuccess = AssignProcessToJobObject( hJob, pi.hProcess );
|
||||||
|
if ( bSuccess == FALSE ) {
|
||||||
|
printf( "AssignProcessToJobObject failed: error %d\n", GetLastError() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE); // Wait for it to finish
|
||||||
|
|
||||||
|
|
||||||
|
DWORD result = 0;
|
||||||
|
GetExitCodeProcess(pi.hProcess, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
// First make sure we aren't going to read nonexistent arrays
|
||||||
|
if(argc < 3) {
|
||||||
|
printf("\n--------------------------------");
|
||||||
|
printf("\nUsage: ConsolePauser.exe <0|1> <filename> <parameters>\n");
|
||||||
|
printf("\n 1 means the STDIN is redirected by Dev-CPP;0 means not\n");
|
||||||
|
PauseExit(EXIT_SUCCESS,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make us look like the paused program
|
||||||
|
SetConsoleTitle(argv[2]);
|
||||||
|
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
sa.nLength = sizeof(sa);
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
sa.bInheritHandle = FALSE;
|
||||||
|
|
||||||
|
hJob= CreateJobObject( &sa, NULL );
|
||||||
|
|
||||||
|
if ( hJob == NULL ) {
|
||||||
|
printf( "CreateJobObject failed: error %d\n", GetLastError() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = { 0 };
|
||||||
|
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||||
|
WINBOOL bSuccess = SetInformationJobObject( hJob, JobObjectExtendedLimitInformation, &info, sizeof( info ) );
|
||||||
|
if ( bSuccess == FALSE ) {
|
||||||
|
printf( "SetInformationJobObject failed: error %d\n", GetLastError() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reInp;
|
||||||
|
// Then build the to-run application command
|
||||||
|
string command = GetCommand(argc,argv,reInp);
|
||||||
|
HANDLE hOutput = NULL;
|
||||||
|
if (reInp) {
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
sa.nLength = sizeof(sa);
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
sa.bInheritHandle = TRUE;
|
||||||
|
|
||||||
|
hOutput = CreateFile("CONOUT$", GENERIC_WRITE | GENERIC_READ,
|
||||||
|
FILE_SHARE_WRITE , &sa, OPEN_EXISTING, /*FILE_ATTRIBUTE_NORMAL*/0, NULL);
|
||||||
|
SetStdHandle(STD_OUTPUT_HANDLE, hOutput);
|
||||||
|
SetStdHandle(STD_ERROR_HANDLE, hOutput);
|
||||||
|
freopen("CONOUT$","w+",stdout);
|
||||||
|
freopen("CONOUT$","w+",stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save starting timestamp
|
||||||
|
LONGLONG starttime = GetClockTick();
|
||||||
|
|
||||||
|
// Then execute said command
|
||||||
|
DWORD returnvalue = ExecuteCommand(command,reInp);
|
||||||
|
|
||||||
|
// Get ending timestamp
|
||||||
|
LONGLONG endtime = GetClockTick();
|
||||||
|
double seconds = (endtime - starttime) / (double)GetClockFrequency();
|
||||||
|
|
||||||
|
// Done? Print return value of executed program
|
||||||
|
printf("\n--------------------------------");
|
||||||
|
printf("\nProcess exited after %.4g seconds with return value %lu\n",seconds,returnvalue);
|
||||||
|
PauseExit(returnvalue,reInp);
|
||||||
|
}
|
Loading…
Reference in New Issue