- **`DisableBusyIndicator`:**
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
==================
<?xml version="1.0" encoding="utf-8"?>
<configuration>
- <startup>
+ <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
<appSettings>
<add key="DisableBusyIndicator" value="false"/>
+ <add key="ThreadCount" value="0"/>
+ <add key="KeepIncompleteFiles" value="false"/>
</appSettings>
</configuration>
{
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_DECRYPT = "-d";
// 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>();
environmentVariables.Add("SLUNK_PASSPHRASE", password);
- string[] arguments = new string[] { GetCommandString(mode), inputFile, outputFile };
- return await ExecAsnyc(m_executableFile.Name, arguments, environmentVariables);
+ environmentVariables.Add("SLUNK_KEEP_INCOMPLETE", Convert.ToInt32(options.HasValue ? options.Value.keepIncompleteFiles : false).ToString());
+ 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()
return false;
}
- private static string GetCommandString(Mode mode)
+ private static string GetCommandLineModeString(Mode mode)
{
switch(mode)
{
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false;
if (!await processor(inputFile, outputFile, password))
{
+ if (!m_config.KeepIncompleteFiles)
+ {
+ PathUtils.TryRemoveFile(outputFile);
+ }
SetProgress(double.NaN, true);
- PathUtils.TryRemoveFile(outputFile);
}
await Task.Yield();
}
}
try
{
+ SlunkCryptRunner.SlunkOptions options = new SlunkCryptRunner.SlunkOptions(m_config.KeepIncompleteFiles, m_config.ThreadCount);
using (m_processRunner = new SlunkCryptRunner(Dispatcher))
{
m_processRunner.OutputAvailable += Process_OutputAvailable;
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
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)
/******************************************************************************/
using System;
+using System.Collections.Concurrent;
using System.Configuration;
+using System.Threading;
namespace com.muldersoft.slunkcrypt.gui.utils
{
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
{
get
{
- return GetConfigValueAsBool("DisableBusyIndicator");
+ return ComputeIfAbsent("DisableBusyIndicator", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
+ }
+ }
+
+ public bool KeepIncompleteFiles
+ {
+ get
+ {
+ return ComputeIfAbsent("KeepIncompleteFiles", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
}
}
- protected string GetConfigValue(string name)
+ public int ThreadCount
{
- KeyValueConfigurationCollection settings = m_settings.Value;
- if (!ReferenceEquals(settings, null))
+ get
{
- KeyValueConfigurationElement element = settings[name];
- if (!ReferenceEquals(element, null))
- {
- string value = element.Value;
- return string.IsNullOrWhiteSpace(value) ? string.Empty : value;
- }
+ return ComputeIfAbsent("ThreadCount", (key) => AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0));
}
- return string.Empty;
}
- protected bool GetConfigValueAsBool(string name)
+ // =============================================================================
+ // Internal methods
+ // =============================================================================
+
+ protected int ComputeIfAbsent(string name, Func<string, int> valueFactory)
{
- string value;
- if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
+ 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)
{
- bool result;
- if (bool.TryParse(value.Trim(), out result))
+ KeyValueConfigurationCollection settings = m_settings.Value;
+ if (!ReferenceEquals(settings, null))
{
- return result;
+ lock (settings.SyncRoot ?? SyncRootInstance)
+ {
+ 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 false;
- }
- private static KeyValueConfigurationCollection InitializeSettings()
- {
- try
+ public static bool? GetConfigValueAsBool(string name)
{
- Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
- return configuration.AppSettings.Settings;
+ string value;
+ if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
+ {
+ bool result;
+ if (bool.TryParse(value.Trim(), out result))
+ {
+ return result;
+ }
+ }
+ return null;
}
- catch
+
+ 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;
+ }
+ }
}
}
}
{
process.StartInfo.FileName = executablePath;
process.StartInfo.Arguments = CreateArgumentList(arguments);
- SetupEnvironment(process.StartInfo.EnvironmentVariables, environmentVariables);
+ SetupEnvironment(process.StartInfo.EnvironmentVariables, executablePath, environmentVariables);
process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
process.Start();
SetProcessPriority(process, priorityClass);
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))
{
foreach (KeyValuePair<string, string> entry in environmentVariables)
{
- dictionary.Add(entry.Key, entry.Value);
+ dictionary[entry.Key] = entry.Value;
}
}
}
/* CRT */
#include <stdlib.h>
+#include <errno.h>
#include <string.h>
/* PThread */
#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)