Added support for setting the number threads in the GUI + some improvements application configuration handling.
This commit is contained in:
parent
7359ce3673
commit
45829c4317
@ -55,6 +55,11 @@ The following settings can be adjusted in the `slunkcrypt-gui.exe.config` config
|
|||||||
- **`DisableBusyIndicator`:**
|
- **`DisableBusyIndicator`:**
|
||||||
If set to `true`, the “busy indicator” animation will be *disabled* on application startup — default value: `false`.
|
If set to `true`, the “busy indicator” animation will be *disabled* on application startup — default value: `false`.
|
||||||
|
|
||||||
|
- **`ThreadCount`:**
|
||||||
|
Specifies the number of worker threads to use — default value: `0` (i.e. detect the number of available processors and create one thread for each processor).
|
||||||
|
|
||||||
|
- **`KeepIncompleteFiles`:**
|
||||||
|
If set to `true`, incomplete or corrupted output files will *not* be deleted — default value: `false`.
|
||||||
|
|
||||||
Command-line Usage
|
Command-line Usage
|
||||||
==================
|
==================
|
||||||
|
@ -5,5 +5,7 @@
|
|||||||
</startup>
|
</startup>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="DisableBusyIndicator" value="false"/>
|
<add key="DisableBusyIndicator" value="false"/>
|
||||||
|
<add key="ThreadCount" value="0"/>
|
||||||
|
<add key="KeepIncompleteFiles" value="false"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -19,6 +19,17 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
{
|
{
|
||||||
public enum Mode { Encrypt, Decrypt }
|
public enum Mode { Encrypt, Decrypt }
|
||||||
|
|
||||||
|
public struct SlunkOptions
|
||||||
|
{
|
||||||
|
public SlunkOptions(bool keepIncompleteFiles, int threadCount)
|
||||||
|
{
|
||||||
|
this.keepIncompleteFiles = keepIncompleteFiles;
|
||||||
|
this.threadCount = threadCount;
|
||||||
|
}
|
||||||
|
public readonly bool keepIncompleteFiles;
|
||||||
|
public readonly int threadCount;
|
||||||
|
}
|
||||||
|
|
||||||
private const string COMMAND_ENCRYPT = "-e";
|
private const string COMMAND_ENCRYPT = "-e";
|
||||||
private const string COMMAND_DECRYPT = "-d";
|
private const string COMMAND_DECRYPT = "-d";
|
||||||
|
|
||||||
@ -39,12 +50,13 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
// Public methods
|
// Public methods
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
public async Task<int> ExecuteAsync(Mode mode, string inputFile, string outputFile, string password)
|
public async Task<int> ExecuteAsync(Mode mode, string inputFile, string outputFile, string password, SlunkOptions? options = null)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> environmentVariables = new Dictionary<string, string>();
|
Dictionary<string, string> environmentVariables = new Dictionary<string, string>();
|
||||||
environmentVariables.Add("SLUNK_PASSPHRASE", password);
|
environmentVariables.Add("SLUNK_PASSPHRASE", password);
|
||||||
string[] arguments = new string[] { GetCommandString(mode), inputFile, outputFile };
|
environmentVariables.Add("SLUNK_KEEP_INCOMPLETE", Convert.ToInt32(options.HasValue ? options.Value.keepIncompleteFiles : false).ToString());
|
||||||
return await ExecAsnyc(m_executableFile.Name, arguments, environmentVariables);
|
environmentVariables.Add("SLUNK_THREADS", Math.Max(0, Math.Min(32, options.HasValue ? options.Value.threadCount : 0)).ToString());
|
||||||
|
return await ExecAsnyc(m_executableFile.Name, new string[] { GetCommandLineModeString(mode), inputFile, outputFile }, environmentVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
@ -94,7 +106,7 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetCommandString(Mode mode)
|
private static string GetCommandLineModeString(Mode mode)
|
||||||
{
|
{
|
||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
|
@ -556,8 +556,11 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false;
|
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false;
|
||||||
if (!await processor(inputFile, outputFile, password))
|
if (!await processor(inputFile, outputFile, password))
|
||||||
{
|
{
|
||||||
|
if (!m_config.KeepIncompleteFiles)
|
||||||
|
{
|
||||||
|
PathUtils.TryRemoveFile(outputFile);
|
||||||
|
}
|
||||||
SetProgress(double.NaN, true);
|
SetProgress(double.NaN, true);
|
||||||
PathUtils.TryRemoveFile(outputFile);
|
|
||||||
}
|
}
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
}
|
}
|
||||||
@ -624,12 +627,13 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
SlunkCryptRunner.SlunkOptions options = new SlunkCryptRunner.SlunkOptions(m_config.KeepIncompleteFiles, m_config.ThreadCount);
|
||||||
using (m_processRunner = new SlunkCryptRunner(Dispatcher))
|
using (m_processRunner = new SlunkCryptRunner(Dispatcher))
|
||||||
{
|
{
|
||||||
m_processRunner.OutputAvailable += Process_OutputAvailable;
|
m_processRunner.OutputAvailable += Process_OutputAvailable;
|
||||||
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
|
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
|
||||||
SetProcessPriority(ProcessPriorityClass.AboveNormal);
|
SetProcessPriority(ProcessPriorityClass.AboveNormal);
|
||||||
return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password);
|
return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ProcessRunner.ProcessStartException err)
|
catch (ProcessRunner.ProcessStartException err)
|
||||||
|
@ -4,62 +4,138 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace com.muldersoft.slunkcrypt.gui.utils
|
namespace com.muldersoft.slunkcrypt.gui.utils
|
||||||
{
|
{
|
||||||
class ApplicationConfig
|
class ApplicationConfig
|
||||||
{
|
{
|
||||||
private readonly Lazy<KeyValueConfigurationCollection> m_settings = new Lazy<KeyValueConfigurationCollection>(InitializeSettings);
|
private readonly ConcurrentDictionary<string, int> m_cache = new ConcurrentDictionary<string, int>();
|
||||||
|
|
||||||
public bool DisableBusyIndicator
|
public bool DisableBusyIndicator
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetConfigValueAsBool("DisableBusyIndicator");
|
return ComputeIfAbsent("DisableBusyIndicator", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetConfigValue(string name)
|
public bool KeepIncompleteFiles
|
||||||
{
|
{
|
||||||
KeyValueConfigurationCollection settings = m_settings.Value;
|
get
|
||||||
if (!ReferenceEquals(settings, null))
|
|
||||||
{
|
{
|
||||||
KeyValueConfigurationElement element = settings[name];
|
return ComputeIfAbsent("KeepIncompleteFiles", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
|
||||||
if (!ReferenceEquals(element, null))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ThreadCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ComputeIfAbsent("ThreadCount", (key) => AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Internal methods
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
protected int ComputeIfAbsent(string name, Func<string, int> valueFactory)
|
||||||
|
{
|
||||||
|
return m_cache.GetOrAdd(name, valueFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool ComputeIfAbsent(string name, Func<string, bool> valueFactory)
|
||||||
|
{
|
||||||
|
return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Helper class
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
private static class AppConfHelper
|
||||||
|
{
|
||||||
|
private static readonly Lazy<KeyValueConfigurationCollection> m_settings = new Lazy<KeyValueConfigurationCollection>(InitializeSettings, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
|
private static volatile object m_syncRoot;
|
||||||
|
|
||||||
|
public static string GetConfigValue(string name)
|
||||||
|
{
|
||||||
|
KeyValueConfigurationCollection settings = m_settings.Value;
|
||||||
|
if (!ReferenceEquals(settings, null))
|
||||||
{
|
{
|
||||||
string value = element.Value;
|
lock (settings.SyncRoot ?? SyncRootInstance)
|
||||||
return string.IsNullOrWhiteSpace(value) ? string.Empty : value;
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KeyValueConfigurationElement element = settings[name];
|
||||||
|
if (!ReferenceEquals(element, null))
|
||||||
|
{
|
||||||
|
string value = element.Value;
|
||||||
|
return string.IsNullOrWhiteSpace(value) ? string.Empty : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return string.Empty;
|
||||||
}
|
}
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool GetConfigValueAsBool(string name)
|
public static bool? GetConfigValueAsBool(string name)
|
||||||
{
|
|
||||||
string value;
|
|
||||||
if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
|
|
||||||
{
|
{
|
||||||
bool result;
|
string value;
|
||||||
if (bool.TryParse(value.Trim(), out result))
|
if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
|
||||||
{
|
{
|
||||||
return result;
|
bool result;
|
||||||
|
if (bool.TryParse(value.Trim(), out result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KeyValueConfigurationCollection InitializeSettings()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
|
||||||
return configuration.AppSettings.Settings;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int? GetConfigValueAsInt32(string name)
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if (int.TryParse(value.Trim(), out result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KeyValueConfigurationCollection InitializeSettings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||||
|
return configuration.AppSettings.Settings;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object SyncRootInstance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_syncRoot == null)
|
||||||
|
{
|
||||||
|
Interlocked.CompareExchange<object>(ref m_syncRoot, new object(), null);
|
||||||
|
}
|
||||||
|
return m_syncRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
{
|
{
|
||||||
process.StartInfo.FileName = executablePath;
|
process.StartInfo.FileName = executablePath;
|
||||||
process.StartInfo.Arguments = CreateArgumentList(arguments);
|
process.StartInfo.Arguments = CreateArgumentList(arguments);
|
||||||
SetupEnvironment(process.StartInfo.EnvironmentVariables, environmentVariables);
|
SetupEnvironment(process.StartInfo.EnvironmentVariables, executablePath, environmentVariables);
|
||||||
process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
process.Start();
|
process.Start();
|
||||||
SetProcessPriority(process, priorityClass);
|
SetProcessPriority(process, priorityClass);
|
||||||
@ -390,13 +390,15 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupEnvironment(StringDictionary dictionary, IReadOnlyDictionary<string, string> environmentVariables)
|
private static void SetupEnvironment(StringDictionary dictionary, string executablePath, IReadOnlyDictionary<string, string> environmentVariables)
|
||||||
{
|
{
|
||||||
|
string baseDirectory = Path.GetDirectoryName(executablePath);
|
||||||
|
dictionary["PATH"] = string.IsNullOrEmpty(baseDirectory) ? Environment.SystemDirectory : baseDirectory;
|
||||||
if (!ReferenceEquals(environmentVariables, null))
|
if (!ReferenceEquals(environmentVariables, null))
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, string> entry in environmentVariables)
|
foreach (KeyValuePair<string, string> entry in environmentVariables)
|
||||||
{
|
{
|
||||||
dictionary.Add(entry.Key, entry.Value);
|
dictionary[entry.Key] = entry.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
/* CRT */
|
/* CRT */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* PThread */
|
/* PThread */
|
||||||
@ -80,9 +81,10 @@ static INLINE size_t BOUND(const size_t min, const size_t value, const size_t ma
|
|||||||
|
|
||||||
#define PTHRD_MUTEX_ENTER(X) do \
|
#define PTHRD_MUTEX_ENTER(X) do \
|
||||||
{ \
|
{ \
|
||||||
if (pthread_mutex_lock((X)) != 0) \
|
int _retval; \
|
||||||
|
while ((_retval = pthread_mutex_trylock((X))) != 0) \
|
||||||
{ \
|
{ \
|
||||||
abort(); \
|
if (_retval != EBUSY) { abort(); } \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while(0)
|
while(0)
|
||||||
|
Loading…
Reference in New Issue
Block a user