Archive

Posts Tagged ‘CreateProcess’

Starting command prompt in a particular directory

February 28, 2009 Leave a comment

What I mean is, if we type ‘Start->Run->Cmd.exe’ then command prompt directory is our user directory, for e.g. ‘c:\Documents and settings\Nibu’. So how can we do this through code is the question? Directory that we see when command prompt starts up is called working directory. Every executable in windows has a working directory which is in fact the first location it searches for a file. So using ‘CreateProcess’ it’s possible to set a working directory, since it has a function parameter which corresponds to this feature. So here is a simple dedicated function which sets working directory for command prompt…

void OpenCmdInDir( LPCTSTR lpctszDir )
{
   STARTUPINFO StrInf =  { 0 };
   StrInf.cb = sizeof( StrInf );

   PROCESS_INFORMATION ProcInfo = { 0 };
   VERIFY( CreateProcess( NULL, "C:\\Windows\\system32\\cmd.exe", NULL, NULL, FALSE, 0, 0, lpctszDir, &StrInf, &ProcInfo ));

   // Closing handles since not needed further
   CloseHandle( ProcInfo.hProcess );
   CloseHandle( ProcInfo.hThread );
}

// Usage
OpenCmdInDir( _T( "C:\\Windows\\System32\\Drivers" ));

See screenshot…

Command prompt working directory

Command prompt working directory

Advertisements

How to identify a stale handle?

August 29, 2008 1 comment

Lets suppose you are keeping handles of all processes running in a system using OpenProcess, now it’s just normal that some processes may exit, but since you have a valid handle there is no way to tell whether the process is still running or whether it has exited. You cannot check for NULL since the process was running when OpenProcess was called.

Ha! So is there a way? Yes man! Grrrrrr!

We can use WaitForSingleObject with a zero timeout. If dwMilliseconds is zero, the function tests the object’s state and returns immediately. Yes this is the key, this is what we want, the state of the object i.e. whether it’s signaled or non-signaled. An opened process handle is in a signaled state when corresponding process exits or is killed and that’s the only time IMK a process handle can become signaled. So we call WaitForSingleObject with zero timeout and if the return value is WAIT_TIMEOUT then our baby is running else if the return value is WAIT_OBJECT_0 then our baby is no more running. 😉

So here is a function which identifies a stale process handle or the handle of process which is no more running. Function name is IsProcHandleValid.

bool IsProcHandleValid( HANDLE hProc )
{
   if( !hProc )
   {
      ASSERT( FALSE );
      return false;
   }

   // Just check signaled state of the process handle, it will
   // become signaled whenever the process exits
   const DWORD RetVal = WaitForSingleObject( hProc, 0 );
   if( RetVal == WAIT_FAILED )
   {
      ::MessageBox( GetForegroundWindow(), _T( "WaitForSingleObject call failed, most probably the handle does not have wait permission!" ), _T( "Error!" ), MB_OK | MB_ICONERROR );
      return false;
   }

   return ( RetVal == WAIT_TIMEOUT );
}

void TestProcessHandle()
{
   STARTUPINFO StartInfo = { 0 };
   StartInfo.cb = sizeof( StartInfo );
   PROCESS_INFORMATION ProcInfo = { 0 };

   BOOL Result = CreateProcess( _T( "C:\\windows\\notepad.exe" ),
                                NULL,
                                NULL,
                                NULL,
                                FALSE,
                                NULL,
                                NULL,
                                NULL,
                                &StartInfo,
                                &ProcInfo );

   ASSERT( Result );

   // Open a handle to newly created "notepad" process
   HANDLE hProc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ProcInfo.dwProcessId );
   ASSERT( hProc );

   // Kill created process
   if( MessageBox( NULL, _T( "Do you wanna kill this notepad instance?" ), "Kill notepad?", MB_YESNO | MB_ICONQUESTION ) == IDYES )
   {
      PostThreadMessage( ProcInfo.dwThreadId, WM_QUIT, 0, 0 );

      // Wait for notepad to exit
      WaitForSingleObject( ProcInfo.hThread, INFINITE );
   }

   // Check validity of opened notepad handle
   if( IsProcHandleValid( hProc ))
   {
      ::MessageBox( NULL, _T( "We've got a live handle, notepad is still running.\n\nSo our test worked, YaY!!" ), "Testing process handle", MB_OK );

      // Now kill since we are leaving
      PostThreadMessage( ProcInfo.dwThreadId, WM_QUIT, 0, 0 );
      WaitForSingleObject( ProcInfo.hThread, INFINITE );
   }
   else
   {
      ::MessageBox( NULL, _T( "Notepad is not running, we have a stale handle.\n\nSo our test worked, YaY!!" ), "Testing process handle", MB_OK );
   }// End if

   // Release handles in ProcInfo returned by CreateProcess
   CloseHandle( ProcInfo.hProcess );
   CloseHandle( ProcInfo.hThread );

   // Release opened handle
   CloseHandle( hProc );
}

int main()
{
   TestProcessHandle();
   return 0;
}

Yup! that’s it, have fun coding!

How to start a process hidden!

I’ve seen people asking this question number of times, so for those people here is the answer…

When creating a process via CreateProcess we’ve got to give a STARTUPINFO structure as a parameter which specifies startup options for a process.

Set dwFlags member to STARTF_USESHOWWINDOW to indicate that we will be using wShowWindow member of STARTUPINFO. Then set wShowWindow to SW_HIDE to start a process as hidden.

To start a process as maximized use SW_MAXIMIZE, to start as minimized use SW_MINIMIZE, to start as restored use SW_RESTORE. Look up ShowWindow MSDN to for other options!

STARTUPINFO StartInfo = { 0 };
StartInfo.cb = sizeof( StartInfo ); 

// Use showwindow field of this structure
StartInfo.dwFlags = STARTF_USESHOWWINDOW;
StartInfo.wShowWindow = SW_HIDE; 

PROCESS_INFORMATION pi = { 0 };
CreateProcess( _T( "C:\\windows\\Notepad.exe" ),
               NULL,
               NULL,
               NULL,
               FALSE,
               0,
               NULL,
               NULL,
               &StartInfo,
               &pi );

You won’t see notepad running since it’s hidden, open task manager to see notepad running!

%d bloggers like this: