📄 qprocess_win.cpp
字号:
envlist[pos++] = 0; } success = CreateProcess( 0, commandLine, 0, 0, TRUE, CREATE_NO_WINDOW#ifndef Q_OS_TEMP | CREATE_UNICODE_ENVIRONMENT#endif , env==0 ? 0 : envlist.data(), (TCHAR*)qt_winTchar(workingDir.absPath(),TRUE), &startupInfo, d->pid ); delete[] commandLine;# ifndef Q_OS_TEMP } else# endif#endif#ifndef Q_OS_TEMP { STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0, d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] }; QByteArray envlist; if ( env != 0 ) { int pos = 0; // add PATH if necessary (for DLL loading) char *path = getenv( "PATH" ); if ( env->grep( QRegExp("^PATH=",FALSE) ).isEmpty() && path ) { QCString tmp = QString( "PATH=%1" ).arg( getenv( "PATH" ) ).local8Bit(); uint tmpSize = tmp.length() + 1; envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.data(), tmpSize ); pos += tmpSize; } // add the user environment for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { QCString tmp = (*it).local8Bit(); uint tmpSize = tmp.length() + 1; envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.data(), tmpSize ); pos += tmpSize; } // add the terminating 0 (actually 2, just to be on the safe side) envlist.resize( envlist.size()+2 ); envlist[pos++] = 0; envlist[pos++] = 0; } success = CreateProcessA( 0, args.local8Bit().data(), 0, 0, TRUE, DETACHED_PROCESS, env==0 ? 0 : envlist.data(), (const char*)workingDir.absPath().local8Bit(), &startupInfo, d->pid ); }#endif if ( !success ) { d->deletePid(); return FALSE; }#ifndef Q_OS_TEMP if ( (comms & Stdin) != 0 ) CloseHandle( d->pipeStdin[0] ); if ( (comms & Stdout) != 0 ) CloseHandle( d->pipeStdout[1] ); if ( (comms & Stderr) != 0 ) CloseHandle( d->pipeStderr[1] );#endif if ( ioRedirection || notifyOnExit ) { d->lookup->start( 100 ); } // cleanup and return return TRUE;}BOOL CALLBACK qt_terminateApp( HWND hwnd, LPARAM procId ){ DWORD procId_win; GetWindowThreadProcessId( hwnd, &procId_win ); if( procId_win == (DWORD)procId ) PostMessage( hwnd, WM_CLOSE, 0, 0 ); return TRUE;}void QProcess::tryTerminate() const{ EnumWindows( qt_terminateApp, (LPARAM)d->pid->dwProcessId );}void QProcess::kill() const{ if ( d->pid ) TerminateProcess( d->pid->hProcess, 0xf291 );}bool QProcess::isRunning() const{ if ( !d->pid ) return FALSE; if ( WaitForSingleObject( d->pid->hProcess, 0) == WAIT_OBJECT_0 ) { // there might be data to read QProcess *that = (QProcess*)this; that->socketRead( 1 ); // try stdout that->socketRead( 2 ); // try stderr // compute the exit values if ( !d->exitValuesCalculated ) { DWORD exitCode; if ( GetExitCodeProcess( d->pid->hProcess, &exitCode ) ) { if ( exitCode != STILL_ACTIVE ) { // this should ever be true? QProcess *that = (QProcess*)this; // mutable that->exitNormal = exitCode != 0xf291; that->exitStat = exitCode; } } d->exitValuesCalculated = TRUE; } d->deletePid(); return FALSE; } else { return TRUE; }}void QProcess::writeToStdin( const QByteArray& buf ){ d->stdinBuf.enqueue( new QByteArray(buf) ); socketWrite( 0 );}void QProcess::closeStdin( ){ if ( d->pipeStdin[1] != 0 ) { CloseHandle( d->pipeStdin[1] ); d->pipeStdin[1] = 0; }}void QProcess::socketRead( int fd ){ // fd == 1: stdout, fd == 2: stderr HANDLE dev; if ( fd == 1 ) { dev = d->pipeStdout[0]; } else if ( fd == 2 ) { dev = d->pipeStderr[0]; } else { return; }#ifndef Q_OS_TEMP // get the number of bytes that are waiting to be read unsigned long i, r; char dummy; if ( !PeekNamedPipe( dev, &dummy, 1, &r, &i, 0 ) ) { return; // ### is it worth to dig for the reason of the error? }#else unsigned long i = 1000;#endif if ( i > 0 ) { QByteArray *buffer; uint oldSize; if ( fd == 1 ) { buffer = &d->bufStdout; } else { buffer = &d->bufStderr; } oldSize = buffer->size(); buffer->resize( oldSize + i ); uint sz = readStddev( dev, buffer->data()+oldSize, i ); if ( sz != i ) buffer->resize( oldSize + i ); if ( sz == 0 ) return; if ( fd == 1 ) emit readyReadStdout(); else emit readyReadStderr(); }}void QProcess::socketWrite( int fd ){ DWORD written; if ( d->stdinBuf.isEmpty() || !isRunning() ) { return; } if ( !WriteFile( d->pipeStdin[1], d->stdinBuf.head()->data() + d->stdinBufRead, d->stdinBuf.head()->size() - d->stdinBufRead, &written, 0 ) ) { return; } d->stdinBufRead += written; if ( d->stdinBufRead == d->stdinBuf.head()->size() ) { d->stdinBufRead = 0; delete d->stdinBuf.dequeue(); if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) { emit wroteToStdin(); } socketWrite( fd ); // start timer if there is still pending data if ( !d->stdinBuf.isEmpty() ) { d->lookup->start( 100 ); } }}void QProcess::flushStdin(){ socketWrite( 0 );}/* Use a timer for polling misc. stuff.*/void QProcess::timeout(){ // try to write pending data to stdin if ( !d->stdinBuf.isEmpty() ) { socketWrite( 0 ); // stop timer if it is not needed any longer if ( d->stdinBuf.isEmpty() && !ioRedirection && !notifyOnExit ) d->lookup->stop(); } if ( ioRedirection ) { socketRead( 1 ); // try stdout socketRead( 2 ); // try stderr } // stop timer if process is not running also emit processExited() signal if ( !isRunning() ) { d->lookup->stop(); if ( notifyOnExit ) { emit processExited(); } }}/* read on the pipe*/uint QProcess::readStddev( HANDLE dev, char *buf, uint bytes ){ if ( bytes > 0 ) { ulong r; if ( ReadFile( dev, buf, bytes, &r, 0 ) ) return r; } return 0;}/* Used by connectNotify() and disconnectNotify() to change the value of ioRedirection (and related behaviour)*/void QProcess::setIoRedirection( bool value ){ ioRedirection = value; if ( !ioRedirection && !notifyOnExit ) d->lookup->stop(); if ( ioRedirection ) { if ( isRunning() ) d->lookup->start( 100 ); }}/* Used by connectNotify() and disconnectNotify() to change the value of notifyOnExit (and related behaviour)*/void QProcess::setNotifyOnExit( bool value ){ notifyOnExit = value; if ( !ioRedirection && !notifyOnExit ) d->lookup->stop(); if ( notifyOnExit ) { if ( isRunning() ) d->lookup->start( 100 ); }}/* Used by connectNotify() and disconnectNotify() to change the value of wroteToStdinConnected (and related behaviour)*/void QProcess::setWroteStdinConnected( bool value ){ wroteToStdinConnected = value;}QProcess::PID QProcess::processIdentifier(){ return d->pid;}int QProcess::priority() const{ return 0;}void QProcess::setPriority(int p){}#endif // QT_NO_PROCESS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -