Skip to content

Commit

Permalink
add EnableMultiInstances
Browse files Browse the repository at this point in the history
  • Loading branch information
MikiraSora committed Jan 3, 2024
1 parent 618d0c2 commit da1f36a
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 2 deletions.
3 changes: 3 additions & 0 deletions OngekiFumenEditor/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
<setting name="DisableShowSplashScreenAfterBoot" serializeAs="String">
<value>False</value>
</setting>
<setting name="EnableMultiInstances" serializeAs="String">
<value>False</value>
</setting>
</OngekiFumenEditor.Properties.ProgramSetting>
<OngekiFumenEditor.Properties.LogSetting>
<setting name="LogFileDirPath" serializeAs="String">
Expand Down
13 changes: 11 additions & 2 deletions OngekiFumenEditor/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
using System;
using OngekiFumenEditor.Utils;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Windows;

namespace OngekiFumenEditor
Expand All @@ -12,10 +17,14 @@ namespace OngekiFumenEditor
/// </summary>
public partial class App : Application
{
static App()
{
IPCHelper.Init();
}

public App()
{
AppDomain.CurrentDomain.AssemblyResolve += OnSatelliteAssemblyResolve;

// 设置工作目录为执行文件所在的目录
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
}
Expand Down
40 changes: 40 additions & 0 deletions OngekiFumenEditor/AppBootstrapper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Caliburn.Micro;
using ControlzEx.Standard;
using Gemini.Framework.Services;
using Gemini.Modules.Output;
using MahApps.Metro.Controls.Dialogs;
Expand All @@ -21,18 +22,21 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace OngekiFumenEditor
{
Expand Down Expand Up @@ -168,6 +172,7 @@ protected async override void OnStartup(object sender, StartupEventArgs e)
base.OnStartup(sender, e);
InitExceptionCatcher();
LogBaseInfos();
InitIPC();

if (CheckIfAdminPermission())
{
Expand Down Expand Up @@ -213,6 +218,39 @@ protected async override void OnStartup(object sender, StartupEventArgs e)
IoC.Get<IWindowManager>().ShowWindowAsync(IoC.Get<ISplashScreenWindow>());

Check warning on line 218 in OngekiFumenEditor/AppBootstrapper.cs

View workflow job for this annotation

GitHub Actions / build

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
}

private void InitIPC()
{
if (ProgramSetting.Default.EnableMultiInstances)
return;
ipcThread = new AbortableThread(async (cancelToken) =>
{
while (!cancelToken.IsCancellationRequested)
{
try
{
var line = IPCHelper.ReadLineAsync(cancelToken)?.Trim();
if (string.IsNullOrWhiteSpace(line))
continue;
Log.LogDebug($"Recv line by IPC:{line}");
if (line.StartsWith("CMD:"))
{
var args = JsonSerializer.Deserialize<IPCHelper.ArgsWrapper>(line[4..]).Args;
await Application.Current.Dispatcher.InvokeAsync(() => IoC.Get<IProgramArgProcessManager>().ProcessArgs(args));
}
}
catch (Exception e)
{
Log.LogWarn($"Recv line by IPC throw exception:{e.Message}");
}
}
})
{
Name = "OngekiFumenEditorIPCThread",
IsBackground = true,
};
ipcThread.Start();
}

private async void MainWindow_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
Expand All @@ -232,6 +270,7 @@ private async void MainWindow_Drop(object sender, DragEventArgs e)
}

private bool exceptionHandling = false;
private AbortableThread ipcThread;

private void InitExceptionCatcher()
{
Expand Down Expand Up @@ -285,6 +324,7 @@ void exceptionDump(Exception e, int level = 0)

protected override async void OnExit(object sender, EventArgs e)
{
ipcThread?.Abort();
IoC.Get<IAudioManager>().Dispose();
await IoC.Get<ISchedulerManager>().Term();
FileLogOutput.WriteLog("\n----------CLOSE FILE LOG OUTPUT----------");

Check warning on line 330 in OngekiFumenEditor/AppBootstrapper.cs

View workflow job for this annotation

GitHub Actions / build

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
Margin="10,10,10,10"
Content="{markup:Translate [ProcessProriotyUpgrade]}"
IsChecked="{Binding Setting.UpgradeProcessPriority}" />
<CheckBox
Margin="10,0,10,10"
Content="{markup:Translate [EnableMultiInstances]}"
IsChecked="{Binding Setting.EnableMultiInstances}" />
</StackPanel>
</GroupBox>
<GroupBox Margin="5" Header="{markup:Translate [CrashDumpFile]}">
Expand Down
12 changes: 12 additions & 0 deletions OngekiFumenEditor/Properties/ProgramSetting.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions OngekiFumenEditor/Properties/ProgramSetting.settings
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@
<Setting Name="DisableShowSplashScreenAfterBoot" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="EnableMultiInstances" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>
9 changes: 9 additions & 0 deletions OngekiFumenEditor/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions OngekiFumenEditor/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,9 @@
<data name="EnableLoopPlayTiming" xml:space="preserve">
<value>Enable the metronome (only in Design Mode)</value>
</data>
<data name="EnableMultiInstances" xml:space="preserve">
<value>Allow multiple program instances to run</value>
</data>
<data name="EnableNotifyUserByDialog" xml:space="preserve">
<value>Enable display dialog for notifications</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions OngekiFumenEditor/Properties/Resources.zh-Hans.resx
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,9 @@
<data name="EnableLoopPlayTiming" xml:space="preserve">
<value>打开节拍器(仅编辑模式)</value>
</data>
<data name="EnableMultiInstances" xml:space="preserve">
<value>允许同时运行多个程序实例</value>
</data>
<data name="EnableNotifyUserByDialog" xml:space="preserve">
<value>是否显示对话框通知用户</value>
</data>
Expand Down
87 changes: 87 additions & 0 deletions OngekiFumenEditor/Utils/IPCHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using ControlzEx.Standard;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.IO.Pipes;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace OngekiFumenEditor.Utils
{
internal static class IPCHelper
{
const int FileSize = 10240;
private static MemoryMappedFile mmf;
private static bool enableMultiProc;

internal class ArgsWrapper
{
public string[] Args { get; set; }
}

static IPCHelper()
{
enableMultiProc = Properties.ProgramSetting.Default.EnableMultiInstances;
}

public static void Init()
{
if (enableMultiProc)
return;

mmf = MemoryMappedFile.CreateOrOpen("OngekiFumenEditor_MMF", FileSize, MemoryMappedFileAccess.ReadWrite);
using var accessor = mmf.CreateViewAccessor(0, FileSize);

var pid = accessor.ReadInt32(0);
if (pid != 0)
{
var process = Process.GetProcessById(pid);
if (process is not null)
{
//send to host
var r = "CMD:" + JsonSerializer.Serialize(new ArgsWrapper() { Args = Environment.GetCommandLineArgs().Skip(1).ToArray() });

var buffer = Encoding.UTF8.GetBytes(r);
accessor.WriteArray(sizeof(int) * 2, buffer, 0, Math.Min(buffer.Length, FileSize - sizeof(int) * 2));
accessor.Write(sizeof(int), buffer.Length);
accessor.Flush();

Environment.Exit(0);
return;
}
}

accessor.Write(0, Process.GetCurrentProcess().Id);
}

public static string ReadLineAsync(CancellationToken cancellation)
{
if (enableMultiProc)
return string.Empty;

using var accessor = mmf.CreateViewAccessor(0, FileSize);

while (!cancellation.IsCancellationRequested)
{
var size = accessor.ReadInt32(sizeof(int));
if (size > 0)
{
var bytes = new byte[size];
accessor.ReadArray(sizeof(int) * 2, bytes, 0, size);
accessor.Write(sizeof(int), 0);

return Encoding.UTF8.GetString(bytes);
}
}

return string.Empty;
}
}
}

0 comments on commit da1f36a

Please sign in to comment.