crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/ProcessAndThread/ProcessLauncher.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
* 
* Description:
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace SymbianUtils.ProcessAndThread
{
    public class ProcessLauncher
    {
        #region API
        public static int Launch( string aFileName, string aCommandLineArguments, string aCurrentDirectory, bool aShowWindow )
        {
            return Launch( aFileName, aCommandLineArguments, aCurrentDirectory, aShowWindow, 0 );
        }

        public static int Launch( string aFileName, string aCommandLineArguments, string aCurrentDirectory, bool aShowWindow, int aWaitTimeInMs )
        {
            // See http://msdn.microsoft.com/en-us/library/ms682425.aspx
            // See http://msdn2.microsoft.com/en-us/library/ms682425.aspx
            // See http://www.pinvoke.net/default.aspx/kernel32/CreateProcess.html
            ProcessInformation pi = new ProcessInformation();
            StartupInformation si = new StartupInformation();
            if ( !aShowWindow )
            {
                si.dwFlags = STARTF_USESHOWWINDOW;
                si.wShowWindow = SW_SHOWMINIMIZED;
            }

            si.cb = Marshal.SizeOf( si );
            SecurityAttributes pSec = new SecurityAttributes();
            pSec.nLength = Marshal.SizeOf( pSec );
            SecurityAttributes tSec = new SecurityAttributes();
            tSec.nLength = Marshal.SizeOf( tSec );
            //
            int error = 0;
            bool suceeded = CreateProcess( aFileName, aCommandLineArguments, ref pSec, ref tSec, false, 0, IntPtr.Zero, aCurrentDirectory, ref si, out pi ) != false;
            if ( !suceeded )
            {
                error = Marshal.GetLastWin32Error();
            }
            else
            {
                if ( aWaitTimeInMs != 0 )
                {
                    // Wait
                    WaitForSingleObject( pi.hProcess, aWaitTimeInMs );
                }

                // Tidy up
                CloseHandle( pi.hThread );
                CloseHandle( pi.hProcess );

                int hResult = GetExitCodeProcess( pi.hProcess, ref error );
                if ( error != 0 )
                {
                    Win32Exception exception = new Win32Exception( error );
                    throw exception;
                }
            }
            //
            return error;
        }
        #endregion

        #region Internal constants
        private const int STARTF_USESHOWWINDOW = 0x00000001;
        private const int SW_HIDE = 0;
        private const int SW_SHOWNORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;
        private const int SW_SHOWMAXIMIZED = 3;
        #endregion

        #region Internal PInvoke wrappers
        [DllImport( "kernel32.dll", SetLastError = true )]
        static extern int GetExitCodeProcess( IntPtr hProcess, ref int lpExitCode );

        [DllImport( "kernel32.dll", SetLastError = true )]
        internal static extern bool CreateProcess( string lpApplicationName,
                                          string lpCommandLine,
                                          ref SecurityAttributes lpProcessAttributes,
                                          ref SecurityAttributes lpThreadAttributes,
                                          bool bInheritHandles,
                                          uint dwCreationFlags,
                                          IntPtr lpEnvironment,
                                          string lpCurrentDirectory,
                                          ref StartupInformation lpStartupInfo,
                                          out ProcessInformation lpProcessInformation );

        [DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
        internal static extern Int32 WaitForSingleObject( IntPtr handle, Int32 milliseconds );

        [DllImport( "kernel32.dll", SetLastError = true )]
        [return: MarshalAs( UnmanagedType.Bool )]
        internal static extern bool CloseHandle( IntPtr hObject );
        #endregion
   }

    public static class ProcessLauncherWithBlockingWait
    {
        #region API
        public static int Launch( string aFileName, string aCommandLineArguments, string aCurrentDirectory )
        {
            return Launch( aFileName, aCommandLineArguments, aCurrentDirectory, false );
        }

        public static int Launch( string aFileName, string aCommandLineArguments, string aCurrentDirectory, bool aShowWindow )
        {
            LaunchWorkerThread worker = new LaunchWorkerThread( aFileName, aCommandLineArguments, aCurrentDirectory );
            return worker.LaunchAndWait( aShowWindow );
        }
        #endregion
    }

    #region Internal class
    internal class LaunchWorkerThread
    {
        #region Constructors
        public LaunchWorkerThread( string aFileName, string aCommandLineArguments, string aCurrentDirectory )
        {
            iFileName = aFileName;
            iCommandLineArguments = aCommandLineArguments;
            iCurrentDirectory = aCurrentDirectory;
        }
        #endregion

        #region API
        public int LaunchAndWait( bool aShowWindow )
        {
            Thread thread = new Thread( new ParameterizedThreadStart( this.ThreadFunction ) );
            thread.Priority = ThreadPriority.BelowNormal;
            thread.Start( aShowWindow );
            //
            while ( thread.IsAlive )
            {
                Application.DoEvents();
                Thread.Sleep( 250 );
            }
            //
            return iError;
        }
        #endregion

        #region Internal methods
        private void ThreadFunction( object aData )
        {
            bool showWindow = (bool) aData;
            iError = ProcessLauncher.Launch( iFileName, iCommandLineArguments, iCurrentDirectory, showWindow, (int) WAIT_INFINITE );
        }
        #endregion

        #region Internal constants
        private static uint WAIT_INFINITE = 0xFFFFFFFF;
        #endregion

        #region Data members
        private int iError = -1;
        private readonly string iFileName;
        private readonly string iCommandLineArguments;
        private readonly string iCurrentDirectory;
        #endregion
    }
    #endregion
}