351 lines
12 KiB
C#
351 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using Cysharp.Threading.Tasks;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
// ReSharper disable StringLiteralTypo
|
|
#if NET5_0_OR_GREATER
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
#endif
|
|
|
|
namespace BITKit
|
|
{
|
|
public class AppIsNotPlayingException : Exception
|
|
{
|
|
public override string Message => "Application Is Not Playing";
|
|
}
|
|
// ReSharper disable once InconsistentNaming
|
|
public class BITApp
|
|
{
|
|
public static async UniTask SwitchToMainThread()
|
|
{
|
|
#if UNITY_5_3_OR_NEWER
|
|
await UniTask.SwitchToMainThread();
|
|
#else
|
|
if (SynchronizationContext is null)
|
|
{
|
|
return;
|
|
}
|
|
await UniTask.SwitchToSynchronizationContext(SynchronizationContext);
|
|
#endif
|
|
}
|
|
public static class Time
|
|
{
|
|
public static float ElapsedTime { get; set; }
|
|
public static float DeltaTime { get; set; }
|
|
public static double TimeAsDouble { get; set; }
|
|
|
|
}
|
|
[System.Serializable]
|
|
public record AppSettings
|
|
{
|
|
public bool AllowInitialize = true;
|
|
public List<string> whiteList = new();
|
|
public List<string> blackList = new()
|
|
{
|
|
"System",
|
|
"Unity",
|
|
"UnityEngine",
|
|
"Microsoft",
|
|
"Godot",
|
|
"Internal",
|
|
"GodotPlugins",
|
|
// ReSharper disable once StringLiteralTypo
|
|
"Cysharp",
|
|
"kcp2k",
|
|
"Swashbuckle",
|
|
"Newtonsoft",
|
|
"Lightbug",
|
|
"NiceIO",
|
|
"AndroidPlayerBuildProgram",
|
|
"Steamworks",
|
|
"AYellowpaper",
|
|
"Utilities",
|
|
"mattatz",
|
|
"AmazingAssets",
|
|
"MeshCombineStudio",
|
|
"kcp2k",
|
|
"AYellowpaper",
|
|
"MudBlazor",
|
|
"TextCopy",
|
|
"Blazored",
|
|
"TextCopy",
|
|
"mattatz",
|
|
"TrailsFX",
|
|
"Knife",
|
|
"Needle",
|
|
"NiceIO",
|
|
"AndroidPlayerBuildProgram",
|
|
"DocCodeExamples",
|
|
"System",
|
|
"UnityEngine",
|
|
"Unity",
|
|
"Microsoft",
|
|
"UnityEditor",
|
|
"Google",
|
|
"Mono",
|
|
"ZXing",
|
|
"ImmersiveVRTools",
|
|
"MonKey",
|
|
"FLib",
|
|
"Kcp",
|
|
"Udx",
|
|
"Sirenix",
|
|
"TMPro",
|
|
"RotaryHeart",
|
|
"Cinemachine",
|
|
"ParadoxNotion",
|
|
"Net",
|
|
"VSCodeEditor",
|
|
"AOT",
|
|
"UnityEditorInternal",
|
|
"UnityEngineInternal",
|
|
"JetBrains",
|
|
"Bee",
|
|
"NotInvited",
|
|
"HighlightPlus",
|
|
"DG",
|
|
"Hierarchy2",
|
|
"Cysharp",
|
|
"JetBrains",
|
|
"Packages",
|
|
"Newtonsoft_X",
|
|
"Binding",
|
|
"NodeCanvas",
|
|
"SaveDuringPlay",
|
|
"LimWorks",
|
|
"MagicaCloth2",
|
|
"FastScriptReload",
|
|
"ParrelSync",
|
|
"KinematicCharacterController",
|
|
"LimWorksEditor",
|
|
"BuildComponent",
|
|
"dnlib",
|
|
"BigIntegerLibrary",
|
|
"Ionic",
|
|
"log4net",
|
|
"ImmersiveVrToolsCommon",
|
|
"NUnit",
|
|
"HarmonyLib",
|
|
"MonoMod",
|
|
"WebDav",
|
|
"PlasticGui",
|
|
"Codice",
|
|
"GluonGui",
|
|
"PlasticPipe",
|
|
"XDiffGui",
|
|
"MacFsWatcher",
|
|
"MacUI",
|
|
"PlayerBuildProgramLibrary",
|
|
"ExCSS",
|
|
"ScriptCompilationBuildProgram",
|
|
"BeeBuildProgramCommon",
|
|
"Accessibility",
|
|
"CodiceApp",
|
|
"Newtonsoft",
|
|
"MergetoolGui",
|
|
"TreeEditor",
|
|
"MackySoft",
|
|
"FullscreenEditor",
|
|
"mattatz",
|
|
"AYellowpaper",
|
|
"kcp2k",
|
|
"MeshCombineStudio",
|
|
"AmazingAssets",
|
|
"Utilities",
|
|
"Pinwheel",
|
|
"TinyScript",
|
|
"YooAsset",
|
|
"Timeline.Samples",
|
|
"FAE",
|
|
"MK",
|
|
"Lzf",
|
|
"MySql",
|
|
};
|
|
}
|
|
/// <summary>
|
|
/// 依赖服务集合
|
|
/// </summary>
|
|
public static ServiceCollection ServiceCollection { get; set; } = new();
|
|
/// <summary>
|
|
/// 依赖服务提供接口
|
|
/// </summary>
|
|
public static ServiceProvider ServiceProvider
|
|
{
|
|
get=>_serviceProvider??=ServiceCollection.BuildServiceProvider();
|
|
set => _serviceProvider = value;
|
|
}
|
|
private static ServiceProvider _serviceProvider;
|
|
/// <summary>
|
|
/// 主线程
|
|
/// </summary>
|
|
public static SynchronizationContext SynchronizationContext { get; set; } =
|
|
SynchronizationContext.Current;
|
|
|
|
[System.Serializable]
|
|
public class OpenPath : IDisposable
|
|
{
|
|
public string path;
|
|
|
|
public void Dispose()
|
|
{
|
|
path = null;
|
|
}
|
|
|
|
public void Execute()
|
|
{
|
|
//path = string.IsNullOrEmpty(path) ? Environment.CurrentDirectory : path.Replace(@"/", @"\");
|
|
var path = Environment.ExpandEnvironmentVariables(this.path);
|
|
path = string.IsNullOrEmpty(path) ? Environment.CurrentDirectory : System.IO.Path.Combine(Environment.CurrentDirectory, path);
|
|
BIT4Log.Log<OpenPath>($"正在打开文件夹:{path}");
|
|
try
|
|
{
|
|
var process = Process.Start("explorer.exe", path);
|
|
SwitchToThisWindow(process.MainWindowHandle, true);
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
BIT4Log.LogException(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OpenAPP : IDisposable
|
|
{
|
|
public string path;
|
|
public string WorkingDirectory;
|
|
public void Dispose()
|
|
{
|
|
path = WorkingDirectory = null;
|
|
}
|
|
public void Execute()
|
|
{
|
|
if (File.Exists(path))
|
|
{
|
|
ProcessStartInfo startInfo = new(path)
|
|
{
|
|
UseShellExecute = true
|
|
};
|
|
if (string.IsNullOrEmpty(WorkingDirectory) is false)
|
|
{
|
|
startInfo.WorkingDirectory = WorkingDirectory;
|
|
}
|
|
var process = Process.Start(startInfo);
|
|
SwitchToThisWindow(process.MainWindowHandle, true);
|
|
}
|
|
}
|
|
}
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
|
|
public static string AppName { get; private set; } = nameof(BITApp);
|
|
private static CancellationTokenSource CancellationTokenSource = new();
|
|
public static CancellationToken CancellationToken => CancellationTokenSource.Token;
|
|
public static InitializationState State;
|
|
public static Assembly[] Assemblies;
|
|
public static AppSettings Settings { get; protected set; }
|
|
private static DateTime InitialTime { get; set; }=DateTime.Now;
|
|
public static async UniTask Start(string appName = nameof(BITApp),AppSettings settings=default)
|
|
{
|
|
Time.TimeAsDouble = 0;
|
|
Time.DeltaTime = 1 / 60f;
|
|
|
|
SynchronizationContext = (SynchronizationContext, SynchronizationContext.Current) switch
|
|
{
|
|
(null, not null) => SynchronizationContext.Current,
|
|
_ => SynchronizationContext
|
|
};
|
|
|
|
if (SynchronizationContext is null)
|
|
{
|
|
BIT4Log.Warning<BITApp>("未找到主线程上下文,等待主线程将不可用");
|
|
}
|
|
|
|
Settings = settings??new AppSettings();
|
|
CancellationTokenSource = new CancellationTokenSource();
|
|
AppName = appName;
|
|
InitialTime = DateTime.Now;
|
|
await Init();
|
|
}
|
|
private static async Task Init()
|
|
{
|
|
try
|
|
{
|
|
if (State is not InitializationState.None)
|
|
{
|
|
BIT4Log.Warning("警告:上次启动可能未正确退出");
|
|
return;
|
|
}
|
|
//加载app-settings.json
|
|
var appSettingsPath = Path.Combine(Environment.CurrentDirectory, "appsettings.json");
|
|
if (PathHelper.TryGetText(appSettingsPath,out var json))
|
|
{
|
|
DataParser.Set(json);
|
|
BIT4Log.Log<BITApp>("已加载全局appsettings");
|
|
}
|
|
//内部反射初始化
|
|
await UniTask.SwitchToThreadPool();
|
|
Stopwatch stopwatch = new();
|
|
stopwatch.Start();
|
|
Stopwatch reflectionHelperWatch = new();
|
|
reflectionHelperWatch.Start();
|
|
await ReflectionHelper.Init();
|
|
reflectionHelperWatch.Stop();
|
|
|
|
Stopwatch commandWatch = new();
|
|
await BITCommands.InitializeAsync();
|
|
commandWatch.Stop();
|
|
|
|
Stopwatch binaryWatch = new();
|
|
await BITBinary.Start();
|
|
binaryWatch.Stop();
|
|
|
|
stopwatch.Stop();
|
|
State = InitializationState.Initialized;
|
|
BIT4Log.Log<BITApp>($"已完成初始化,耗时:{stopwatch.ElapsedMilliseconds}ms");
|
|
BIT4Log.Log<BITApp>($"反射初始化耗时:{reflectionHelperWatch.ElapsedMilliseconds}ms");
|
|
BIT4Log.Log<BITApp>($"初始化二进制序列化耗时:{binaryWatch.ElapsedMilliseconds}ms");
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
BIT4Log.Warning<BITApp>($"{nameof(BITApp)}初始化错误:");
|
|
BIT4Log.LogException(e);
|
|
}
|
|
#if NET5_0_OR_GREATER
|
|
ServiceProvider = ServiceCollection.BuildServiceProvider();
|
|
#endif
|
|
}
|
|
public static void Stop()
|
|
{
|
|
var runTime = DateTime.Now - InitialTime;
|
|
|
|
BIT4Log.Log<BITApp>($"正在停止{nameof(BITApp)}");
|
|
CancellationTokenSource.Cancel();
|
|
State = InitializationState.None;
|
|
|
|
BITCommands.Dispose();
|
|
|
|
BIT4Log.Log<BITApp>($"已停止{nameof(BITApp)}");
|
|
BIT4Log.Log<BITApp>($"已运行时间:{runTime.ToString("hh\\时mm\\分ss")}");
|
|
BIT4Log.Log<BITApp>("Exit Code:0");
|
|
|
|
}
|
|
public static void Run(string path, string WorkingDirectory = "")
|
|
{
|
|
using var open = new OpenAPP() { path = path, WorkingDirectory = WorkingDirectory };
|
|
open.Execute();
|
|
}
|
|
public static void Open(string path)
|
|
{
|
|
using var open = new OpenPath() { path = path };
|
|
open.Execute();
|
|
}
|
|
}
|
|
}
|