예제 #1
0
        public static void Open()
        {
#if UNITY_STANDALONE_WIN
#pragma warning disable 0618
            if (realOut == null)
            {
                realOut = Console.Out;
            }

            var hasConsole = PInvoke.AttachConsole(0x0ffffffff);
            if (hasConsole == false)
            {
                PInvoke.AllocConsole();
            }

            try {
                // grab handle ptr
                var outHandlePtr = PInvoke.GetStdHandle(PInvoke.STD_OUTPUT_HANDLE);

                // we can then create a filestream from this handle
                var fileStream = new FileStream(outHandlePtr, FileAccess.Write);

                // and then create a new stream writer (using ASCII)
                var stdOut = new StreamWriter(fileStream, Encoding.ASCII);
                stdOut.AutoFlush = true;

                // and force unity to use this
                Console.SetOut(stdOut);
            }
            catch (System.Exception e) {
                Debug.Log(e);
            }
#pragma warning restore 0618
#endif
        }
예제 #2
0
        public static void Main()
        {
            using var exitEvent = new ManualResetEvent(initialState: false);
            using var cts       = new CancellationTokenSource();

            // close console and attach to parent
            // if the app is started from a console the logs are shown directly in the parent console
            // and it is blocked until this app exits.
            // (Windows Application + AttachConsole does not block the parent console)
            if (PInvoke.AttachConsole(Constants.ATTACH_PARENT_PROCESS))
            {
                PInvoke.FreeConsole();
            }
            PInvoke.AttachConsole(Constants.ATTACH_PARENT_PROCESS);

            // handle exit events (probably overkill)
            PInvoke.SetConsoleCtrlHandler(new PHANDLER_ROUTINE(sig => {
                switch (sig)
                {
                case Constants.CTRL_C_EVENT:
                case Constants.CTRL_LOGOFF_EVENT:
                case Constants.CTRL_SHUTDOWN_EVENT:
                case Constants.CTRL_CLOSE_EVENT:
                    Stop();
                    // wait for shutdown and cleanup
                    exitEvent.WaitOne(TimeSpan.FromSeconds(5));
                    return(true);

                default:
                    return(false);
                }
            }), true);
            AppDomain.CurrentDomain.ProcessExit += (_, __) => Stop();
            Console.CancelKeyPress += (_, __) => Stop();

            SetupLogging();

            try {
                Log.Information("Starting up...");

                using var mutex = new Mutex(initiallyOwned: true, SingletonMutexName, out var notAlreadyRunning);
                if (notAlreadyRunning)   // we are the only one around :(
                {
                    try {
                        Execute(cts.Token);
                    } finally {
                        mutex.ReleaseMutex();
                    }
                }
                else     // another instance is already running
                {
                    Log.Information("Another instance is already running.");
                }
            } catch (Exception e) {
                Log.Error(e, "Unexpected error");
            }

            Log.CloseAndFlush();
            exitEvent.Set();

            void Stop()
            {
                if (cts.IsCancellationRequested)
                {
                    return;
                }

                Log.Information("Shutting down...");
                try {
                    cts.Cancel();
                } catch (ObjectDisposedException) {
                    // we dont care about the error as this just means that the cts wa
                    // already canceled and disposed which we wanted to do anyway
                }
            }
        }