Michael Tot Korsgaard
Michael Tot Korsgaard

Reputation: 4014

Application won't crash on purpose while in another thread

I'm trying to crash my Console application after a certain amount of time (this is due to me testing whether the application will start itself after crashing. Following this tutorial)

What I have for this is this piece of code:

static class WebSocket
{
    static int Main(string[] args)
    {
        Recovery.RegisterForAutostart();
        Recovery.RegisterForRestart();
        Test.Run();

        // some more code
    }
}

public static class Recovery
{
    [Flags]
    public enum RestartRestrictions
    {
        None = 0,
        NotOnCrash = 1,
        NotOnHang = 2,
        NotOnPatch = 4,
        NotOnReboot = 8
    }

    public delegate int RecoveryDelegate(RecoveryData parameter);

    public static class ArrImports
    {
        [DllImport("kernel32.dll")]
        public static extern void ApplicationRecoveryFinished(
            bool success);

        [DllImport("kernel32.dll")]
        public static extern int ApplicationRecoveryInProgress(
            out bool canceled);

        [DllImport("kernel32.dll")]
        public static extern int GetApplicationRecoveryCallback(
            IntPtr processHandle,
            out RecoveryDelegate recoveryCallback,
            out RecoveryData parameter,
            out uint pingInterval,
            out uint flags);

        [DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern int GetApplicationRestartSettings(
            IntPtr process,
            IntPtr commandLine,
            ref uint size,
            out uint flags);

        [DllImport("kernel32.dll")]
        public static extern int RegisterApplicationRecoveryCallback(
            RecoveryDelegate recoveryCallback,
            RecoveryData parameter,
            uint pingInterval,
            uint flags);

        [DllImport("kernel32.dll")]
        public static extern int RegisterApplicationRestart(
            [MarshalAs(UnmanagedType.BStr)] string commandLineArgs,
            int flags);

        [DllImport("kernel32.dll")]
        public static extern int UnregisterApplicationRecoveryCallback();

        [DllImport("kernel32.dll")]
        public static extern int UnregisterApplicationRestart();
    }

    public class RecoveryData
    {
        string currentUser;

        public RecoveryData(string who)
        {
            currentUser = who;
        }
        public string CurrentUser
        {
            get { return currentUser; }
        }
    }

    //  Restart after crash
    public static void RegisterForRestart()
    {
        // Register for automatic restart if the application was terminated for any reason.
        ArrImports.RegisterApplicationRestart("/restart",
           (int)RestartRestrictions.None);
    }

    //  Start app when PC starts
    public static void RegisterForAutostart()
    {
    #if (!DEBUG)
        RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
        key.SetValue("websocket", @"c:\websocket\run.bat");
    #endif
    }

public static class Test
{
    public static void Run()
    {
        crash();
    }

    static void crash()
    {
        double crashAfter = 1.5 * 60; //  seconds
        int secondsPassed = 0;
        int waitSeconds = 1;

        Console.WriteLine("\nCrash test startet, crash will occour in " + crashAfter + " seconds");

        Timer timer = new Timer(
            delegate (object seconds) {
                secondsPassed += int.Parse(seconds.ToString());
                if (secondsPassed > crashAfter)
                {
                    Console.WriteLine("Crashing");
                    Environment.FailFast("Test - intentional crash."); // Error happens here
                }
                else
                {
                    double timeUntilCrash = (crashAfter - secondsPassed);
                    Console.WriteLine("Time until crash = " + timeUntilCrash + " seconds");
                }
            },
            waitSeconds,
            TimeSpan.FromSeconds(waitSeconds),
            TimeSpan.FromSeconds(waitSeconds));
    }
}

When it's time to crash I get this message:

Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible, possibly because the code is optimized.

The checkbox for code optimization is unchecked.

I surpose this is because it's not in the main thread, if this is the case how do I return to the main thread. And if not, what might be the cause?

Upvotes: 1

Views: 200

Answers (2)

PaulF
PaulF

Reputation: 6773

I created an application based on your code & found that everything runs as expected when the application is run from the command-line - it is only in Visual Studio debugger the restart does not work.

Upvotes: 1

Michael Tot Korsgaard
Michael Tot Korsgaard

Reputation: 4014

Thanks to PaulF we found the problem. I was testing in Debug mode, running the application in release mode outside of Visual Studio fixed the problem. The following NullReferenceException was caused by missing command line arguments upon restart.

Upvotes: 0

Related Questions