Skip to content

Commit

Permalink
Only allow a single instance to run
Browse files Browse the repository at this point in the history
crtcpl and ejectcd now use a mutex to allow only a single instance to run at once.

for crtcpl this is required since it grabs the serial port for exclusive use and multiple instances of ejectcd make no sense...
  • Loading branch information
shuuryou committed May 8, 2020
1 parent 13eaad7 commit 610480f
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 66 deletions.
7 changes: 7 additions & 0 deletions crtcpl/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ internal static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern IntPtr SetActiveWindow(IntPtr hWnd);


[DllImport("user32.dll")]
internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
#endif
}
99 changes: 73 additions & 26 deletions crtcpl/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace crtcpl
Expand All @@ -10,48 +13,92 @@ public static class Program
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

bool result;
Mutex m = new Mutex(true, "crtcpl", out result);

if (!result)
{
try
{
#if !MONO
// Best effort switch to active instance
Process[] procs = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Application.ExecutablePath));
foreach (Process p in procs)
{
if (p.Id == Process.GetCurrentProcess().Id)
continue;

if (p.MainWindowHandle == IntPtr.Zero)
continue;

const int SW_SHOW = 5;

NativeMethods.SetForegroundWindow(p.MainWindowHandle);
NativeMethods.ShowWindow(p.MainWindowHandle, SW_SHOW);

break;
}
#else
// Sorry, don't know what to do.
MessageBox.Show(StringRes.StringRes.AlreadyRunning, StringRes.StringRes.AlreadyRunningTitle,
MessageBoxButtons.OK, MessageBoxIcon.Error);
#endif
}
catch (Exception)
{
#if DEBUG
System.Threading.Thread.CurrentThread.CurrentCulture =
System.Threading.Thread.CurrentThread.CurrentUICulture =
new System.Globalization.CultureInfo("de-de");
throw;
#endif
if (Settings.Default.NeedsUpgrade)
{
Settings.Default.Upgrade();
Settings.Default.NeedsUpgrade = false;
Settings.Default.Save();
}

return;
}

if (!string.IsNullOrWhiteSpace(Settings.Default.SerialPort))
try
{
bool bad = false;
try
if (Settings.Default.NeedsUpgrade)
{
UCCom.Open(Settings.Default.SerialPort);
byte[] ret = UCCom.SendCommand(1, 0, 0);
Settings.Default.Upgrade();
Settings.Default.NeedsUpgrade = false;
Settings.Default.Save();
}

if (ret == null || ret.Length != 1 || ret[0] != SUPPORTED_EEPROM_VERSION)
if (!string.IsNullOrWhiteSpace(Settings.Default.SerialPort))
{
bool bad = false;
try
{
UCCom.Open(Settings.Default.SerialPort);
byte[] ret = UCCom.SendCommand(1, 0, 0);

if (ret == null || ret.Length != 1 || ret[0] != SUPPORTED_EEPROM_VERSION)
{
bad = true;
}
}
catch (UCComException)
{
bad = true;
}
}
catch (UCComException)
{
bad = true;

if (bad)
{
Settings.Default.SerialPort = null;
}
}

if (bad)
using (AppletForm a = new AppletForm())
{
Settings.Default.SerialPort = null;
Application.Run(a);
}
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

using (AppletForm a = new AppletForm())
finally
{
Application.Run(a);
m.ReleaseMutex();
m.Dispose();
}
}
}
Expand Down
24 changes: 21 additions & 3 deletions crtcpl/StringRes/StringRes.Designer.cs

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

