Winforms: Application.Restart throws InvalidOperationException

Created on 25 Jan 2020  路  12Comments  路  Source: dotnet/winforms

  • .NET Core Version:
    3.1.1

  • Have you experienced this same bug with .NET Framework?:
    No - this has always worked fine on .NET Framework!

Problem description:
Calling Application.Restart in a .NET Core WinForms application does not work as it does on .NET Framework. An exception is thrown:

System.InvalidOperationException: Process was not started by this object, so requested information cannot be determined.
   at System.Diagnostics.Process.get_StartInfo()
   at System.Windows.Forms.Application.Restart()

I also tried launching the exe without the debugger, but that doesn't make a difference.

Additionally, there is no note or breaking change detailing any .NET Core changes.

Expected behavior:
Application.Restart should work the same as it does on .NET Framework.

Minimal repro:
Create a new .NET Core WinForms project in Visual Studio, put Application.Restart anywhere (even under InitializeComponent in Form1), run it, and observe the exception.

bug regression

Most helpful comment

@RussKie I couldn't get it working when I tried before, but I tried again and this time I realized why. Turns out, there is a _second bug_ in there, but that one is already being fixed, by you!馃榿

I modified the method a bit and it works fine now.

private void Restart()
{
    string[] arguments = Environment.GetCommandLineArgs();
    Debug.Assert(arguments != null && arguments.Length > 0);
    StringBuilder sb = new StringBuilder((arguments.Length - 1) * 16);
    for (int argumentIndex = 1; argumentIndex < arguments.Length - 1; argumentIndex++)
    {
        sb.Append('"');
        sb.Append(arguments[argumentIndex]);
        sb.Append("\" ");
    }
    if (arguments.Length > 1)
    {
        sb.Append('"');
        sb.Append(arguments[arguments.Length - 1]);
        sb.Append('"');
    }
    ProcessStartInfo currentStartInfo = new ProcessStartInfo();
    currentStartInfo.FileName = Path.ChangeExtension(Application.ExecutablePath, "exe");
    if (sb.Length > 0)
    {
        currentStartInfo.Arguments = sb.ToString();
    }
    Application.Exit();
    Process.Start(currentStartInfo);
}

All 12 comments

@danmosemsft @stephentoub @davkean for us this is a regression caused by a change introduced in https://github.com/dotnet/corefx/pull/1167

Could you please provide guidance on how to restart the app?

https://github.com/dotnet/winforms/blob/62c17fe35b2f00f8156828148a5fbbb910cc52a1/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs#L1172-L1195

Application.Restart and .NET Core 1.0 didn't exist at the time that change was checked in, so its not a regression. Probably need a bug against CoreFx to let you look at the StartInfo of a process if its the "current process".

For us it is a regression because it worked in .NET Framework and it doesn't work in .NET Core.

The only valid piece of Process.GetCurrentProcess().StartInfo was the environment variables, which are also populated when creating a new PSI. Just create a new PSI and populate it as you already are, e.g. replace:
```C#
Process.GetCurrentProcess().StartInfo

with
```C#
new ProcessStartInfo()

That's simpler and cheaper.

Hi @merriemcgaw, is the fix really only going to make it for 5.0?
If that is the case, does anyone have any temporary workarounds I can use here?

I'm confident once it is fixed, it will be considered for a servicing in 3.1.

As an interim workaround you could copy the implementation of Application.Restart into your app.
https://github.com/dotnet/winforms/blob/62c17fe35b2f00f8156828148a5fbbb910cc52a1/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs#L1173-L1195

@RussKie I couldn't get it working when I tried before, but I tried again and this time I realized why. Turns out, there is a _second bug_ in there, but that one is already being fixed, by you!馃榿

I modified the method a bit and it works fine now.

private void Restart()
{
    string[] arguments = Environment.GetCommandLineArgs();
    Debug.Assert(arguments != null && arguments.Length > 0);
    StringBuilder sb = new StringBuilder((arguments.Length - 1) * 16);
    for (int argumentIndex = 1; argumentIndex < arguments.Length - 1; argumentIndex++)
    {
        sb.Append('"');
        sb.Append(arguments[argumentIndex]);
        sb.Append("\" ");
    }
    if (arguments.Length > 1)
    {
        sb.Append('"');
        sb.Append(arguments[arguments.Length - 1]);
        sb.Append('"');
    }
    ProcessStartInfo currentStartInfo = new ProcessStartInfo();
    currentStartInfo.FileName = Path.ChangeExtension(Application.ExecutablePath, "exe");
    if (sb.Length > 0)
    {
        currentStartInfo.Arguments = sb.ToString();
    }
    Application.Exit();
    Process.Start(currentStartInfo);
}

Btw you're welcome to send a PR with the fix 馃槈

@RussKie I wasn't sure if the proper fix was that simple... but I guess it is, so I just submitted a PR.馃榿

This particular bug, since it's not blocking you at the moment, doesn't meet the servicing bar for 3.1, but I am very glad you got it in for 5.0. If we find out that this is blocking someone and impacting customers then I believe it would meet the bar and we'd take it. But at this point the workaround is a viable one I'm afraid.

Hi @merriemcgaw, I think it's a long time to wait until November for a 1-line fix. If that is what you want to do, then I suggest documenting this breakage somewhere so people will be able to find the workaround when searching.

OMG, I just realized that we are using Application.Restart too :scream: Another one obstruction on migrating process :rage:
@EatonZ thank you very match for workaround!!!

Was this page helpful?
0 / 5 - 0 ratings