Example #1
0
    static void _Main(string[] args)
    {
        //Debug_.PrintLoadedAssemblies(true, !true);

        AppDomain.CurrentDomain.UnhandledException += _UnhandledException;
        process.ThisThreadSetComApartment_(ApartmentState.STA);
        process.thisProcessCultureIsInvariant = true;
        DebugTraceListener.Setup(usePrint: true);
        Directory.SetCurrentDirectory(folders.ThisApp);                     //it is c:\windows\system32 when restarted as admin
        Api.SetSearchPathMode(Api.BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); //let SearchPath search in current directory after system directories
        Api.SetErrorMode(Api.GetErrorMode() | Api.SEM_FAILCRITICALERRORS);  //disable some error message boxes, eg when removable media not found; MSDN recommends too.
        _SetThisAppDocuments();

        if (CommandLine.ProgramStarted2(args))
        {
            return;
        }

        PrintServer = new print.Server(true)
        {
            NoNewline = true
        };
        PrintServer.Start();
#if TRACE
        print.qm2.use = !true;
        //timer.after(1, _ => perf.nw());
#endif

        perf.next('o');
        Settings = AppSettings.Load();         //the slowest part, >50 ms. Loads many dlls.
        //Debug_.PrintLoadedAssemblies(true, !true);
        perf.next('s');
        UserGuid = Settings.user; if (UserGuid == null)
        {
            Settings.user = UserGuid = Guid.NewGuid().ToString();
        }

        AssemblyLoadContext.Default.Resolving             += _Assembly_Resolving;
        AssemblyLoadContext.Default.ResolvingUnmanagedDll += _UnmanagedDll_Resolving;

        Tasks = new RunningTasks();
        perf.next('t');

        script.editor.IconNameToXaml_ = (s, what) => DIcons.GetIconString(s, what);
        FilesModel.LoadWorkspace(CommandLine.WorkspaceDirectory);
        perf.next('W');
        CommandLine.ProgramLoaded();
        perf.next('c');
        Loaded = EProgramState.LoadedWorkspace;

        timer.every(1000, t => _TimerProc(t));
        //note: timer can make Process Hacker/Explorer show CPU usage, even if we do nothing. Eg 0.02 if 250, 0.01 if 500, <0.01 if 1000.
        //Timer1s += () => print.it("1 s");
        //Timer1sOr025s += () => print.it("0.25 s");

        TrayIcon.Update_();
        perf.next('i');

        _app = new() {
            ShutdownMode = ShutdownMode.OnExplicitShutdown             //will set OnMainWindowClose when creating main window. If now, would exit if a startup script shows/closes a WPF window.
        };
        _app.Dispatcher.InvokeAsync(() => Model.RunStartupScripts());
        if (!Settings.runHidden || CommandLine.StartVisible)
        {
            _app.Dispatcher.Invoke(() => ShowWindow());
        }
        try {
            _app.Run();
            //Hidden app should start as fast as possible, because usually starts with Windows.
            //Tested with native message loop. Faster by 70 ms (240 vs 310 without the .NET startup time).
            //	But then problems. Eg cannot auto-create main window synchronously, because need to exit native loop and start WPF loop.
        }
        finally {
            Loaded = EProgramState.Unloading;
            var fm = Model; Model = null;
            fm.Dispose();             //stops tasks etc
            Loaded = EProgramState.Unloaded;

            PrintServer.Stop();
        }
    }