Dialogs now remember last-used folders for source, destination, logo, and settings files by storing these paths in a user preferences file under LocalApplicationData. Preferences are saved on form close, reducing unnecessary writes. SettingsService now uses a temporary ParametriSetup for settings files to avoid polluting user preferences. Error handling ensures preference save failures do not disrupt the user. This separation improves user experience and keeps user preferences distinct from project settings.
149 lines
No EOL
5.3 KiB
C#
149 lines
No EOL
5.3 KiB
C#
using System.Runtime.InteropServices;
|
|
using ImageCatalog;
|
|
using ImageCatalog_2.Services;
|
|
using MaddoShared;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using AutoMapper;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Logging.Console;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace ImageCatalog_2;
|
|
|
|
static class Program
|
|
{
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool AllocConsole();
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr GetStdHandle(int nStdHandle);
|
|
|
|
private const int STD_OUTPUT_HANDLE = -11;
|
|
private const int STD_ERROR_HANDLE = -12;
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool SetStdHandle(int nStdHandle, IntPtr handle);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr GetConsoleWindow();
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool AttachConsole(int dwProcessId);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr CreateFile(
|
|
string lpFileName,
|
|
uint dwDesiredAccess,
|
|
uint dwShareMode,
|
|
IntPtr lpSecurityAttributes,
|
|
uint dwCreationDisposition,
|
|
uint dwFlagsAndAttributes,
|
|
IntPtr hTemplateFile);
|
|
|
|
private const uint GENERIC_WRITE = 0x40000000;
|
|
private const uint OPEN_EXISTING = 3;
|
|
|
|
private static void RedirectConsoleOutput()
|
|
{
|
|
var stdOutHandle = CreateFile("CONOUT$", GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
|
|
var safeFileHandle = new Microsoft.Win32.SafeHandles.SafeFileHandle(stdOutHandle, true);
|
|
var fileStream = new FileStream(safeFileHandle, FileAccess.Write);
|
|
var standardOutput = new StreamWriter(fileStream) { AutoFlush = true };
|
|
Console.SetOut(standardOutput);
|
|
Console.SetError(standardOutput);
|
|
}
|
|
|
|
public static IServiceProvider ServiceProvider { get; private set; }
|
|
[STAThread]
|
|
static void Main()
|
|
{
|
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
|
Application.EnableVisualStyles();
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
AllocConsole();
|
|
RedirectConsoleOutput();
|
|
|
|
var serviceCollection = new ServiceCollection();
|
|
ConfigureServices(serviceCollection);
|
|
|
|
ServiceProvider = serviceCollection.BuildServiceProvider();
|
|
|
|
var mainForm = ServiceProvider.GetRequiredService<MainForm>();
|
|
//var mainViewModel = ServiceProvider.GetRequiredService<DataModel>();
|
|
|
|
//mainForm.Model = mainViewModel;
|
|
|
|
Application.Run(mainForm);
|
|
}
|
|
|
|
private static void ConfigureServices(ServiceCollection services)
|
|
{
|
|
// Register AutoMapper (new AddAutoMapper overload — provide config and marker types)
|
|
services.AddAutoMapper(cfg => { }, typeof(Program));
|
|
|
|
// Register your services here
|
|
services.AddTransient<ITestService, TestService>();
|
|
services.AddTransient<ISettingsService, SettingsService>();
|
|
|
|
services.AddTransient<DataModel>();
|
|
|
|
services.AddTransient<ImageCreationStuff>();
|
|
services.AddTransient<ImageCreatorSharp>();
|
|
|
|
// Register a ParametriSetup singleton that persists user preferences in LocalApplicationData
|
|
var userPrefsPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
|
"ImageCatalog", "userprefs.xml");
|
|
services.AddSingleton(new ParametriSetup(userPrefsPath));
|
|
services.AddSingleton<PicSettings>();
|
|
|
|
// Register your forms
|
|
services.AddTransient<MainForm>();
|
|
|
|
services.AddLogging(configure =>
|
|
{
|
|
configure.AddCustomFormatter();
|
|
configure.AddConsole();
|
|
configure.SetMinimumLevel(LogLevel.Debug);
|
|
});
|
|
}
|
|
}
|
|
|
|
public static class ConsoleLoggerExtensions
|
|
{
|
|
public static ILoggingBuilder AddCustomFormatter(
|
|
this ILoggingBuilder builder) =>
|
|
builder.AddConsole(options => options.FormatterName = nameof(CustomLoggingFormatter))
|
|
.AddConsoleFormatter<CustomLoggingFormatter, ConsoleFormatterOptions>();
|
|
}
|
|
public sealed class CustomLoggingFormatter : ConsoleFormatter, IDisposable
|
|
{
|
|
private readonly IDisposable _optionsReloadToken;
|
|
private ConsoleFormatterOptions _formatterOptions;
|
|
public CustomLoggingFormatter(IOptionsMonitor<ConsoleFormatterOptions> options)
|
|
// Case insensitive
|
|
: base(nameof(CustomLoggingFormatter)) =>
|
|
(_optionsReloadToken, _formatterOptions) =
|
|
(options.OnChange(ReloadLoggerOptions), options.CurrentValue);
|
|
private void ReloadLoggerOptions(ConsoleFormatterOptions options) =>
|
|
_formatterOptions = options;
|
|
|
|
public override void Write<TState>(
|
|
in LogEntry<TState> logEntry,
|
|
IExternalScopeProvider scopeProvider,
|
|
TextWriter textWriter)
|
|
{
|
|
string? message =
|
|
logEntry.Formatter?.Invoke(
|
|
logEntry.State, logEntry.Exception);
|
|
|
|
if (message is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
textWriter.WriteLine($"{message}");
|
|
}
|
|
public void Dispose() => _optionsReloadToken?.Dispose();
|
|
} |