6 changes: 6 additions & 0 deletions crtcpl/StringRes/StringRes.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AlreadyRunning" xml:space="preserve">
<value>Es wird bereits eine weitere Instanz dieses Programms ausgeführt.</value>
</data>
<data name="AlreadyRunningTitle" xml:space="preserve">
<value>Bildschirmeinstellungen</value>
</data>
<data name="CantApplyChanges" xml:space="preserve">
<value>Bei der Anweisung an den IVAD-Controller, alle Änderungen dauerhaft zu machen, ist ein Fehler aufgetreten. {0}</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions crtcpl/StringRes/StringRes.fr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AlreadyRunning" xml:space="preserve">
<value>Une autre instance de ce programme est déjà en cours d'exécution</value>
</data>
<data name="AlreadyRunningTitle" xml:space="preserve">
<value>Paramètres de l’écran</value>
</data>
<data name="CantApplyChanges" xml:space="preserve">
<value>Une erreur s'est produite alors que le contrôleur IVAD avait reçu l'instruction de rendre permanentes toutes les modifications. {0}</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions crtcpl/StringRes/StringRes.ja.resx
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,10 @@
<data name="UCComUnauthorizedAccess" xml:space="preserve">
<value>COMポートへのアクセスが拒否されました。 別のプログラムが指定されたCOMポートを既に開いている可能性があります。</value>
</data>
<data name="AlreadyRunning" xml:space="preserve">
<value>このプログラムの他のインスタンスが既に実行されています。</value>
</data>
<data name="AlreadyRunningTitle" xml:space="preserve">
<value>画面設定</value>
</data>
</root>
6 changes: 6 additions & 0 deletions crtcpl/StringRes/StringRes.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AlreadyRunning" xml:space="preserve">
<value>Another Instance of this program is already running</value>
</data>
<data name="AlreadyRunningTitle" xml:space="preserve">
<value>Screen Settings</value>
</data>
<data name="CantApplyChanges" xml:space="preserve">
<value>An error occurred while instructing the IVAD controller to make all changes permanent. {0}</value>
</data>
Expand Down
93 changes: 56 additions & 37 deletions ejectcd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,87 @@
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace ejectcd
{
public static class Program
{
public static int Main(string[] args)
{
DriveInfo[] drives;
bool result;
Mutex m = new Mutex(true, "ejectcd", out result);

try
{
drives = DriveInfo.GetDrives();
}
catch (IOException e)
if (!result)
{
Console.Error.WriteLine(e.Message);
return 1;
}
catch (UnauthorizedAccessException e)
{
Console.Error.WriteLine(e.Message);
Console.Error.Write("Another instance is already running.");
return 1;
}

foreach (DriveInfo drive in drives)
try
{
if (drive.DriveType != DriveType.CDRom)
continue;

Console.WriteLine("Eject CD-ROM drive {0}.", drive.Name);

IntPtr hDrive = new IntPtr(INVALID_HANDLE_VALUE);
DriveInfo[] drives;

try
{
// Open the device
hDrive = CreateFile(@"\\.\" + drive.Name[0] + ':', FileAccess.Read, FileShare.ReadWrite | FileShare.Delete,
IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

if ((int)hDrive == INVALID_HANDLE_VALUE) { throw new Win32Exception(); }

// Try and eject
int dummy = 0;
bool ejected = DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0,
IntPtr.Zero, 0, ref dummy, IntPtr.Zero);

if (!ejected) { throw new Win32Exception(); }

drives = DriveInfo.GetDrives();
}
catch (IOException e)
{
Console.Error.WriteLine(e.Message);
return 1;
}
catch (Win32Exception e)
catch (UnauthorizedAccessException e)
{
Console.Error.WriteLine(e.Message);
return 1;
}
finally

foreach (DriveInfo drive in drives)
{
if (hDrive.ToInt32() != INVALID_HANDLE_VALUE)
CloseHandle(hDrive);
if (drive.DriveType != DriveType.CDRom)
continue;

Console.WriteLine("Eject CD-ROM drive {0}.", drive.Name);

IntPtr hDrive = new IntPtr(INVALID_HANDLE_VALUE);

try
{
// Open the device
hDrive = CreateFile(@"\\.\" + drive.Name[0] + ':', FileAccess.Read, FileShare.ReadWrite | FileShare.Delete,
IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

if ((int)hDrive == INVALID_HANDLE_VALUE) { throw new Win32Exception(); }

// Try and eject
int dummy = 0;
bool ejected = DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0,
IntPtr.Zero, 0, ref dummy, IntPtr.Zero);

if (!ejected) { throw new Win32Exception(); }

}
catch (Win32Exception e)
{
Console.Error.WriteLine(e.Message);
return 1;
}
finally
{
if (hDrive.ToInt32() != INVALID_HANDLE_VALUE)
CloseHandle(hDrive);
}
}

Console.WriteLine("Done.");
}
finally
{
m.ReleaseMutex();
m.Dispose();
}

Console.WriteLine("Done.");
return 0;
}

Expand Down

0 comments on commit 610480f

Please sign in to comment.