|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.CodeAnalysis.ErrorReporting;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Interactive
{
internal static class InteractiveHostEntryPoint
{
private static async Task<int> Main(string[] args)
{
FatalError.SetHandlers(FailFast.Handler, nonFatalHandler: null);
// Disables Windows Error Reporting for the process, so that the process fails fast.
SetErrorMode(GetErrorMode() | ErrorMode.SEM_FAILCRITICALERRORS | ErrorMode.SEM_NOOPENFILEERRORBOX | ErrorMode.SEM_NOGPFAULTERRORBOX);
Contract.ThrowIfFalse(args.Length == 4, "Expecting arguments: <pipe name> <client process id> <culture name> <ui culture name>");
var pipeName = args[0];
var clientProcessId = int.Parse(args[1], CultureInfo.InvariantCulture);
var culture = new CultureInfo(args[2]);
var uiCulture = new CultureInfo(args[3]);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = uiCulture;
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = uiCulture;
Control? control = null;
using (var resetEvent = new ManualResetEventSlim(false))
{
var uiThread = new Thread(() =>
{
control = new Control();
control.CreateControl();
resetEvent.Set();
Application.Run();
});
uiThread.SetApartmentState(ApartmentState.STA);
uiThread.IsBackground = true;
uiThread.Start();
resetEvent.Wait();
}
var invokeOnMainThread = new Func<Func<object>, object>(operation => control!.Invoke(operation));
try
{
await InteractiveHost.Service.RunServerAsync(pipeName, clientProcessId, invokeOnMainThread).ConfigureAwait(false);
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine(e);
return 1;
}
}
[DllImport("kernel32", PreserveSig = true)]
internal static extern ErrorMode SetErrorMode(ErrorMode mode);
[DllImport("kernel32", PreserveSig = true)]
internal static extern ErrorMode GetErrorMode();
[Flags]
internal enum ErrorMode : int
{
/// <summary>
/// Use the system default, which is to display all error dialog boxes.
/// </summary>
SEM_FAILCRITICALERRORS = 0x0001,
/// <summary>
/// The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.
/// Best practice is that all applications call the process-wide SetErrorMode function with a parameter of SEM_FAILCRITICALERRORS at startup.
/// This is to prevent error mode dialogs from blocking the application.
/// </summary>
SEM_NOGPFAULTERRORBOX = 0x0002,
/// <summary>
/// The system automatically fixes memory alignment faults and makes them invisible to the application.
/// It does this for the calling process and any descendant processes. This feature is only supported by
/// certain processor architectures. For more information, see the Remarks section.
/// After this value is set for a process, subsequent attempts to clear the value are ignored.
/// </summary>
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
/// <summary>
/// The system does not display a message box when it fails to find a file. Instead, the error is returned to the calling process.
/// </summary>
SEM_NOOPENFILEERRORBOX = 0x8000,
}
}
}
|