Best Puppeteer-sharp code snippet using PuppeteerSharp.States.InitialState.ExitAsync
ChromiumProcess.cs
Source:ChromiumProcess.cs  
...137        /// Kills the Chromium process if it has not exited within this period.138        /// </summary>139        /// <param name="timeout">The maximum waiting time for a graceful process exit.</param>140        /// <returns></returns>141        public Task EnsureExitAsync(TimeSpan? timeout) => timeout.HasValue142            ? _currentState.ExitAsync(this, timeout.Value)143            : _currentState.KillAsync(this);144        /// <summary>145        /// Asynchronously kills Chromium process.146        /// </summary>147        /// <returns></returns>148        public Task KillAsync() => _currentState.KillAsync(this);149        /// <summary>150        /// Waits for Chromium process exit within a given timeout.151        /// </summary>152        /// <param name="timeout">The maximum wait period.</param>153        /// <returns><c>true</c> if Chromium process has exited within the given <paramref name="timeout"/>,154        /// or <c>false</c> otherwise.</returns>155        public async Task<bool> WaitForExitAsync(TimeSpan? timeout)156        {157            if (timeout.HasValue)158            {159                var taskCompleted = true;160                await _exitCompletionSource.Task.WithTimeout(() =>161                {162                    taskCompleted = false;163                }, timeout.Value).ConfigureAwait(false);164                return taskCompleted;165            }166            await _exitCompletionSource.Task.ConfigureAwait(false);167            return true;168        }169        /// <inheritdoc />170        public override string ToString() => $"Chromium process; EndPoint={EndPoint}; State={_currentState}";171        #endregion172        #region Private methods173        private static (List<string> chromiumArgs, TempDirectory tempUserDataDir) PrepareChromiumArgs(LaunchOptions options)174        {175            var chromiumArgs = new List<string>();176            if (!options.IgnoreDefaultArgs)177            {178                chromiumArgs.AddRange(GetDefaultArgs(options));179            }180            else if (options.IgnoredDefaultArgs?.Length > 0)181            {182                chromiumArgs.AddRange(GetDefaultArgs(options).Except(options.IgnoredDefaultArgs));183            }184            else185            {186                chromiumArgs.AddRange(options.Args);187            }188            TempDirectory tempUserDataDir = null;189            if (!chromiumArgs.Any(argument => argument.StartsWith("--remote-debugging-", StringComparison.Ordinal)))190            {191                chromiumArgs.Add("--remote-debugging-port=0");192            }193            var userDataDirOption = chromiumArgs.FirstOrDefault(i => i.StartsWith(UserDataDirArgument, StringComparison.Ordinal));194            if (string.IsNullOrEmpty(userDataDirOption))195            {196                tempUserDataDir = new TempDirectory();197                chromiumArgs.Add($"{UserDataDirArgument}={tempUserDataDir.Path.Quote()}");198            }199            return (chromiumArgs, tempUserDataDir);200        }201        internal static string[] GetDefaultArgs(LaunchOptions options)202        {203            var chromeArguments = new List<string>(DefaultArgs);204            if (!string.IsNullOrEmpty(options.UserDataDir))205            {206                chromeArguments.Add($"{UserDataDirArgument}={options.UserDataDir.Quote()}");207            }208            if (options.Devtools)209            {210                chromeArguments.Add("--auto-open-devtools-for-tabs");211            }212            if (options.Headless)213            {214                chromeArguments.AddRange(new[]{215                    "--headless",216                    "--hide-scrollbars",217                    "--mute-audio"218                });219            }220            if (options.Args.All(arg => arg.StartsWith("-", StringComparison.Ordinal)))221            {222                chromeArguments.Add("about:blank");223            }224            chromeArguments.AddRange(options.Args);225            return chromeArguments.ToArray();226        }227        private static void SetEnvVariables(IDictionary<string, string> environment, IDictionary<string, string> customEnv, IDictionary realEnv)228        {229            foreach (DictionaryEntry item in realEnv)230            {231                environment[item.Key.ToString()] = item.Value.ToString();232            }233            if (customEnv != null)234            {235                foreach (var item in customEnv)236                {237                    environment[item.Key] = item.Value;238                }239            }240        }241        #endregion242        #region State machine243        /// <summary>244        /// Represents state machine for Chromium process instances. The happy path runs along the245        /// following state transitions: <see cref="Initial"/>246        /// -> <see cref="Starting"/>247        /// -> <see cref="Started"/>248        /// -> <see cref="Exiting"/>249        /// -> <see cref="Exited"/>.250        /// -> <see cref="Disposed"/>.251        /// </summary>252        /// <remarks>253        /// <para>254        /// This state machine implements the following state transitions:255        /// <code>256        /// State     Event              Target State Action257        /// ======== =================== ============ ==========================================================258        /// Initial  --StartAsync------> Starting     Start process and wait for endpoint259        /// Initial  --ExitAsync-------> Exited       Cleanup temp user data260        /// Initial  --KillAsync-------> Exited       Cleanup temp user data261        /// Initial  --Dispose---------> Disposed     Cleanup temp user data262        /// Starting --StartAsync------> Starting     -263        /// Starting --ExitAsync-------> Exiting      Wait for process exit264        /// Starting --KillAsync-------> Killing      Kill process265        /// Starting --Dispose---------> Disposed     Kill process; Cleanup temp user data;  throw ObjectDisposedException on outstanding async operations;266        /// Starting --endpoint ready--> Started      Complete StartAsync successfully; Log process start267        /// Starting --process exit----> Exited       Complete StartAsync with exception; Cleanup temp user data268        /// Started  --StartAsync------> Started      -269        /// Started  --EnsureExitAsync-> Exiting      Start exit timer; Log process exit270        /// Started  --KillAsync-------> Killing      Kill process; Log process exit271        /// Started  --Dispose---------> Disposed     Kill process; Log process exit; Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;272        /// Started  --process exit----> Exited       Log process exit; Cleanup temp user data273        /// Exiting  --StartAsync------> Exiting      - (StartAsync throws InvalidOperationException)274        /// Exiting  --ExitAsync-------> Exiting      -275        /// Exiting  --KillAsync-------> Killing      Kill process276        /// Exiting  --Dispose---------> Disposed     Kill process; Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;277        /// Exiting  --exit timeout----> Killing      Kill process278        /// Exiting  --process exit----> Exited       Cleanup temp user data; complete outstanding async operations;279        /// Killing  --StartAsync------> Killing      - (StartAsync throws InvalidOperationException)280        /// Killing  --KillAsync-------> Killing      -281        /// Killing  --Dispose---------> Disposed     Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;282        /// Killing  --process exit----> Exited       Cleanup temp user data; complete outstanding async operations;283        /// Exited   --StartAsync------> Killing      - (StartAsync throws InvalidOperationException)284        /// Exited   --KillAsync-------> Exited       -285        /// Exited   --Dispose---------> Disposed     -286        /// Disposed --StartAsync------> Disposed     -287        /// Disposed --KillAsync-------> Disposed     -288        /// Disposed --Dispose---------> Disposed     -289        /// </code>290        /// </para>291        /// </remarks>292        private abstract class State293        {294            #region Predefined states295            public static readonly State Initial = new InitialState();296            private static readonly StartingState Starting = new StartingState();297            private static readonly StartedState Started = new StartedState();298            private static readonly ExitingState Exiting = new ExitingState();299            private static readonly KillingState Killing = new KillingState();300            private static readonly ExitedState Exited = new ExitedState();301            private static readonly DisposedState Disposed = new DisposedState();302            #endregion303            #region Properties304            public bool IsExiting => this == Killing || this == Exiting;305            public bool IsExited => this == Exited || this == Disposed;306            #endregion307            #region Methods308            /// <summary>309            /// Attempts thread-safe transitions from a given state to this state.310            /// </summary>311            /// <param name="p">The Chromium process</param>312            /// <param name="fromState">The state from which state transition takes place</param>313            /// <returns>Returns <c>true</c> if transition is successful, or <c>false</c> if transition314            /// cannot be made because current state does not equal <paramref name="fromState"/>.</returns>315            protected bool TryEnter(ChromiumProcess p, State fromState)316            {317                if (Interlocked.CompareExchange(ref p._currentState, this, fromState) == fromState)318                {319                    fromState.Leave(p);320                    return true;321                }322                return false;323            }324            /// <summary>325            /// Notifies that state machine is about to transition to another state.326            /// </summary>327            /// <param name="p">The Chromium process</param>328            protected virtual void Leave(ChromiumProcess p)329            { }330            /// <summary>331            /// Handles process start request.332            /// </summary>333            /// <param name="p">The Chromium process</param>334            /// <returns></returns>335            public virtual Task StartAsync(ChromiumProcess p) => Task.FromException(InvalidOperation("start"));336            /// <summary>337            /// Handles process exit request.338            /// </summary>339            /// <param name="p">The Chromium process</param>340            /// <param name="timeout">The maximum waiting time for a graceful process exit.</param>341            /// <returns></returns>342            public virtual Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => Task.FromException(InvalidOperation("exit"));343            /// <summary>344            /// Handles process kill request.345            /// </summary>346            /// <param name="p">The Chromium process</param>347            /// <returns></returns>348            public virtual Task KillAsync(ChromiumProcess p) => Task.FromException(InvalidOperation("kill"));349            /// <summary>350            /// Handles wait for process exit request.351            /// </summary>352            /// <param name="p">The Chromium process</param>353            /// <returns></returns>354            public virtual Task WaitForExitAsync(ChromiumProcess p) => p._exitCompletionSource.Task;355            /// <summary>356            /// Handles disposal of process and temporary user directory357            /// </summary>358            /// <param name="p"></param>359            public virtual void Dispose(ChromiumProcess p) => Disposed.EnterFrom(p, this);360            public override string ToString()361            {362                var name = GetType().Name;363                return name.Substring(0, name.Length - "State".Length);364            }365            private Exception InvalidOperation(string operationName)366                => new InvalidOperationException($"Cannot {operationName} in state {this}");367            /// <summary>368            /// Kills process if it is still alive.369            /// </summary>370            /// <param name="p"></param>371            private static void Kill(ChromiumProcess p)372            {373                try374                {375                    if (!p.Process.HasExited)376                    {377                        p.Process.Kill();378                    }379                }380                catch (InvalidOperationException)381                {382                    // Ignore383                }384            }385            #endregion386            #region Concrete state classes387            private class InitialState : State388            {389                public override Task StartAsync(ChromiumProcess p) => Starting.EnterFromAsync(p, this);390                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout)391                {392                    Exited.EnterFrom(p, this);393                    return Task.CompletedTask;394                }395                public override Task KillAsync(ChromiumProcess p)396                {397                    Exited.EnterFrom(p, this);398                    return Task.CompletedTask;399                }400                public override Task WaitForExitAsync(ChromiumProcess p) => Task.FromException(InvalidOperation("wait for exit"));401            }402            private class StartingState : State403            {404                public Task EnterFromAsync(ChromiumProcess p, State fromState)405                {406                    if (!TryEnter(p, fromState))407                    {408                        // Delegate StartAsync to current state, because it has already changed since409                        // transition to this state was initiated.410                        return p._currentState.StartAsync(p);411                    }412                    return StartCoreAsync(p);413                }414                public override Task StartAsync(ChromiumProcess p) => p._startCompletionSource.Task;415                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);416                public override Task KillAsync(ChromiumProcess p) => Killing.EnterFromAsync(p, this);417                public override void Dispose(ChromiumProcess p)418                {419                    p._startCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));420                    base.Dispose(p);421                }422                private async Task StartCoreAsync(ChromiumProcess p)423                {424                    var output = new StringBuilder();425                    void OnProcessDataReceivedWhileStarting(object sender, DataReceivedEventArgs e)426                    {427                        if (e.Data != null)428                        {429                            output.AppendLine(e.Data);430                            var match = Regex.Match(e.Data, "^DevTools listening on (ws:\\/\\/.*)");431                            if (match.Success)432                            {433                                p._startCompletionSource.TrySetResult(match.Groups[1].Value);434                            }435                        }436                    }437                    void OnProcessExitedWhileStarting(object sender, EventArgs e)438                        => p._startCompletionSource.TrySetException(new ChromiumProcessException($"Failed to launch Chromium! {output}"));439                    void OnProcessExited(object sender, EventArgs e) => Exited.EnterFrom(p, p._currentState);440                    p.Process.ErrorDataReceived += OnProcessDataReceivedWhileStarting;441                    p.Process.Exited += OnProcessExitedWhileStarting;442                    p.Process.Exited += OnProcessExited;443                    CancellationTokenSource cts = null;444                    try445                    {446                        p.Process.Start();447                        await Started.EnterFromAsync(p, this).ConfigureAwait(false);448                        p.Process.BeginErrorReadLine();449                        var timeout = p._options.Timeout;450                        if (timeout > 0)451                        {452                            cts = new CancellationTokenSource(timeout);453                            cts.Token.Register(() => p._startCompletionSource.TrySetException(454                                new ChromiumProcessException($"Timed out after {timeout} ms while trying to connect to Chromium!")));455                        }456                        try457                        {458                            await p._startCompletionSource.Task.ConfigureAwait(false);459                            await Started.EnterFromAsync(p, this).ConfigureAwait(false);460                        }461                        catch462                        {463                            await Killing.EnterFromAsync(p, this).ConfigureAwait(false);464                            throw;465                        }466                    }467                    finally468                    {469                        cts?.Dispose();470                        p.Process.Exited -= OnProcessExitedWhileStarting;471                        p.Process.ErrorDataReceived -= OnProcessDataReceivedWhileStarting;472                    }473                }474            }475            private class StartedState : State476            {477                public Task EnterFromAsync(ChromiumProcess p, State fromState)478                {479                    if (TryEnter(p, fromState))480                    {481                        // Process has not exited or been killed since transition to this state was initiated482                        LogProcessCount(p, Interlocked.Increment(ref _processCount));483                    }484                    return Task.CompletedTask;485                }486                protected override void Leave(ChromiumProcess p)487                    => LogProcessCount(p, Interlocked.Decrement(ref _processCount));488                public override Task StartAsync(ChromiumProcess p) => Task.CompletedTask;489                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);490                public override Task KillAsync(ChromiumProcess p) => Killing.EnterFromAsync(p, this);491                private static void LogProcessCount(ChromiumProcess p, int processCount)492                {493                    try494                    {495                        p._logger?.LogInformation("Process Count: {ProcessCount}", processCount);496                    }497                    catch498                    {499                        // Prevent logging exception from causing havoc500                    }501                }502            }503            private class ExitingState : State504            {505                public Task EnterFromAsync(ChromiumProcess p, State fromState, TimeSpan timeout)506                    => !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);507                public override async Task ExitAsync(ChromiumProcess p, TimeSpan timeout)508                {509                    var waitForExitTask = WaitForExitAsync(p);510                    await waitForExitTask.WithTimeout(async () =>511                    {512                        await Killing.EnterFromAsync(p, this).ConfigureAwait(false);513                        await waitForExitTask.ConfigureAwait(false);514                    }, timeout).ConfigureAwait(false);515                }516                public override Task KillAsync(ChromiumProcess p) => Killing.EnterFromAsync(p, this);517            }518            private class KillingState : State519            {520                public async Task EnterFromAsync(ChromiumProcess p, State fromState)521                {522                    if (!TryEnter(p, fromState))523                    {524                        // Delegate KillAsync to current state, because it has already changed since525                        // transition to this state was initiated.526                        await p._currentState.KillAsync(p).ConfigureAwait(false);527                    }528                    try529                    {530                        if (!p.Process.HasExited)531                        {532                            p.Process.Kill();533                        }534                    }535                    catch (InvalidOperationException)536                    {537                        // Ignore538                        return;539                    }540                    await WaitForExitAsync(p).ConfigureAwait(false);541                }542                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => WaitForExitAsync(p);543                public override Task KillAsync(ChromiumProcess p) => WaitForExitAsync(p);544            }545            private class ExitedState : State546            {547                public void EnterFrom(ChromiumProcess p, State fromState)548                {549                    while (!TryEnter(p, fromState))550                    {551                        // Current state has changed since transition to this state was requested.552                        // Therefore retry transition to this state from the current state. This ensures553                        // that Leave() operation of current state is properly called.554                        fromState = p._currentState;555                        if (fromState == this)556                        {557                            return;558                        }559                    }560                    p._exitCompletionSource.TrySetResult(true);561                    p._tempUserDataDir?.Dispose();562                }563                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => Task.CompletedTask;564                public override Task KillAsync(ChromiumProcess p) => Task.CompletedTask;565                public override Task WaitForExitAsync(ChromiumProcess p) => Task.CompletedTask;566            }567            private class DisposedState : State568            {569                public void EnterFrom(ChromiumProcess p, State fromState)570                {571                    if (!TryEnter(p, fromState))572                    {573                        // Delegate Dispose to current state, because it has already changed since574                        // transition to this state was initiated.575                        p._currentState.Dispose(p);576                    }577                    else if (fromState != Exited)578                    {579                        Kill(p);580                        p._exitCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));581                        p._tempUserDataDir?.Dispose();582                    }583                }584                public override Task StartAsync(ChromiumProcess p) => throw new ObjectDisposedException(p.ToString());585                public override Task ExitAsync(ChromiumProcess p, TimeSpan timeout) => throw new ObjectDisposedException(p.ToString());586                public override Task KillAsync(ChromiumProcess p) => throw new ObjectDisposedException(p.ToString());587                public override void Dispose(ChromiumProcess p)588                {589                    // Nothing to do590                }591            }592            #endregion593        }594        #endregion595    }596}...LauncherBase.cs
Source:LauncherBase.cs  
...101        /// Kills the Base process if it has not exited within this period.102        /// </summary>103        /// <param name="timeout">The maximum waiting time for a graceful process exit.</param>104        /// <returns></returns>105        public Task EnsureExitAsync(TimeSpan? timeout) => timeout.HasValue106            ? _currentState.ExitAsync(this, timeout.Value)107            : _currentState.KillAsync(this);108        /// <summary>109        /// Asynchronously kills Base process.110        /// </summary>111        /// <returns></returns>112        public Task KillAsync() => _currentState.KillAsync(this);113        /// <summary>114        /// Waits for Base process exit within a given timeout.115        /// </summary>116        /// <param name="timeout">The maximum wait period.</param>117        /// <returns><c>true</c> if Base process has exited within the given <paramref name="timeout"/>,118        /// or <c>false</c> otherwise.</returns>119        public async Task<bool> WaitForExitAsync(TimeSpan? timeout)120        {121            if (timeout.HasValue)122            {123                bool taskCompleted = true;124                await _exitCompletionSource.Task.WithTimeout(125                    () =>126                    {127                        taskCompleted = false;128                    }, timeout.Value).ConfigureAwait(false);129                return taskCompleted;130            }131            await _exitCompletionSource.Task.ConfigureAwait(false);132            return true;133        }134        #endregion135        #region Private methods136        /// <summary>137        /// Set Env Variables138        /// </summary>139        /// <param name="environment">The environment.</param>140        /// <param name="customEnv">The customEnv.</param>141        /// <param name="realEnv">The realEnv.</param>142        protected static void SetEnvVariables(IDictionary<string, string> environment, IDictionary<string, string> customEnv, IDictionary realEnv)143        {144            foreach (DictionaryEntry item in realEnv)145            {146                environment[item.Key.ToString()] = item.Value.ToString();147            }148            if (customEnv != null)149            {150                foreach (var item in customEnv)151                {152                    environment[item.Key] = item.Value;153                }154            }155        }156        #endregion157        #region State machine158        /// <summary>159        /// Represents state machine for Base process instances. The happy path runs along the160        /// following state transitions: <see cref="Initial"/>161        /// -> <see cref="Starting"/>162        /// -> <see cref="Started"/>163        /// -> <see cref="Exiting"/>164        /// -> <see cref="Exited"/>.165        /// -> <see cref="Disposed"/>.166        /// </summary>167        /// <remarks>168        /// <para>169        /// This state machine implements the following state transitions:170        /// <code>171        /// State     Event              Target State Action172        /// ======== =================== ============ ==========================================================173        /// Initial  --StartAsync------> Starting     Start process and wait for endpoint174        /// Initial  --ExitAsync-------> Exited       Cleanup temp user data175        /// Initial  --KillAsync-------> Exited       Cleanup temp user data176        /// Initial  --Dispose---------> Disposed     Cleanup temp user data177        /// Starting --StartAsync------> Starting     -178        /// Starting --ExitAsync-------> Exiting      Wait for process exit179        /// Starting --KillAsync-------> Killing      Kill process180        /// Starting --Dispose---------> Disposed     Kill process; Cleanup temp user data;  throw ObjectDisposedException on outstanding async operations;181        /// Starting --endpoint ready--> Started      Complete StartAsync successfully; Log process start182        /// Starting --process exit----> Exited       Complete StartAsync with exception; Cleanup temp user data183        /// Started  --StartAsync------> Started      -184        /// Started  --EnsureExitAsync-> Exiting      Start exit timer; Log process exit185        /// Started  --KillAsync-------> Killing      Kill process; Log process exit186        /// Started  --Dispose---------> Disposed     Kill process; Log process exit; Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;187        /// Started  --process exit----> Exited       Log process exit; Cleanup temp user data188        /// Exiting  --StartAsync------> Exiting      - (StartAsync throws InvalidOperationException)189        /// Exiting  --ExitAsync-------> Exiting      -190        /// Exiting  --KillAsync-------> Killing      Kill process191        /// Exiting  --Dispose---------> Disposed     Kill process; Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;192        /// Exiting  --exit timeout----> Killing      Kill process193        /// Exiting  --process exit----> Exited       Cleanup temp user data; complete outstanding async operations;194        /// Killing  --StartAsync------> Killing      - (StartAsync throws InvalidOperationException)195        /// Killing  --KillAsync-------> Killing      -196        /// Killing  --Dispose---------> Disposed     Cleanup temp user data; throw ObjectDisposedException on outstanding async operations;197        /// Killing  --process exit----> Exited       Cleanup temp user data; complete outstanding async operations;198        /// Exited   --StartAsync------> Killing      - (StartAsync throws InvalidOperationException)199        /// Exited   --KillAsync-------> Exited       -200        /// Exited   --Dispose---------> Disposed     -201        /// Disposed --StartAsync------> Disposed     -202        /// Disposed --KillAsync-------> Disposed     -203        /// Disposed --Dispose---------> Disposed     -204        /// </code>205        /// </para>206        /// </remarks>207        protected abstract class State208        {209            #region Predefined states210            /// <summary>211            /// Set initial state.212            /// </summary>213            public static readonly State Initial = new InitialState();214            private static readonly StartingState Starting = new StartingState();215            private static readonly StartedState Started = new StartedState();216            private static readonly ExitingState Exiting = new ExitingState();217            private static readonly KillingState Killing = new KillingState();218            private static readonly ExitedState Exited = new ExitedState();219            private static readonly DisposedState Disposed = new DisposedState();220            #endregion221            #region Properties222            /// <summary>223            /// Get If process exists.224            /// </summary>225            public bool IsExiting => this == Killing || this == Exiting;226            /// <summary>227            /// Get If process is exited.228            /// </summary>229            public bool IsExited => this == Exited || this == Disposed;230            #endregion231            #region Methods232            /// <summary>233            /// Attempts thread-safe transitions from a given state to this state.234            /// </summary>235            /// <param name="p">The Base process</param>236            /// <param name="fromState">The state from which state transition takes place</param>237            /// <returns>Returns <c>true</c> if transition is successful, or <c>false</c> if transition238            /// cannot be made because current state does not equal <paramref name="fromState"/>.</returns>239            protected bool TryEnter(LauncherBase p, State fromState)240            {241                if (Interlocked.CompareExchange(ref p._currentState, this, fromState) == fromState)242                {243                    fromState.Leave(p);244                    return true;245                }246                return false;247            }248            /// <summary>249            /// Notifies that state machine is about to transition to another state.250            /// </summary>251            /// <param name="p">The Base process</param>252            protected virtual void Leave(LauncherBase p)253            {254            }255            /// <summary>256            /// Handles process start request.257            /// </summary>258            /// <param name="p">The Base process</param>259            /// <returns></returns>260            public virtual Task StartAsync(LauncherBase p) => Task.FromException(InvalidOperation("start"));261            /// <summary>262            /// Handles process exit request.263            /// </summary>264            /// <param name="p">The Base process</param>265            /// <param name="timeout">The maximum waiting time for a graceful process exit.</param>266            /// <returns></returns>267            public virtual Task ExitAsync(LauncherBase p, TimeSpan timeout) => Task.FromException(InvalidOperation("exit"));268            /// <summary>269            /// Handles process kill request.270            /// </summary>271            /// <param name="p">The Base process</param>272            /// <returns></returns>273            public virtual Task KillAsync(LauncherBase p) => Task.FromException(InvalidOperation("kill"));274            /// <summary>275            /// Handles wait for process exit request.276            /// </summary>277            /// <param name="p">The Base process</param>278            /// <returns></returns>279            public virtual Task WaitForExitAsync(LauncherBase p) => p._exitCompletionSource.Task;280            /// <summary>281            /// Handles disposal of process and temporary user directory282            /// </summary>283            /// <param name="p"></param>284            public virtual void Dispose(LauncherBase p) => Disposed.EnterFrom(p, this);285            /// <inheritdoc />286            public override string ToString()287            {288                string name = GetType().Name;289                return name.Substring(0, name.Length - "State".Length);290            }291            private Exception InvalidOperation(string operationName)292                => new InvalidOperationException($"Cannot {operationName} in state {this}");293            /// <summary>294            /// Kills process if it is still alive.295            /// </summary>296            /// <param name="p"></param>297            private static void Kill(LauncherBase p)298            {299                try300                {301                    if (!p.Process.HasExited)302                    {303                        p.Process.Kill();304                    }305                }306                catch (InvalidOperationException)307                {308                    // Ignore309                }310            }311            #endregion312            #region Concrete state classes313            private class InitialState : State314            {315                public override Task StartAsync(LauncherBase p) => Starting.EnterFromAsync(p, this);316                public override Task ExitAsync(LauncherBase p, TimeSpan timeout)317                {318                    Exited.EnterFrom(p, this);319                    return Task.CompletedTask;320                }321                public override Task KillAsync(LauncherBase p)322                {323                    Exited.EnterFrom(p, this);324                    return Task.CompletedTask;325                }326                public override Task WaitForExitAsync(LauncherBase p) => Task.FromException(InvalidOperation("wait for exit"));327            }328            private class StartingState : State329            {330                public Task EnterFromAsync(LauncherBase p, State fromState)331                {332                    if (!TryEnter(p, fromState))333                    {334                        // Delegate StartAsync to current state, because it has already changed since335                        // transition to this state was initiated.336                        return p._currentState.StartAsync(p);337                    }338                    return StartCoreAsync(p);339                }340                public override Task StartAsync(LauncherBase p) => p._startCompletionSource.Task;341                public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);342                public override Task KillAsync(LauncherBase p) => Killing.EnterFromAsync(p, this);343                public override void Dispose(LauncherBase p)344                {345                    p._startCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));346                    base.Dispose(p);347                }348                private async Task StartCoreAsync(LauncherBase p)349                {350                    var output = new StringBuilder();351                    void OnProcessDataReceivedWhileStarting(object sender, DataReceivedEventArgs e)352                    {353                        if (e.Data != null)354                        {355                            output.AppendLine(e.Data);356                            var match = Regex.Match(e.Data, "^DevTools listening on (ws:\\/\\/.*)");357                            if (match.Success)358                            {359                                p._startCompletionSource.TrySetResult(match.Groups[1].Value);360                            }361                        }362                    }363                    void OnProcessExitedWhileStarting(object sender, EventArgs e)364                        => p._startCompletionSource.TrySetException(new ProcessException($"Failed to launch Base! {output}"));365                    void OnProcessExited(object sender, EventArgs e) => Exited.EnterFrom(p, p._currentState);366                    p.Process.ErrorDataReceived += OnProcessDataReceivedWhileStarting;367                    p.Process.Exited += OnProcessExitedWhileStarting;368                    p.Process.Exited += OnProcessExited;369                    CancellationTokenSource cts = null;370                    try371                    {372                        p.Process.Start();373                        await Started.EnterFromAsync(p, this).ConfigureAwait(false);374                        p.Process.BeginErrorReadLine();375                        int timeout = p._options.Timeout;376                        if (timeout > 0)377                        {378                            cts = new CancellationTokenSource(timeout);379                            cts.Token.Register(() => p._startCompletionSource.TrySetException(380                                new ProcessException($"Timed out after {timeout} ms while trying to connect to Base!")));381                        }382                        try383                        {384                            await p._startCompletionSource.Task.ConfigureAwait(false);385                            await Started.EnterFromAsync(p, this).ConfigureAwait(false);386                        }387                        catch388                        {389                            await Killing.EnterFromAsync(p, this).ConfigureAwait(false);390                            throw;391                        }392                    }393                    finally394                    {395                        cts?.Dispose();396                        p.Process.Exited -= OnProcessExitedWhileStarting;397                        p.Process.ErrorDataReceived -= OnProcessDataReceivedWhileStarting;398                    }399                }400            }401            private class StartedState : State402            {403                public Task EnterFromAsync(LauncherBase p, State fromState)404                {405                    if (TryEnter(p, fromState))406                    {407                    }408                    return Task.CompletedTask;409                }410                protected override void Leave(LauncherBase p) { }411                public override Task StartAsync(LauncherBase p) => Task.CompletedTask;412                public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);413                public override Task KillAsync(LauncherBase p) => Killing.EnterFromAsync(p, this);414            }415            private class ExitingState : State416            {417                public Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout)418                    => !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);419                public override async Task ExitAsync(LauncherBase p, TimeSpan timeout)420                {421                    var waitForExitTask = WaitForExitAsync(p);422                    await waitForExitTask.WithTimeout(423                        async () =>424                        {425                            await Killing.EnterFromAsync(p, this).ConfigureAwait(false);426                            await waitForExitTask.ConfigureAwait(false);427                        },428                        timeout,429                        CancellationToken.None).ConfigureAwait(false);430                }431                public override Task KillAsync(LauncherBase p) => Killing.EnterFromAsync(p, this);432            }433            private class KillingState : State434            {435                public async Task EnterFromAsync(LauncherBase p, State fromState)436                {437                    if (!TryEnter(p, fromState))438                    {439                        // Delegate KillAsync to current state, because it has already changed since440                        // transition to this state was initiated.441                        await p._currentState.KillAsync(p).ConfigureAwait(false);442                    }443                    try444                    {445                        if (!p.Process.HasExited)446                        {447                            p.Process.Kill();448                        }449                    }450                    catch (InvalidOperationException)451                    {452                        // Ignore453                        return;454                    }455                    await WaitForExitAsync(p).ConfigureAwait(false);456                }457                public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => WaitForExitAsync(p);458                public override Task KillAsync(LauncherBase p) => WaitForExitAsync(p);459            }460            private class ExitedState : State461            {462                public void EnterFrom(LauncherBase p, State fromState)463                {464                    while (!TryEnter(p, fromState))465                    {466                        // Current state has changed since transition to this state was requested.467                        // Therefore retry transition to this state from the current state. This ensures468                        // that Leave() operation of current state is properly called.469                        fromState = p._currentState;470                        if (fromState == this)471                        {472                            return;473                        }474                    }475                    p._exitCompletionSource.TrySetResult(true);476                    p.TempUserDataDir?.Dispose();477                }478                public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Task.CompletedTask;479                public override Task KillAsync(LauncherBase p) => Task.CompletedTask;480                public override Task WaitForExitAsync(LauncherBase p) => Task.CompletedTask;481            }482            private class DisposedState : State483            {484                public void EnterFrom(LauncherBase p, State fromState)485                {486                    if (!TryEnter(p, fromState))487                    {488                        // Delegate Dispose to current state, because it has already changed since489                        // transition to this state was initiated.490                        p._currentState.Dispose(p);491                    }492                    else if (fromState != Exited)493                    {494                        Kill(p);495                        p._exitCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));496                        p.TempUserDataDir?.Dispose();497                    }498                }499                public override Task StartAsync(LauncherBase p) => throw new ObjectDisposedException(p.ToString());500                public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => throw new ObjectDisposedException(p.ToString());501                public override Task KillAsync(LauncherBase p) => throw new ObjectDisposedException(p.ToString());502                public override void Dispose(LauncherBase p)503                {504                    // Nothing to do505                }506            }507            #endregion508        }509        #endregion510    }511}...InitialState.cs
Source:InitialState.cs  
...7        public InitialState(StateManager stateManager) : base(stateManager)8        {9        }10        public override Task StartAsync(LauncherBase p) => StateManager.Starting.EnterFromAsync(p, this, TimeSpan.Zero);11        public override Task ExitAsync(LauncherBase p, TimeSpan timeout)12        {13            StateManager.Exited.EnterFromAsync(p, this);14            return Task.CompletedTask;15        }16        public override Task KillAsync(LauncherBase p)17        {18            StateManager.Exited.EnterFromAsync(p, this);19            return Task.CompletedTask;20        }21        public override Task WaitForExitAsync(LauncherBase p) => Task.FromException(InvalidOperation("wait for exit"));22        private Exception InvalidOperation(string v)23        {24            throw new NotImplementedException();25        }26    }27}...ExitAsync
Using AI Code Generation
1await browser.CloseAsync();2await browser.CloseAsync();3await browser.CloseAsync();4await browser.CloseAsync();5await browser.CloseAsync();6await browser.CloseAsync();7await browser.CloseAsync();8await browser.CloseAsync();9await browser.CloseAsync();10await browser.CloseAsync();11await browser.CloseAsync();12await browser.CloseAsync();13await browser.CloseAsync();14await browser.CloseAsync();15await browser.CloseAsync();16await browser.CloseAsync();17await browser.CloseAsync();18await browser.CloseAsync();ExitAsync
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        static async Task Main(string[] args)7        {8            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });10            var page = await browser.NewPageAsync();11            await page.WaitForSelectorAsync("input[name=q]");12            await page.TypeAsync("input[name=q]", "Hello World");13            await page.ClickAsync("input[name=btnK]");14            await page.WaitForNavigationAsync();15            await browser.CloseAsync();16        }17    }18}19using System;20using System.Threading.Tasks;21using PuppeteerSharp;22{23    {24        static async Task Main(string[] args)25        {26            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);27            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });28            var page = await browser.NewPageAsync();29            await page.WaitForSelectorAsync("input[name=q]");30            await page.TypeAsync("input[name=q]", "Hello World");31            await page.ClickAsync("input[name=btnK]");32            await page.WaitForNavigationAsync();33            await browser.ExitAsync();34        }35    }36}37using System;38using System.Threading.Tasks;39using PuppeteerSharp;40{41    {42        static async Task Main(string[] args)43        {44            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);45            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });46            var page = await browser.NewPageAsync();47            await page.WaitForSelectorAsync("input[name=q]");48            await page.TypeAsync("input[name=q]", "Hello World");49            await page.ClickAsync("input[name=btnK]");50            await page.WaitForNavigationAsync();51            await browser.ExitAsync();52        }53    }54}ExitAsync
Using AI Code Generation
1var browser = await Puppeteer.LaunchAsync(new LaunchOptions2{3    Args = new[] { "--no-sandbox" }4});5var page = await browser.NewPageAsync();6Console.WriteLine(await page.GetContentAsync());7await page.CloseAsync();8await browser.CloseAsync();9await browser.ExitAsync();10var browser = await Puppeteer.LaunchAsync(new LaunchOptions11{12    Args = new[] { "--no-sandbox" }13});14var page = await browser.NewPageAsync();15Console.WriteLine(await page.GetContentAsync());16await page.CloseAsync();17await browser.CloseAsync();18await browser.KillAsync();19var browser = await Puppeteer.LaunchAsync(new LaunchOptions20{21    Args = new[] { "--no-sandbox" }22});23var page = await browser.NewPageAsync();24Console.WriteLine(await page.GetContentAsync());25await page.CloseAsync();26await browser.CloseAsync();27await browser.KillChrome();28var browser = await Puppeteer.LaunchAsync(new LaunchOptions29{30    Args = new[] { "--no-sandbox" }31});32var page = await browser.NewPageAsync();33Console.WriteLine(await page.GetContentAsync());34await page.CloseAsync();35await browser.CloseAsync();36await browser.KillChrome();37var browser = await Puppeteer.LaunchAsync(new LaunchOptions38{39    Args = new[] { "--no-sandbox" }40});41var page = await browser.NewPageAsync();42Console.WriteLine(await page.GetContentAsync());43await page.CloseAsync();44await browser.CloseAsync();45await browser.KillChrome();ExitAsync
Using AI Code Generation
1var  browser =  await  Puppeteer.LaunchAsync( new  LaunchOptions { Headless =  false  });2 var  page =  await  browser.NewPageAsync();3 await  page.WaitForSelectorAsync( "input[title='Search']" );4 await  page.TypeAsync( "input[title='Search']" ,  "Hello World" );5 await  page.Keyboard.PressAsync( "Enter" );6 await  page.WaitForNavigationAsync();7 await  page.ScreenshotAsync( "screenshot.png" );8 await  browser.CloseAsync();9var  browser =  await  Puppeteer.LaunchAsync( new  LaunchOptions { Headless =  false  });10 var  page =  await  browser.NewPageAsync();11 await  page.WaitForSelectorAsync( "input[title='Search']" );12 await  page.TypeAsync( "input[title='Search']" ,  "Hello World" );13 await  page.Keyboard.PressAsync( "Enter" );14 await  page.WaitForNavigationAsync();15 await  page.ScreenshotAsync( "screenshot.png" );16 await  browser.ExitAsync();17var  browser =  await  Puppeteer.LaunchAsync( new  LaunchOptions { Headless =  false  });18 var  page =  await  browser.NewPageAsync();19 await  page.WaitForSelectorAsync( "input[title='Search']" );20 await  page.TypeAsync( "input[title='Search']" ,  "Hello World" );21 await  page.Keyboard.PressAsync( "Enter" );22 await  page.WaitForNavigationAsync();23 await  page.ScreenshotAsync( "screenshot.png" );24 await  browser.ExitAsync();25var  browser =  await  Puppeteer.LaunchAsync( new  LaunchOptions { Headless =  false  });26 var  page =  await  browser.NewPageAsync();27 await  page.GoToAsync( "ExitAsync
Using AI Code Generation
1var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });2var page = await browser.NewPageAsync();3await page.WaitForSelectorAsync("input[name=q]");4await page.TypeAsync("input[name=q]", "PuppeteerSharp");5await page.Keyboard.PressAsync("Enter");6await page.WaitForNavigationAsync();7await page.ScreenshotAsync("google.png");8await browser.CloseAsync();9await browser.ExitAsync();10var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });11var page = await browser.NewPageAsync();12await page.WaitForSelectorAsync("input[name=q]");13await page.TypeAsync("input[name=q]", "PuppeteerSharp");14await page.Keyboard.PressAsync("Enter");15await page.WaitForNavigationAsync();16await page.ScreenshotAsync("google.png");17await browser.CloseAsync();18await browser.KillAsync();19var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });20var page = await browser.NewPageAsync();21await page.WaitForSelectorAsync("input[name=q]");22await page.TypeAsync("input[name=q]", "PuppeteerSharp");23await page.Keyboard.PressAsync("Enter");24await page.WaitForNavigationAsync();25await page.ScreenshotAsync("google.png");26await browser.CloseAsync();27await browser.KillAsync();28var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });29var page = await browser.NewPageAsync();30await page.WaitForSelectorAsync("input[name=q]");31await page.TypeAsync("input[name=q]", "PuppeteerSharp");32await page.Keyboard.PressAsync("Enter");33await page.WaitForNavigationAsync();34await page.ScreenshotAsync("google.png");35await browser.CloseAsync();36await browser.KillAsync();ExitAsync
Using AI Code Generation
1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        public static async Task Main(string[] args)7        {8            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });9            var page = await browser.NewPageAsync();10            await browser.CloseAsync();11        }12    }13}14using PuppeteerSharp;15using System;16using System.Threading.Tasks;17{18    {19        public static async Task Main(string[] args)20        {21            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });22            var page = await browser.NewPageAsync();23            await browser.CloseAsync();24            await browser.CloseAsync();25        }26    }27}28using PuppeteerSharp;29using System;30using System.Threading.Tasks;31{32    {33        public static async Task Main(string[] args)34        {35            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });36            var page = await browser.NewPageAsync();37            await browser.CloseAsync();38            await browser.CloseAsync();39            await browser.CloseAsync();40        }41    }42}43using PuppeteerSharp;44using System;45using System.Threading.Tasks;46{47    {48        public static async Task Main(string[] args)49        {50            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });51            var page = await browser.NewPageAsync();52            await browser.CloseAsync();53            await browser.CloseAsync();54            await browser.CloseAsync();55            await browser.CloseAsync();56        }57    }58}ExitAsync
Using AI Code Generation
1var state = new InitialState();2await state.ExitAsync();3await state.ExitAsync();4await state.ExitAsync();5var state = new InitialState();6await state.ExitAsync();7await state.ExitAsync();8await state.ExitAsync();9var state = new InitialState();10await state.ExitAsync();11await state.ExitAsync();12await state.ExitAsync();13var state = new InitialState();14await state.ExitAsync();15await state.ExitAsync();16await state.ExitAsync();17var state = new InitialState();18await state.ExitAsync();19await state.ExitAsync();20await state.ExitAsync();21var state = new InitialState();22await state.ExitAsync();23await state.ExitAsync();24await state.ExitAsync();25var state = new InitialState();26await state.ExitAsync();27await state.ExitAsync();28await state.ExitAsync();29var state = new InitialState();30await state.ExitAsync();31await state.ExitAsync();32await state.ExitAsync();33var state = new InitialState();34await state.ExitAsync();35await state.ExitAsync();36await state.ExitAsync();37var state = new InitialState();38await state.ExitAsync();39await state.ExitAsync();40await state.ExitAsync();41var state = new InitialState();42await state.ExitAsync();43await state.ExitAsync();44await state.ExitAsync();ExitAsync
Using AI Code Generation
1await page.WaitForSelectorAsync("input[name=q]");2await page.TypeAsync("input[name=q]", "PuppeteerSharp");3await page.ClickAsync("input[name=btnK]");4await page.WaitForNavigationAsync();5await page.CloseAsync();6await page.WaitForSelectorAsync("input[name=q]");7await page.TypeAsync("input[name=q]", "PuppeteerSharp");8await page.ClickAsync("input[name=btnK]");9await page.WaitForNavigationAsync();10await page.CloseAsync();11await page.WaitForSelectorAsync("input[name=q]");12await page.TypeAsync("input[name=q]", "PuppeteerSharp");13await page.ClickAsync("input[name=btnK]");14await page.WaitForNavigationAsync();15await page.CloseAsync();16await page.WaitForSelectorAsync("input[name=q]");17await page.TypeAsync("input[name=q]", "PuppeteerSharp");18await page.ClickAsync("input[name=btnK]");19await page.WaitForNavigationAsync();20await page.CloseAsync();21await page.WaitForSelectorAsync("input[name=q]");22await page.TypeAsync("input[name=q]", "PuppeteerSharp");23await page.ClickAsync("input[name=btnK]");24await page.WaitForNavigationAsync();25await page.CloseAsync();26await page.WaitForSelectorAsync("input[name=q]");27await page.TypeAsync("input[name=q]", "PuppeteerSharp");28await page.ClickAsync("input[name=btnK]");29await page.WaitForNavigationAsync();30await page.CloseAsync();ExitAsync
Using AI Code Generation
1var exitcode = await state.ExitAsync();2var exitcode = state.Exit();3var exitcode = await state.ExitAsync();4var exitcode = state.Exit();5var exitcode = await state.ExitAsync();6var exitcode = state.Exit();7var exitcode = await state.ExitAsync();8var exitcode = state.Exit();9var exitcode = await state.ExitAsync();10var exitcode = state.Exit();11var exitcode = await state.ExitAsync();12var exitcode = state.Exit();13var exitcode = await state.ExitAsync();14var exitcode = state.Exit();15var exitcode = await state.ExitAsync();16var exitcode = state.Exit();17var exitcode = await state.ExitAsync();18var exitcode = state.Exit();Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
