diff --git a/framework-dotnet/src/lib/MBS.Core/Application.cs b/framework-dotnet/src/lib/MBS.Core/Application.cs index 90d4aa2..024c65c 100644 --- a/framework-dotnet/src/lib/MBS.Core/Application.cs +++ b/framework-dotnet/src/lib/MBS.Core/Application.cs @@ -4,11 +4,27 @@ public class Application { public static Application? Instance { get; private set; } + public CommandLine CommandLine { get; } = new CommandLine(); + protected virtual void OnStartup(EventArgs e) + { + } + protected virtual void OnActivated(ApplicationActivatedEventArgs e) + { + } protected virtual int StartInternal() { - return 0; + OnStartup(EventArgs.Empty); + + CommandLine cline = new CommandLine(); + cline.Arguments = System.Environment.GetCommandLineArgs(); + + ApplicationActivatedEventArgs e = new ApplicationActivatedEventArgs(true, ApplicationActivationType.CommandLineLaunch, cline); + OnActivated(e); + + return e.ExitCode; } + public int Start() { Instance = this; diff --git a/framework-dotnet/src/lib/MBS.Core/ApplicationActivatedEvent.cs b/framework-dotnet/src/lib/MBS.Core/ApplicationActivatedEvent.cs new file mode 100644 index 0000000..5d14e03 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/ApplicationActivatedEvent.cs @@ -0,0 +1,43 @@ +// +// ApplicationActivatedEvent.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 20192024 Michael Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; + +namespace MBS.Core +{ + public class ApplicationActivatedEventArgs : EventArgs + { + public bool Success { get; set; } = true; + + public bool FirstRun { get; } = true; + public CommandLine CommandLine { get; } = null; + public int ExitCode { get; set; } = 0; + public ApplicationActivationType ActivationType { get; } = ApplicationActivationType.Launch; + + public ApplicationActivatedEventArgs(bool firstRun, ApplicationActivationType activationType, CommandLine commandLine) + { + FirstRun = firstRun; + ActivationType = activationType; + CommandLine = commandLine; + } + } + public delegate void ApplicationActivatedEventHandler(object sender, ApplicationActivatedEventArgs e); +} diff --git a/framework-dotnet/src/lib/MBS.Core/ApplicationActivationType.cs b/framework-dotnet/src/lib/MBS.Core/ApplicationActivationType.cs new file mode 100644 index 0000000..d2aea16 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/ApplicationActivationType.cs @@ -0,0 +1,275 @@ +// +// ActivationType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2022 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace MBS.Core; + +/// +/// Specifies the type of activation when the application is started +/// from layout on a layout-aware operating system. +/// +/// +/// +/// Values are mutually exclusive and cannot be combined. Each one +/// relates to a different type of activation, and an app instance can +/// be activated in only one way at a time. +/// +/// +/// The activation types are based on those supported by Windows 11, +/// however the enum values are operating system agnostic. Translation +/// (e.g. by an Engine) must be done before calls to operating system +/// specific methods are made. +/// +/// +/// On non-layout-aware operating systems, such as Linux, a wrapper +/// executable (bootstrapper) must be used to invoke the app activation +/// with the desired . +/// +/// +public enum ApplicationActivationType +{ + /// + /// The activation type was not specified. + /// + Unspecified = -1, + + /// + /// The user wants to manage appointments that are provided by the + /// app. + /// + AppointmentsProvider, + /// + /// The app was activated as a barcode scanner provider. + /// + BarcodeScannerProvider, + /// + /// The user wants to save a file for which the app provides content + /// management. + /// + CachedFileUpdater, + /// + /// The app captures photos or video from an attached camera. + /// + CameraSettings, + /// + /// The app was launched from the command line. + /// + CommandLineLaunch, + /// + /// Reserved for system use. Introduced in Windows 10, version 1507 + /// (10.0.10240). + /// + ComponentUI, + /// + /// The user wants to handle calls or messages for the phone number + /// of a contact that is provided by the app. + /// + Contact, + /// + /// The app was launched from the My People UI. Note: introduced in + /// Windows 10, version 1703 (10.0.15063), but not used. Now used + /// starting with Windows 10, version 1709 (10.0.16299). + /// + ContactPanel, + /// + /// The user wants to pick contacts. + /// + ContactPicker, + /// + /// The app handles AutoPlay. + /// + Device, + /// + /// This app was activated as a result of pairing a device. + /// + DevicePairing, + /// + /// This app was launched by another app on a different device by + /// using the DIAL protocol.Introduced in Windows 10, version 1507 + /// (10.0.10240). + /// + DialReceiver, + /// + /// An app launched a file whose file type this app is registered to + /// handle. + /// + File, + /// + /// The user wants to pick files that are provided by the app. + /// + FileOpenPicker, + /// + /// Reserved for system use. Introduced in Windows 10, version 1607 + /// (10.0.14393). + /// + FilePickerExperience, + /// + /// The user wants to save a file and selected the app as the + /// location. + /// + FileSavePicker, + /// + /// The app was activated because it was launched by the OS due to a + /// game's request for Xbox-specific UI. Introduced in Windows 10, + /// version 1703 (10.0.15063). + /// + GameUIProvider, + /// + /// The user launched the app or tapped a content tile. + /// + Launch, + /// + /// The app was activated as the lock screen. Introduced in Windows + /// 10, version 1507 (10.0.10240). + /// + LockScreen, + /// + /// Windows Store only. The app launches a call from the lock screen. + /// If the user wants to accept the call, the app displays its call + /// UI directly on the lock screen without requiring the user to + /// unlock. A lock-screen call is a special type of launch + /// activation. + /// + LockScreenCall, + /// + /// Reserved for system use. Introduced in Windows 10, version 1703 + /// (10.0.15063). + /// + LockScreenComponent, + /// + /// The app was activated in response to a phone call. + /// + PhoneCallActivation, + /// + /// Windows Phone only. The app was activated after the completion of + /// a picker. + /// + PickerReturned, + /// + /// Windows Phone only. The app was activated after the app was + /// suspended for a file picker operation. + /// + PickFileContinuation, + /// + /// Windows Phone only. The app was activated after the app was + /// suspended for a folder picker operation. + /// + PickFolderContinuation, + /// + /// Windows Phone only. The app was activated after the app was + /// suspended for a file save picker operation. + /// + PickSaveFileContinuation, + /// + /// This app was launched by another app to provide a customized + /// printing experience for a 3D printer. Introduced in Windows 10, + /// version 1507 (10.0.10240). + /// + Print3DWorkflow, + /// + /// The app was activated as a print workflow job UI extension. + /// + PrintSupportJobUI, + /// + /// The app was activated as a print support settings UI extension. + /// + PrintSupportSettingsUI, + /// + /// The app handles print tasks. + /// + PrintTaskSettings, + /// + /// The app was activated because the user is printing to a printer + /// that has a Print Workflow Application associated with it which + /// has requested user input. + /// + PrintWorkflowForegroundTask, + /// + /// An app launched a URI whose scheme name this app is registered to + /// handle. + /// + Protocol, + /// + /// The app was launched by another app with the expectation that it + /// will return a result back to the caller. Introduced in Windows + /// 10, version 1507 (10.0.10240). + /// + ProtocolForResults, + /// + /// Windows Store only. The user launched the restricted app. + /// + RestrictedLaunch, + /// + /// The user wants to search with the app. + /// + Search, + /// + /// The app is activated as a target for share operations. + /// + ShareTarget, + /// + /// The app was activated because the app is specified to launch at + /// system startup or user log-in. Introduced in Windows 10, version + /// 1703 (10.0.15063). + /// + StartupTask, + /// + /// The app was activated when a user tapped on the body of a toast + /// notification or performed an action inside a toast notification. + /// Introduced in Windows 10, version 1507 (10.0.10240). + /// + ToastNotification, + /// + /// The app was launched to handle the user interface for account + /// management. In circumstances where the system would have shown + /// the default system user interface, it instead has invoked your + /// app with the UserDataAccountProvider contract. The activation + /// payload contains information about the type of operation being + /// requested and all the information necessary to replicate the + /// system-provided user interface. This activation kind is limited + /// to 1st party apps. To use this field, you must add the + /// userDataAccountsProvider capability in your app's package + /// manifest. For more info see App capability declarations. + /// Introduced in Windows 10, version 1607 (10.0.14393). + /// + UserDataAccountsProvider, + /// + /// The app was activated as the result of a voice command. + /// + VoiceCommand, + /// + /// The app is a VPN foreground app that was activated by the plugin. + /// For more details, see VpnChannel.ActivateForeground. + /// + VpnForeground, + /// + /// The app was activated to perform a Wallet operation. + /// + WalletAction, + /// + /// The app was activated by a web account provider. + /// + WebAccountProvider, + /// + /// The app was activated after the app was suspended for a web + /// authentication broker operation. + /// + WebAuthenticationBrokerContinuation +} diff --git a/framework-dotnet/src/lib/MBS.Core/CommandLine.cs b/framework-dotnet/src/lib/MBS.Core/CommandLine.cs new file mode 100644 index 0000000..dbc6750 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandLine.cs @@ -0,0 +1,70 @@ +// +// CommandLine.cs +// +// Author: +// Mike Becker +// +// Copyright (c) 2019 Mike Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; + +namespace MBS.Core; + +public class CommandLine +{ + /// + /// Gets the original array of arguments. + /// + /// The arguments. + public string[] Arguments { get; internal set; } + + /// + /// Gets the list of file names passed on the command line. + /// + /// The file names. + public List FileNames { get; } = new List(); + + public CommandLineParser Parser { get; set; } = null; + + public string HelpTextPrefix { get; set; } = null; + public string HelpTextSuffix { get; set; } = null; + + public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection(); + public CommandLineCommand.CommandLineCommandCollection Commands { get; } = new CommandLineCommand.CommandLineCommandCollection(); + public CommandLineCommand Command { get; internal set; } = null; + public string ShortOptionPrefix { get; set; } = null; + public string LongOptionPrefix { get; set; } = null; + + public CommandLine(string[] arguments = null) + { + string[] args = arguments; + if (args == null) + { + args = Environment.GetCommandLineArgs(); + } + string[] args2 = new string[args.Length - 1]; + Array.Copy(args, 1, args2, 0, args2.Length); + Arguments = args2; + + Options.Add(new CommandLineOption() { Abbreviation = 'A', Name = "activation-type", Description = "The type of activation for this app", Type = CommandLineOptionValueType.Single, Optional = true }); + Options.Add(new CommandLineOption() { Name = "help", Description = "Displays help", Type = CommandLineOptionValueType.None, Optional = true }); + } + + public override string ToString() + { + return String.Join(" ", Arguments); + } +} diff --git a/framework-dotnet/src/lib/MBS.Core/CommandLineCommand.cs b/framework-dotnet/src/lib/MBS.Core/CommandLineCommand.cs new file mode 100644 index 0000000..8f5ace3 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandLineCommand.cs @@ -0,0 +1,61 @@ +// +// CommandLineCommand.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2022 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using MBS.Core.Collections.Generic; + +namespace MBS.Core; + +public class CommandLineCommand +{ + public class CommandLineCommandCollection + : System.Collections.ObjectModel.Collection + { + public CommandLineCommand this[string name] + { + get + { + foreach (CommandLineCommand item in this) + { + if (item.Name == name) + return item; + } + return null; + } + } + } + + public string Name { get; set; } = null; + public string Description { get; set; } = null; + + public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection(); + + public Action ActivationDelegate { get; } = null; + + public CommandLineCommand(string command, CommandLineOption[] options = null, Action activationDelegate = null) + { + Name = command; + if (options != null) + { + Options.AddRange(options); + } + ActivationDelegate = activationDelegate; + } +} diff --git a/framework-dotnet/src/lib/MBS.Core/CommandLineOption.cs b/framework-dotnet/src/lib/MBS.Core/CommandLineOption.cs new file mode 100644 index 0000000..0581ed2 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandLineOption.cs @@ -0,0 +1,138 @@ +// +// CommandLineOption.cs +// +// Author: +// Mike Becker +// +// Copyright (c) 2019 Mike Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; + +namespace MBS.Core; + +public class CommandLineOption +{ + public class CommandLineOptionCollection + : System.Collections.ObjectModel.Collection + { + private Dictionary _byAbbreviation = new Dictionary(); + private Dictionary _byName = new Dictionary(); + + public bool Contains(char abbreviation) + { + return _byAbbreviation.ContainsKey(abbreviation); + } + public bool Contains(string name) + { + return _byName.ContainsKey(name); + } + + public CommandLineOption this[char abbreviation] + { + get + { + if (_byAbbreviation.ContainsKey(abbreviation)) + return _byAbbreviation[abbreviation]; + return null; + } + } + public CommandLineOption this[string name] + { + get + { + if (_byName.ContainsKey(name)) + return _byName[name]; + return null; + } + } + + protected override void ClearItems() + { + base.ClearItems(); + + _byName.Clear(); + _byAbbreviation.Clear(); + } + protected override void InsertItem(int index, CommandLineOption item) + { + base.InsertItem(index, item); + + if (item.Name != null) + _byName[item.Name] = item; + + if (item.Abbreviation != '\0') + _byAbbreviation[item.Abbreviation] = item; + } + + public CommandLineOption Add(string name, CommandLineOptionValueType type = CommandLineOptionValueType.None, object defaultValue = null, char abbreviation = '\0', string description = null) + { + return Add(name, abbreviation, defaultValue, type, description); + } + public CommandLineOption Add(string name, char abbreviation = '\0', object defaultValue = null, CommandLineOptionValueType type = CommandLineOptionValueType.None, string description = null) + { + CommandLineOption option = new CommandLineOption(); + option.Name = name; + option.Abbreviation = abbreviation; + option.DefaultValue = defaultValue; + option.Type = type; + option.Description = description; + + Add(option); + return option; + } + + protected override void RemoveItem(int index) + { + _byName.Remove(this[index].Name); + _byAbbreviation.Remove(this[index].Abbreviation); + + base.RemoveItem(index); + } + + public T GetValueOrDefault(string name, T defaultValue = default(T)) + { + if (_byName.ContainsKey(name)) + { + return (T) _byName[name].Value; + } + return defaultValue; + } + } + + public string Name { get; set; } = null; + public char Abbreviation { get; set; } = '\0'; + + public object DefaultValue { get; set; } = null; + + /// + /// Gets or sets a value indicating whether this is optional. + /// + /// true if optional; otherwise, false. + public bool Optional { get; set; } = false; + + /// + /// The description displayed in the help text. + /// + /// The description. + public string Description { get; set; } = null; + public object Value { get; set; } = null; + + /// + /// Gets or sets a value indicating whether this expects a value to be passed in after this option. + /// + /// true if a value is expected to be passed in after this option; otherwise, false. + public CommandLineOptionValueType Type { get; set; } = CommandLineOptionValueType.None; +} diff --git a/framework-dotnet/src/lib/MBS.Core/CommandLineOptionValueType.cs b/framework-dotnet/src/lib/MBS.Core/CommandLineOptionValueType.cs new file mode 100644 index 0000000..1488c83 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandLineOptionValueType.cs @@ -0,0 +1,38 @@ +// +// CommandLineOptionValueType.cs +// +// Author: +// Mike Becker +// +// Copyright (c) 2019 Mike Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace MBS.Core; + +public enum CommandLineOptionValueType +{ + /// + /// The option accepts no values. + /// + None = 0, + /// + /// The option accepts a single value. + /// + Single = 1, + /// + /// The option accepts multiple values. + /// + Multiple = 2 +} diff --git a/framework-dotnet/src/lib/MBS.Core/CommandLineParser.cs b/framework-dotnet/src/lib/MBS.Core/CommandLineParser.cs new file mode 100644 index 0000000..fe6b2b0 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandLineParser.cs @@ -0,0 +1,38 @@ +// +// CommandLineParser.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2022 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace MBS.Core; + +public class CommandLineParser +{ + protected virtual void ParseInternal(string[] arguments) + { + string[] ary1 = Environment.GetCommandLineArgs(); + string[] ary2 = new string[ary1.Length - 1]; + + Array.Copy(ary1, 1, ary2, 0, ary1.Length - 1); + Application.Instance.CommandLine.Arguments = ary2; + } + public void Parse(string[] arguments) + { + ParseInternal(arguments); + } +} diff --git a/framework-dotnet/src/lib/MBS.Core/Interop/InteropServices.cs b/framework-dotnet/src/lib/MBS.Core/Interop/InteropServices.cs new file mode 100644 index 0000000..ab47053 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Interop/InteropServices.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace MBS.Core.Interop; + +public static class InteropServices +{ + + [StructLayout(LayoutKind.Sequential)] + private struct PtrToStringArrayStruct + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public IntPtr[] listOfStrings; + } + + public static string[] PtrToStringArray(IntPtr hptr, int size) + { + // eww.. gross. thanks https://stackoverflow.com/questions/1323797/marshaling-pointer-to-an-array-of-strings + PtrToStringArrayStruct hwss = (PtrToStringArrayStruct)Marshal.PtrToStructure(hptr, typeof(PtrToStringArrayStruct)); + string[] argv = new string[size]; + for (int i = 0; i < size; i++) + { + IntPtr hstr = hwss.listOfStrings[i]; + + string p = Marshal.PtrToStringAuto(hstr); + argv[i] = p; + } + return argv; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Orientation.cs b/framework-dotnet/src/lib/MBS.Core/Orientation.cs new file mode 100644 index 0000000..d7fa30b --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Orientation.cs @@ -0,0 +1,7 @@ +namespace MBS.Core; + +public enum Orientation +{ + Horizontal, + Vertical +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Reflection/Invoker.cs b/framework-dotnet/src/lib/MBS.Core/Reflection/Invoker.cs new file mode 100644 index 0000000..82a3a80 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Reflection/Invoker.cs @@ -0,0 +1,43 @@ +namespace MBS.Core.Reflection; + +public class Invoker +{ + public static void Invoke(object obj, string meth, params object[] parms) + { + if (obj == null) + { + Console.WriteLine("Invoker::Invoke: obj is null"); + return; + } + + Type t = obj.GetType(); + System.Reflection.MethodInfo mi = t.GetMethod(meth, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + if (mi != null) + { + mi.Invoke(obj, parms); + } + else + { + Console.WriteLine("Invoker::Invoke: instance method not found '" + meth + "' on '" + t.FullName + "'"); + } + } + public static void InvokeStatic(Type type, string meth, params object[] parms) + { + if (type == null) + { + Console.WriteLine("Invoker::InvokeStatic: type is null"); + return; + } + + Type t = type; + System.Reflection.MethodInfo mi = t.GetMethod(meth, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + if (mi != null) + { + mi.Invoke(null, parms); + } + else + { + Console.WriteLine("Invoker::InvokeStatic: static method not found '" + meth + "' on '" + t.FullName + "'"); + } + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Reflection/TypeLoader.cs b/framework-dotnet/src/lib/MBS.Core/Reflection/TypeLoader.cs index 45dc9ba..29e999e 100644 --- a/framework-dotnet/src/lib/MBS.Core/Reflection/TypeLoader.cs +++ b/framework-dotnet/src/lib/MBS.Core/Reflection/TypeLoader.cs @@ -76,7 +76,13 @@ public class TypeLoader List asmdirs = new List(); string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().Location); asmdirs.Add(dir); - asmdirs.Add(dir + System.IO.Path.DirectorySeparatorChar.ToString() + "plugins"); + + string[] subdirs = System.IO.Directory.GetDirectories(dir); + foreach (string subdir in subdirs) + { + asmdirs.Add(subdir); + } + // asmdirs.Add(dir + System.IO.Path.DirectorySeparatorChar.ToString() + "plugins"); if (searchPaths != null) { for (int i = 0; i < searchPaths.Length; i++) @@ -123,6 +129,33 @@ public class TypeLoader } private static Type[] mvarAvailableTypes = null; + public static T[] GetAvailableTypes(Assembly[] additionalAssemblies = null) where T : class + { + Type[] ts = null; + try + { + ts = GetAvailableTypes(new Type[] { typeof(T) }, additionalAssemblies); + } + catch (ReflectionTypeLoadException ex) + { + ts = ex.Types; + } + + List list = new List(); + foreach (Type t in ts) + { + if (t == null) + continue; + + if (t.IsAbstract) + continue; + + T obj = t.Assembly.CreateInstance(t.FullName) as T; + if (obj != null) + list.Add(obj); + } + return list.ToArray(); + } public static Type[] GetAvailableTypes(Type[] inheritsFrom = null, Assembly[] additionalAssemblies = null) { if (mvarAvailableTypes == null) diff --git a/framework-dotnet/src/lib/MBS.Desktop/DesktopApplication.cs b/framework-dotnet/src/lib/MBS.Desktop/DesktopApplication.cs deleted file mode 100644 index 1e0b72a..0000000 --- a/framework-dotnet/src/lib/MBS.Desktop/DesktopApplication.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace MBS.Desktop; - -public class DesktopApplication : MBS.Core.Application -{ - -} diff --git a/framework-dotnet/src/lib/MBS.Desktop/MBS.Desktop.csproj b/framework-dotnet/src/lib/MBS.Desktop/MBS.Desktop.csproj deleted file mode 100644 index 020ce4d..0000000 --- a/framework-dotnet/src/lib/MBS.Desktop/MBS.Desktop.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - net8.0 - enable - enable - - -