diff --git a/Greenshot/Destinations/EmailDestination.cs b/Greenshot/Destinations/EmailDestination.cs
index 8d9fe0ad9..323fe80f2 100644
--- a/Greenshot/Destinations/EmailDestination.cs
+++ b/Greenshot/Destinations/EmailDestination.cs
@@ -192,7 +192,10 @@ namespace Greenshot.Destinations {
using (Image image = surface.GetImageForExport()) {
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, conf.OutputFileFormat, conf.OutputFileJpegQuality, conf.OutputFileReduceColors);
}
+ } else {
+ LOG.InfoFormat("Using already available file: {0}", tmpFile);
}
+
// Create a attachment name for the image
string attachmentName = captureDetails.Title;
if (!string.IsNullOrEmpty(attachmentName)) {
diff --git a/Greenshot/Forms/MainForm.cs b/Greenshot/Forms/MainForm.cs
index 665dc002c..cf6803b83 100644
--- a/Greenshot/Forms/MainForm.cs
+++ b/Greenshot/Forms/MainForm.cs
@@ -450,7 +450,45 @@ namespace Greenshot {
}
base.WndProc(ref m);
}
-
+
+ ///
+ /// Helper method to cleanly register a hotkey
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static bool RegisterHotkey(StringBuilder failedKeys, string functionName, string hotkeyString, HotKeyHandler handler) {
+ Keys modifierKeyCode = HotkeyControl.HotkeyModifiersFromString(hotkeyString);
+ Keys virtualKeyCode = HotkeyControl.HotkeyFromString(hotkeyString);
+ if (HotkeyControl.RegisterHotKey(modifierKeyCode, virtualKeyCode, handler) < 0) {
+ LOG.DebugFormat("Failed to register {0} to hotkey: {1}", functionName, hotkeyString);
+ if (failedKeys.Length > 0) {
+ failedKeys.Append(", ");
+ }
+ failedKeys.Append(hotkeyString);
+ return false;
+ } else {
+ LOG.DebugFormat("Registered {0} to hotkey: {1}", functionName, hotkeyString);
+ }
+ return true;
+ }
+
+ private static bool RegisterWrapper(StringBuilder failedKeys, string functionName, string configurationKey, HotKeyHandler handler) {
+ IniValue hotkeyValue = conf.Values[configurationKey];
+ try {
+ return RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ LOG.WarnFormat("Repairing the hotkey for {0}, stored under {1} from '{2}' to '{3}'", functionName, configurationKey, hotkeyValue.Value, hotkeyValue.Attributes.DefaultValue);
+ // when getting an exception the key wasn't found: reset the hotkey value
+ hotkeyValue.UseValueOrDefault(null);
+ hotkeyValue.ContainingIniSection.IsDirty = true;
+ return RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
+ }
+ }
+
public static void RegisterHotkeys() {
if (instance == null) {
return;
@@ -458,64 +496,20 @@ namespace Greenshot {
bool success = true;
StringBuilder failedKeys = new StringBuilder();
- // Capture region
- if (HotkeyControl.RegisterHotKey(conf.RegionHotkey, new HotKeyHandler(instance.CaptureRegion)) < 0) {
- LOG.DebugFormat("Failed to register CaptureRegion to hotkey: {0}", conf.RegionHotkey);
+ if (!RegisterWrapper(failedKeys, "CaptureRegion", "RegionHotkey", new HotKeyHandler(instance.CaptureRegion))) {
success = false;
- if(failedKeys.Length > 0) {
- failedKeys.Append(", ");
- }
- failedKeys.Append(conf.RegionHotkey);
- } else {
- LOG.DebugFormat("Registered CaptureRegion to hotkey: {0}", conf.RegionHotkey);
}
-
- // Capture window
- if (HotkeyControl.RegisterHotKey(conf.WindowHotkey, new HotKeyHandler(instance.CaptureWindow)) < 0) {
- LOG.DebugFormat("Failed to register CaptureWindow to hotkey: {0}", conf.WindowHotkey);
+ if (!RegisterWrapper(failedKeys, "CaptureWindow", "WindowHotkey", new HotKeyHandler(instance.CaptureWindow))) {
success = false;
- if(failedKeys.Length > 0) {
- failedKeys.Append(", ");
- }
- failedKeys.Append(conf.WindowHotkey);
- } else {
- LOG.DebugFormat("Registered CaptureWindow to hotkey: {0}", conf.WindowHotkey);
}
-
- // Capture fullScreen
- if (HotkeyControl.RegisterHotKey(conf.FullscreenHotkey, new HotKeyHandler(instance.CaptureFullScreen)) < 0) {
- LOG.DebugFormat("Failed to register CaptureFullScreen to hotkey: {0}", conf.FullscreenHotkey);
+ if (!RegisterWrapper(failedKeys, "CaptureFullScreen", "FullscreenHotkey", new HotKeyHandler(instance.CaptureFullScreen))) {
success = false;
- if(failedKeys.Length > 0) {
- failedKeys.Append(", ");
- }
- failedKeys.Append(conf.FullscreenHotkey);
- } else {
- LOG.DebugFormat("Registered CaptureFullScreen to hotkey: {0}", conf.FullscreenHotkey);
}
-
- // Capture last region
- if (HotkeyControl.RegisterHotKey(conf.LastregionHotkey, new HotKeyHandler(instance.CaptureLastRegion)) < 0) {
- LOG.DebugFormat("Failed to register CaptureLastRegion to hotkey: {0}", conf.LastregionHotkey);
+ if (!RegisterWrapper(failedKeys, "CaptureLastRegion", "LastregionHotkey", new HotKeyHandler(instance.CaptureLastRegion))) {
success = false;
- if(failedKeys.Length > 0) {
- failedKeys.Append(", ");
- }
- failedKeys.Append(conf.LastregionHotkey);
- } else {
- LOG.DebugFormat("Registered CaptureLastRegion to hotkey: {0}", conf.LastregionHotkey);
}
-
- // Capture IE
- if (HotkeyControl.RegisterHotKey(conf.IEHotkey, new HotKeyHandler(instance.CaptureIE)) < 0) {
- LOG.DebugFormat("Failed to register CaptureIE to hotkey: {0}", conf.IEHotkey);
+ if (!RegisterWrapper(failedKeys, "CaptureIE", "IEHotkey", new HotKeyHandler(instance.CaptureIE))) {
success = false;
- if(failedKeys.Length > 0) {
- failedKeys.Append(", ");
- }
- failedKeys.Append(conf.IEHotkey);
- } else {
- LOG.DebugFormat("Registered CaptureIE to hotkey: {0}", conf.IEHotkey);
}
if (!success) {
diff --git a/Greenshot/Helpers/DestinationHelper.cs b/Greenshot/Helpers/DestinationHelper.cs
index b313a0a4b..6535b8a38 100644
--- a/Greenshot/Helpers/DestinationHelper.cs
+++ b/Greenshot/Helpers/DestinationHelper.cs
@@ -75,7 +75,10 @@ namespace Greenshot.Helpers {
List destinations = new List();
destinations.AddRange(RegisteredDestinations.Values);
foreach(IGreenshotPlugin plugin in PluginHelper.instance.Plugins.Values) {
- destinations.AddRange(plugin.Destinations());
+ var dests = plugin.Destinations();
+ if (dests != null) {
+ destinations.AddRange(dests);
+ }
}
destinations.Sort();
return destinations;
diff --git a/Greenshot/Helpers/EnvironmentInfo.cs b/Greenshot/Helpers/EnvironmentInfo.cs
index 8f3e52f21..68e51a077 100644
--- a/Greenshot/Helpers/EnvironmentInfo.cs
+++ b/Greenshot/Helpers/EnvironmentInfo.cs
@@ -125,7 +125,7 @@ namespace Greenshot.Helpers {
exceptionText.AppendLine(EnvironmentInfo.ExceptionToString(exception));
exceptionText.AppendLine("Configuration dump:");
using (TextWriter writer = new StringWriter(exceptionText)) {
- IniConfig.SaveIniSectionToWriter(writer, IniConfig.GetIniSection(), true);
+ IniConfig.GetIniSection().Write(writer, true);
}
return exceptionText.ToString();
diff --git a/GreenshotPlugin/Core/CoreConfiguration.cs b/GreenshotPlugin/Core/CoreConfiguration.cs
index 8d5c50e3a..1a5d00024 100644
--- a/GreenshotPlugin/Core/CoreConfiguration.cs
+++ b/GreenshotPlugin/Core/CoreConfiguration.cs
@@ -194,7 +194,8 @@ namespace GreenshotPlugin.Core {
if (productName != null && NoDWMCaptureForProduct.Contains(productName.ToLower())) {
return false;
}
- } catch {
+ } catch (Exception ex) {
+ LOG.Warn(ex);
}
}
}
@@ -214,7 +215,8 @@ namespace GreenshotPlugin.Core {
if (productName != null && NoGDICaptureForProduct.Contains(productName.ToLower())) {
return false;
}
- } catch {
+ } catch (Exception ex) {
+ LOG.Warn(ex);
}
}
}
@@ -250,7 +252,8 @@ namespace GreenshotPlugin.Core {
try {
Directory.CreateDirectory(pafOutputFilePath);
return pafOutputFilePath;
- } catch(Exception) {
+ } catch (Exception ex) {
+ LOG.Warn(ex);
// Problem creating directory, fallback to Desktop
}
} else {
diff --git a/GreenshotPlugin/Core/InterfaceUtils.cs b/GreenshotPlugin/Core/InterfaceUtils.cs
index dbb196d1a..dda013442 100644
--- a/GreenshotPlugin/Core/InterfaceUtils.cs
+++ b/GreenshotPlugin/Core/InterfaceUtils.cs
@@ -48,7 +48,8 @@ namespace GreenshotPlugin.Core {
}
}
}
- } catch {
+ } catch (Exception ex) {
+ LOG.Warn(ex);
}
}
return list;
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index 4ed110f3b..cc53b6b38 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -244,7 +244,7 @@ namespace GreenshotPlugin.Core {
return iconCache[filename];
} catch (Exception ex) {
LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message);
- };
+ }
return null;
}
}
@@ -567,7 +567,9 @@ namespace GreenshotPlugin.Core {
if (process != null) {
return process;
}
- } catch {}
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ }
return null;
}
}
@@ -1358,7 +1360,9 @@ namespace GreenshotPlugin.Core {
get {
try {
return "Greenshot".Equals(Process.MainModule.FileVersionInfo.ProductName);
- } catch {}
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ }
return false;
}
}
diff --git a/GreenshotPlugin/IniFile/IniConfig.cs b/GreenshotPlugin/IniFile/IniConfig.cs
index 9a5eb43ea..20bf1816e 100644
--- a/GreenshotPlugin/IniFile/IniConfig.cs
+++ b/GreenshotPlugin/IniFile/IniConfig.cs
@@ -221,7 +221,7 @@ namespace Greenshot.IniFile {
Read(CreateIniLocation(configName + FIXED_POSTFIX + INI_EXTENSION));
foreach (IniSection section in sectionMap.Values) {
- FillIniSection(section);
+ section.Fill(PropertiesForSection(section));
}
}
@@ -278,8 +278,7 @@ namespace Greenshot.IniFile {
// Store for later save & retrieval
sectionMap.Add(sectionName, section);
- FillIniSection(section);
- //LOG.Debug("Returning newly mapped section " + sectionName);
+ section.Fill(PropertiesForSection(section));
}
if (section.IsDirty) {
LOG.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
@@ -288,7 +287,7 @@ namespace Greenshot.IniFile {
return section;
}
- private static void FillIniSection(IniSection section) {
+ public static Dictionary PropertiesForSection(IniSection section) {
Type iniSectionType = section.GetType();
string sectionName = getSectionName(iniSectionType);
// Get the properties for the section
@@ -299,279 +298,7 @@ namespace Greenshot.IniFile {
sections.Add(sectionName, new Dictionary());
properties = sections[sectionName];
}
-
- // Iterate over the members and create IniValueContainers
- foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) {
- if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) {
- if (!section.Values.ContainsKey(fieldInfo.Name)) {
- IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
- section.Values.Add(fieldInfo.Name, new IniValue(section, fieldInfo, iniPropertyAttribute));
- }
- }
- }
-
- foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) {
- if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) {
- if (!section.Values.ContainsKey(propertyInfo.Name)) {
- IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
- section.Values.Add(propertyInfo.Name, new IniValue(section, propertyInfo, iniPropertyAttribute));
- }
- }
- }
-
- foreach (string fieldName in section.Values.Keys) {
- IniValue iniValue = section.Values[fieldName];
- string propertyName = iniValue.Attributes.Name;
- string propertyDefaultValue = iniValue.Attributes.DefaultValue;
-
- // Get the value from the ini file, if there is none take the default
- if (!properties.ContainsKey(propertyName) && propertyDefaultValue != null) {
- // Mark as dirty, we didn't use properties from the file (even defaults from the default file are allowed)
- section.IsDirty = true;
- //LOG.Debug("Passing default: " + propertyName + "=" + propertyDefaultValue);
- }
-
- // Try to get the field value from the properties or use the default value
- object fieldValue = null;
- try {
- fieldValue = CreateValue(section, sectionName, iniValue);
- } catch (Exception) {
- //LOG.Warn("Couldn't parse field: " + sectionName + "." + propertyName, e);
- }
-
- // If still no value, e.g. due to an exception, check if the GetDefault delivers a value
- if (fieldValue == null) {
- // Use GetDefault to fill the field if none is set
- fieldValue = section.GetDefault(propertyName);
- }
-
- // Still no value? Log warning
- if (fieldValue == null) {
- LOG.WarnFormat("Property {0} has no value or default value.", propertyName);
- }
-
- // Set the value
- try {
- iniValue.Value = fieldValue;
- } catch (Exception) {
- //LOG.Warn("Couldn't set field: " + sectionName + "." + propertyName, e);
- }
- }
- section.AfterLoad();
- }
-
- ///
- /// Helper method for creating a value
- ///
- /// IniSection
- /// string with name of section
- /// IniValue
- ///
- private static object CreateValue(IniSection section, string sectionName, IniValue iniValue) {
- string propertyName = iniValue.Attributes.Name;
- string defaultValue = iniValue.Attributes.DefaultValue;
- string arraySeparator = iniValue.Attributes.Separator;
- // Get the type, or the underlying type for nullables
- Type valueType = iniValue.ValueType;
-
- Dictionary properties = sections[sectionName];
- bool defaultUsed = false;
- string propertyValue = null;
- object defaultValueFromConfig = null;
- if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
- propertyValue = section.PreCheckValue(propertyName, properties[propertyName]);
- } else if (defaultValue != null && defaultValue.Trim().Length != 0) {
- propertyValue = defaultValue;
- defaultUsed = true;
- } else {
- LOG.DebugFormat("Property {0} has no value or default value, this might be corrected later!", propertyName);
- // Check if the developer implemented a default for the property
- defaultValueFromConfig = section.GetDefault(propertyName);
- if (defaultValueFromConfig != null) {
- LOG.DebugFormat("Default for Property {0} implemented!", propertyName);
- } else {
- if (iniValue.Attributes.ExcludeIfNull) {
- return null;
- }
- }
- }
-
- // Now set the value
- if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
- object list = Activator.CreateInstance(valueType);
- // Logic for List<>
- if (propertyValue == null) {
- if (defaultValueFromConfig != null) {
- return defaultValueFromConfig;
- }
- return list;
- }
- string[] arrayValues = propertyValue.Split(new string[] { arraySeparator }, StringSplitOptions.None);
- if (arrayValues == null || arrayValues.Length == 0) {
- return list;
- }
- bool addedElements = false;
- bool parseProblems = false;
- MethodInfo addMethodInfo = valueType.GetMethod("Add");
-
- foreach (string arrayValue in arrayValues) {
- if (arrayValue != null && arrayValue.Length > 0) {
- object newValue = null;
- try {
- newValue = ConvertValueToValueType(valueType.GetGenericArguments()[0], arrayValue);
- } catch (Exception) {
- //LOG.Error("Problem converting " + arrayValue + " to type " + fieldType.FullName, e);
- parseProblems = true;
- }
- if (newValue != null) {
- addMethodInfo.Invoke(list, new object[] { newValue });
- addedElements = true;
- }
- }
- }
- // Try to fallback on a default
- if (!addedElements && parseProblems) {
- try {
- object fallbackValue = ConvertValueToValueType(valueType.GetGenericArguments()[0], defaultValue);
- addMethodInfo.Invoke(list, new object[] { fallbackValue });
- return list;
- } catch (Exception) {
- //LOG.Error("Problem converting " + defaultValue + " to type " + fieldType.FullName, e);
- }
- }
-
- return list;
- } else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
- // Logic for Dictionary<,>
- Type type1 = valueType.GetGenericArguments()[0];
- Type type2 = valueType.GetGenericArguments()[1];
- //LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name));
- object dictionary = Activator.CreateInstance(valueType);
- MethodInfo addMethodInfo = valueType.GetMethod("Add");
- bool addedElements = false;
- foreach (string key in properties.Keys) {
- if (key != null && key.StartsWith(propertyName + ".")) {
- // What "key" do we need to store it under?
- string subPropertyName = key.Substring(propertyName.Length + 1);
- string stringValue = properties[key];
- object newValue1 = null;
- object newValue2 = null;
- try {
- newValue1 = ConvertValueToValueType(type1, subPropertyName);
- } catch (Exception) {
- //LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
- }
- try {
- newValue2 = ConvertValueToValueType(type2, stringValue);
- } catch (Exception) {
- //LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
- }
- addMethodInfo.Invoke(dictionary, new object[] { newValue1, newValue2 });
- addedElements = true;
- }
- }
- // No need to return something that isn't filled!
- if (addedElements) {
- return dictionary;
- } else if (defaultValueFromConfig != null) {
- return defaultValueFromConfig;
- }
- } if (defaultValueFromConfig != null) {
- return defaultValueFromConfig;
- } else {
- if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
- // We are dealing with a generic type that is nullable
- valueType = Nullable.GetUnderlyingType(valueType);
- }
- object newValue = null;
- try {
- newValue = ConvertValueToValueType(valueType, propertyValue);
- } catch (Exception) {
- newValue = null;
- if (!defaultUsed) {
- try {
- newValue = ConvertValueToValueType(valueType, defaultValue);
- } catch (Exception) {
- //LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e2);
- }
- } else {
- //LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e1);
- }
- }
- return newValue;
- }
- }
-
- private static object ConvertValueToValueType(Type valueType, string valueString) {
- if (valueString == null) {
- return null;
- }
- if (valueType == typeof(string)) {
- return valueString;
- }
- TypeConverter converter = TypeDescriptor.GetConverter(valueType);
- //LOG.Debug("No convertor for " + fieldType.ToString());
- if (valueType == typeof(object) && valueString.Length > 0) {
- //LOG.Debug("Parsing: " + valueString);
- string[] values = valueString.Split(new Char[] { ':' });
- //LOG.Debug("Type: " + values[0]);
- //LOG.Debug("Value: " + values[1]);
- Type fieldTypeForValue = Type.GetType(values[0], true);
- //LOG.Debug("Type after GetType: " + fieldTypeForValue);
- return ConvertValueToValueType(fieldTypeForValue, values[1]);
- } else if (converter != null) {
- return converter.ConvertFromInvariantString(valueString);
- } else if (valueType.IsEnum) {
- if (valueString.Length > 0) {
- try {
- return Enum.Parse(valueType, valueString);
- } catch (ArgumentException ae) {
- //LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
- foreach (Enum enumValue in Enum.GetValues(valueType)) {
- if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
- //LOG.Info("Match found...");
- return enumValue;
- }
- }
- throw ae;
- }
- }
- }
- return null;
- }
-
- private static string ConvertValueToString(Type valueType, object valueObject) {
- if (valueObject == null) {
- // If there is nothing, deliver nothing!
- return "";
- }
- if (valueType == typeof(object)) {
- // object to String, this is the hardest
- // Format will be "FQTypename[,Assemblyname]:Value"
-
- // Get the type so we can call ourselves recursive
- Type objectType = valueObject.GetType();
-
- // Get the value as string
- string ourValue = ConvertValueToString(objectType, valueObject);
-
- // Get the valuetype as string
- string valueTypeName = objectType.FullName;
- // Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing)
- string assemblyName = objectType.Assembly.FullName;
- // correct assemblyName, this also has version information etc.
- if (assemblyName.StartsWith("Green")) {
- assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
- }
- return String.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
- } else {
- TypeConverter converter = TypeDescriptor.GetConverter(valueType);
- if (converter != null) {
- return converter.ConvertToInvariantString(valueObject);
- }
- }
- // All other types
- return valueObject.ToString();
+ return properties;
}
private static string getSectionName(Type iniSectionType) {
@@ -589,101 +316,12 @@ namespace Greenshot.IniFile {
string iniLocation = CreateIniLocation(configName + INI_EXTENSION);
try {
SaveInternally(iniLocation);
- } catch (Exception) {
- //LOG.Error("A problem occured while writing the configuration file to: " + iniLocation, e);
+ } catch (Exception ex) {
+ LOG.Error("A problem occured while writing the configuration file to: " + iniLocation);
+ LOG.Error(ex);
}
}
- public static void SaveIniSectionToWriter(TextWriter writer, IniSection section, bool onlyProperties) {
- section.BeforeSave();
- Type classType = section.GetType();
- Attribute[] classAttributes = Attribute.GetCustomAttributes(classType);
- foreach (Attribute attribute in classAttributes) {
- if (attribute is IniSectionAttribute) {
- IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute;
- if (!onlyProperties) {
- writer.WriteLine("; {0}", iniSectionAttribute.Description);
- }
- writer.WriteLine("[{0}]", iniSectionAttribute.Name);
-
- // Iterate over the members and fill them
- List members = new List();
-
- foreach (FieldInfo fieldInfo in classType.GetFields()) {
- members.Add(fieldInfo);
- }
- foreach (PropertyInfo propertyInfo in classType.GetProperties()) {
- members.Add(propertyInfo);
- }
-
- foreach (MemberInfo member in members) {
- if (Attribute.IsDefined(member, typeof(IniPropertyAttribute))) {
- IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)member.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
- object propertyValue;
- Type valueType;
- if (member is FieldInfo) {
- propertyValue = ((FieldInfo)member).GetValue(section);
- valueType = ((FieldInfo)member).FieldType;
- } else if (member is PropertyInfo) {
- propertyValue = ((PropertyInfo)member).GetValue(section, null);
- valueType = ((PropertyInfo)member).PropertyType;
- } else {
- continue;
- }
-
- if (propertyValue == null) {
- if (iniPropertyAttribute.ExcludeIfNull) {
- continue;
- }
- propertyValue = iniPropertyAttribute.DefaultValue;
- valueType = typeof(string);
- }
-
- if (!onlyProperties) {
- writer.WriteLine("; {0}", iniPropertyAttribute.Description);
- }
- if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
- Type specificValueType = valueType.GetGenericArguments()[0];
- writer.Write("{0}=", iniPropertyAttribute.Name);
- int listCount = (int)valueType.GetProperty("Count").GetValue(propertyValue, null);
- // Loop though generic list
- for (int index = 0; index < listCount; index++) {
- object item = valueType.GetMethod("get_Item").Invoke(propertyValue, new object[] { index });
-
- // Now you have an instance of the item in the generic list
- if (index < listCount - 1) {
- writer.Write("{0}" + iniPropertyAttribute.Separator, ConvertValueToString(specificValueType, item));
- } else {
- writer.Write("{0}", ConvertValueToString(specificValueType, item));
- }
- }
- writer.WriteLine();
- } else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
- // Handle dictionaries.
- Type valueType1 = valueType.GetGenericArguments()[0];
- Type valueType2 = valueType.GetGenericArguments()[1];
- // Get the methods we need to deal with dictionaries.
- var keys = valueType.GetProperty("Keys").GetValue(propertyValue, null);
- var item = valueType.GetProperty("Item");
- var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null);
- var moveNext = enumerator.GetType().GetMethod("MoveNext");
- var current = enumerator.GetType().GetProperty("Current").GetGetMethod();
- // Get all the values.
- while ((bool)moveNext.Invoke(enumerator, null)) {
- var key = current.Invoke(enumerator, null);
- var valueObject = item.GetValue(propertyValue, new object[] { key });
- // Write to ini file!
- writer.WriteLine("{0}.{1}={2}", iniPropertyAttribute.Name, ConvertValueToString(valueType1, key), ConvertValueToString(valueType2, valueObject));
- }
- } else {
- writer.WriteLine("{0}={1}", iniPropertyAttribute.Name, ConvertValueToString(valueType, propertyValue));
- }
- }
- }
- }
- section.AfterSave();
- }
- }
private static void SaveInternally(string iniLocation) {
WatchConfigFile(false);
@@ -694,7 +332,7 @@ namespace Greenshot.IniFile {
}
TextWriter writer = new StreamWriter(iniLocation, false, Encoding.UTF8);
foreach (IniSection section in sectionMap.Values) {
- SaveIniSectionToWriter(writer, section, false);
+ section.Write(writer, false);
// Add empty line after section
writer.WriteLine();
section.IsDirty = false;
diff --git a/GreenshotPlugin/IniFile/IniSection.cs b/GreenshotPlugin/IniFile/IniSection.cs
index 444a3847f..ca7684bd5 100644
--- a/GreenshotPlugin/IniFile/IniSection.cs
+++ b/GreenshotPlugin/IniFile/IniSection.cs
@@ -20,6 +20,8 @@
*/
using System;
using System.Collections.Generic;
+using System.Reflection;
+using System.IO;
namespace Greenshot.IniFile {
///
@@ -27,16 +29,23 @@ namespace Greenshot.IniFile {
///
[Serializable]
public abstract class IniSection {
+ protected static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniSection));
+
[NonSerialized]
private IDictionary values = new Dictionary();
+ ///
+ /// Get the dictionary with all the IniValues
+ ///
public IDictionary Values {
get {
return values;
}
}
+ ///
/// Flag to specify if values have been changed
+ ///
public bool IsDirty = false;
///
@@ -65,10 +74,86 @@ namespace Greenshot.IniFile {
public virtual void AfterLoad() {
}
+ ///
+ /// This will be called before saving the Section, so we can encrypt passwords etc...
+ ///
public virtual void BeforeSave() {
}
+ ///
+ /// This will be called before saving the Section, so we can decrypt passwords etc...
+ ///
public virtual void AfterSave() {
}
+
+ ///
+ /// Fill the section with the supplied properties
+ ///
+ ///
+ public void Fill(Dictionary properties) {
+ Type iniSectionType = this.GetType();
+
+ // Iterate over the members and create IniValueContainers
+ foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) {
+ if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) {
+ if (!Values.ContainsKey(fieldInfo.Name)) {
+ IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
+ Values.Add(fieldInfo.Name, new IniValue(this, fieldInfo, iniPropertyAttribute));
+ }
+ }
+ }
+
+ foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) {
+ if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) {
+ if (!Values.ContainsKey(propertyInfo.Name)) {
+ IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
+ Values.Add(propertyInfo.Name, new IniValue(this, propertyInfo, iniPropertyAttribute));
+ }
+ }
+ }
+
+ foreach (string fieldName in Values.Keys) {
+ IniValue iniValue = Values[fieldName];
+ try {
+ iniValue.SetValueFromProperties(properties);
+ } catch (Exception ex) {
+ LOG.Error(ex);
+ }
+ }
+ AfterLoad();
+ }
+
+ ///
+ /// Write the section to the writer
+ ///
+ ///
+ ///
+ public void Write(TextWriter writer, bool onlyProperties) {
+ BeforeSave();
+ try {
+ Attribute[] classAttributes = Attribute.GetCustomAttributes(this.GetType());
+ IniSectionAttribute iniSectionAttribute = null;
+ foreach (Attribute attribute in classAttributes) {
+ if (attribute is IniSectionAttribute) {
+ iniSectionAttribute = (IniSectionAttribute)attribute;
+ break;
+ }
+ }
+ if (iniSectionAttribute == null) {
+ throw new ArgumentException("Section didn't implement the IniSectionAttribute");
+ }
+
+ if (!onlyProperties) {
+ writer.WriteLine("; {0}", iniSectionAttribute.Description);
+ }
+ writer.WriteLine("[{0}]", iniSectionAttribute.Name);
+
+ foreach (IniValue value in Values.Values) {
+ value.Write(writer, onlyProperties);
+ }
+ } finally {
+ AfterSave();
+ }
+ }
}
}
diff --git a/GreenshotPlugin/IniFile/IniValue.cs b/GreenshotPlugin/IniFile/IniValue.cs
index 3fd85f080..b079295cf 100644
--- a/GreenshotPlugin/IniFile/IniValue.cs
+++ b/GreenshotPlugin/IniFile/IniValue.cs
@@ -20,25 +20,29 @@
*/
using System;
using System.Reflection;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
namespace Greenshot.IniFile {
///
/// A container to be able to pass the value from a IniSection around.
///
public class IniValue {
+ private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniValue));
private PropertyInfo propertyInfo;
private FieldInfo fieldInfo;
- private object containingObject;
+ private IniSection containingIniSection;
private IniPropertyAttribute attributes;
- public IniValue(object containingObject, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) {
- this.containingObject = containingObject;
+ public IniValue(IniSection containingIniSection, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) {
+ this.containingIniSection = containingIniSection;
this.propertyInfo = propertyInfo;
this.attributes = iniPropertyAttribute;
}
- public IniValue(object containingObject, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) {
- this.containingObject = containingObject;
+ public IniValue(IniSection containingIniSection, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) {
+ this.containingIniSection = containingIniSection;
this.fieldInfo = fieldInfo;
this.attributes = iniPropertyAttribute;
}
@@ -52,6 +56,12 @@ namespace Greenshot.IniFile {
}
}
}
+
+ public IniSection ContainingIniSection {
+ get {
+ return containingIniSection;
+ }
+ }
public IniPropertyAttribute Attributes {
get {
@@ -62,28 +72,354 @@ namespace Greenshot.IniFile {
public object Value {
get {
if (propertyInfo == null) {
- return fieldInfo.GetValue(containingObject);
+ return fieldInfo.GetValue(containingIniSection);
} else {
- return propertyInfo.GetValue(containingObject, null);
+ return propertyInfo.GetValue(containingIniSection, null);
}
}
set {
if (propertyInfo == null) {
- fieldInfo.SetValue(containingObject, value);
+ fieldInfo.SetValue(containingIniSection, value);
} else {
- propertyInfo.SetValue(containingObject, value, null);
+ propertyInfo.SetValue(containingIniSection, value, null);
}
}
}
public Type ValueType {
get {
+ Type valueType = null;
if (propertyInfo == null) {
- return fieldInfo.FieldType;
+ valueType = fieldInfo.FieldType;
} else {
- return propertyInfo.PropertyType;
+ valueType = propertyInfo.PropertyType;
}
+ if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
+ // We are dealing with a generic type that is nullable
+ valueType = Nullable.GetUnderlyingType(valueType);
+ }
+ return valueType;
}
}
+
+ ///
+ /// Write the value to the text writer
+ ///
+ /// TextWriter to write to
+ /// true if we do not want the comment
+ public void Write(TextWriter writer, bool onlyProperties) {
+ object myValue = Value;
+ Type valueType = ValueType;
+ if (myValue == null) {
+ if (attributes.ExcludeIfNull) {
+ return;
+ }
+ if (attributes.DefaultValue != null) {
+ myValue = attributes.DefaultValue;
+ valueType = typeof(string);
+ } else {
+ myValue = containingIniSection.GetDefault(attributes.Name);
+ if (myValue != null) {
+ valueType = myValue.GetType();
+ }
+ }
+ }
+ if (myValue == null) {
+ if (attributes.ExcludeIfNull) {
+ return;
+ }
+ }
+ if (!onlyProperties) {
+ writer.WriteLine("; {0}", attributes.Description);
+ }
+ if (myValue == null) {
+ writer.Write("{0}=", attributes.Name);
+ return;
+ }
+ if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) {
+ Type specificValueType = valueType.GetGenericArguments()[0];
+ writer.Write("{0}=", attributes.Name);
+ int listCount = (int)valueType.GetProperty("Count").GetValue(myValue, null);
+ // Loop though generic list
+ for (int index = 0; index < listCount; index++) {
+ object item = valueType.GetMethod("get_Item").Invoke(myValue, new object[] { index });
+
+ // Now you have an instance of the item in the generic list
+ if (index < listCount - 1) {
+ writer.Write("{0}" + attributes.Separator, ConvertValueToString(specificValueType, item));
+ } else {
+ writer.Write("{0}", ConvertValueToString(specificValueType, item));
+ }
+ }
+ writer.WriteLine();
+ } else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
+ // Handle dictionaries.
+ Type valueType1 = valueType.GetGenericArguments()[0];
+ Type valueType2 = valueType.GetGenericArguments()[1];
+ // Get the methods we need to deal with dictionaries.
+ var keys = valueType.GetProperty("Keys").GetValue(myValue, null);
+ var item = valueType.GetProperty("Item");
+ var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null);
+ var moveNext = enumerator.GetType().GetMethod("MoveNext");
+ var current = enumerator.GetType().GetProperty("Current").GetGetMethod();
+ // Get all the values.
+ while ((bool)moveNext.Invoke(enumerator, null)) {
+ var key = current.Invoke(enumerator, null);
+ var valueObject = item.GetValue(myValue, new object[] { key });
+ // Write to ini file!
+ writer.WriteLine("{0}.{1}={2}", attributes.Name, ConvertValueToString(valueType1, key), ConvertValueToString(valueType2, valueObject));
+ }
+ } else {
+ writer.WriteLine("{0}={1}", attributes.Name, ConvertValueToString(valueType, myValue));
+ }
+
+ }
+
+ ///
+ /// Set the value to the value in the ini file, or default
+ ///
+ ///
+ public void SetValueFromProperties(Dictionary properties) {
+ string propertyName = attributes.Name;
+ string defaultValue = attributes.DefaultValue;
+
+ // Get the value from the ini file, if there is none take the default
+ if (!properties.ContainsKey(propertyName) && defaultValue != null) {
+ // Mark as dirty, we didn't use properties from the file (even defaults from the default file are allowed)
+ containingIniSection.IsDirty = true;
+ //LOG.Debug("Passing default: " + propertyName + "=" + propertyDefaultValue);
+ }
+
+ string propertyValue = null;
+ if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
+ propertyValue = containingIniSection.PreCheckValue(propertyName, properties[propertyName]);
+ }
+ UseValueOrDefault(propertyValue);
+ }
+
+ ///
+ /// This method will set the ini value to the supplied value or use the default if non supplied
+ ///
+ ///
+ public void UseValueOrDefault(string propertyValue) {
+ Type valueType = ValueType;
+ string propertyName = attributes.Name;
+ string defaultValue = attributes.DefaultValue;
+ bool defaultUsed = false;
+ object defaultValueFromConfig = containingIniSection.GetDefault(propertyName);
+
+ if (string.IsNullOrEmpty(propertyValue)) {
+ if (defaultValue != null && defaultValue.Trim().Length != 0) {
+ propertyValue = defaultValue;
+ defaultUsed = true;
+ } else if (defaultValueFromConfig != null) {
+ LOG.DebugFormat("Default for Property {0} implemented!", propertyName);
+ } else {
+ if (attributes.ExcludeIfNull) {
+ Value = null;
+ return;
+ }
+ LOG.DebugFormat("Property {0} has no value or default value!", propertyName);
+ }
+ }
+ // Now set the value
+ if (valueType.IsGenericType && ValueType.GetGenericTypeDefinition() == typeof(List<>)) {
+ string arraySeparator = attributes.Separator;
+ object list = Activator.CreateInstance(ValueType);
+ // Logic for List<>
+ if (propertyValue == null) {
+ if (defaultValueFromConfig != null) {
+ Value = defaultValueFromConfig;
+ return;
+ }
+ Value = list;
+ return;
+ }
+ string[] arrayValues = propertyValue.Split(new string[] { arraySeparator }, StringSplitOptions.None);
+ if (arrayValues == null || arrayValues.Length == 0) {
+ Value = list;
+ return;
+ }
+ bool addedElements = false;
+ bool parseProblems = false;
+ MethodInfo addMethodInfo = valueType.GetMethod("Add");
+
+ foreach (string arrayValue in arrayValues) {
+ if (arrayValue != null && arrayValue.Length > 0) {
+ object newValue = null;
+ try {
+ newValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], arrayValue);
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ //LOG.Error("Problem converting " + arrayValue + " to type " + fieldType.FullName, e);
+ parseProblems = true;
+ }
+ if (newValue != null) {
+ addMethodInfo.Invoke(list, new object[] { newValue });
+ addedElements = true;
+ }
+ }
+ }
+ // Try to fallback on a default
+ if (!addedElements && parseProblems) {
+ try {
+ object fallbackValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], defaultValue);
+ addMethodInfo.Invoke(list, new object[] { fallbackValue });
+ Value = list;
+ return;
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ //LOG.Error("Problem converting " + defaultValue + " to type " + fieldType.FullName, e);
+ }
+ }
+ Value = list;
+ return;
+ } else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
+ // Logic for Dictionary<,>
+ Type type1 = valueType.GetGenericArguments()[0];
+ Type type2 = valueType.GetGenericArguments()[1];
+ //LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name));
+ object dictionary = Activator.CreateInstance(valueType);
+ MethodInfo addMethodInfo = valueType.GetMethod("Add");
+ bool addedElements = false;
+ Dictionary properties = IniConfig.PropertiesForSection(containingIniSection);
+ foreach (string key in properties.Keys) {
+ if (key != null && key.StartsWith(propertyName + ".")) {
+ // What "key" do we need to store it under?
+ string subPropertyName = key.Substring(propertyName.Length + 1);
+ string stringValue = properties[key];
+ object newValue1 = null;
+ object newValue2 = null;
+ try {
+ newValue1 = ConvertStringToValueType(type1, subPropertyName);
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ //LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
+ }
+ try {
+ newValue2 = ConvertStringToValueType(type2, stringValue);
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ //LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
+ }
+ addMethodInfo.Invoke(dictionary, new object[] { newValue1, newValue2 });
+ addedElements = true;
+ }
+ }
+ // No need to return something that isn't filled!
+ if (addedElements) {
+ Value = dictionary;
+ return;
+ } else if (defaultValueFromConfig != null) {
+ Value = defaultValueFromConfig;
+ return;
+ }
+ } if (defaultValueFromConfig != null) {
+ Value = defaultValueFromConfig;
+ return;
+ } else {
+ if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
+ // We are dealing with a generic type that is nullable
+ valueType = Nullable.GetUnderlyingType(valueType);
+ }
+ object newValue = null;
+ try {
+ newValue = ConvertStringToValueType(valueType, propertyValue);
+ } catch (Exception ex1) {
+ newValue = null;
+ if (!defaultUsed) {
+ try {
+ newValue = ConvertStringToValueType(valueType, defaultValue);
+ } catch (Exception ex2) {
+ LOG.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex2);
+ }
+ } else {
+ LOG.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1);
+ }
+ }
+ Value = newValue;
+ return;
+ }
+ }
+
+ ///
+ /// Helper method for conversion
+ ///
+ ///
+ ///
+ ///
+ private static object ConvertStringToValueType(Type valueType, string valueString) {
+ if (valueString == null) {
+ return null;
+ }
+ if (valueType == typeof(string)) {
+ return valueString;
+ }
+ TypeConverter converter = TypeDescriptor.GetConverter(valueType);
+ //LOG.Debug("No convertor for " + fieldType.ToString());
+ if (valueType == typeof(object) && valueString.Length > 0) {
+ //LOG.Debug("Parsing: " + valueString);
+ string[] values = valueString.Split(new Char[] { ':' });
+ //LOG.Debug("Type: " + values[0]);
+ //LOG.Debug("Value: " + values[1]);
+ Type fieldTypeForValue = Type.GetType(values[0], true);
+ //LOG.Debug("Type after GetType: " + fieldTypeForValue);
+ return ConvertStringToValueType(fieldTypeForValue, values[1]);
+ } else if (converter != null) {
+ return converter.ConvertFromInvariantString(valueString);
+ } else if (valueType.IsEnum) {
+ if (valueString.Length > 0) {
+ try {
+ return Enum.Parse(valueType, valueString);
+ } catch (ArgumentException ae) {
+ //LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
+ foreach (Enum enumValue in Enum.GetValues(valueType)) {
+ if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
+ //LOG.Info("Match found...");
+ return enumValue;
+ }
+ }
+ throw ae;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static string ConvertValueToString(Type valueType, object valueObject) {
+ if (valueObject == null) {
+ // If there is nothing, deliver nothing!
+ return "";
+ }
+ if (valueType == typeof(object)) {
+ // object to String, this is the hardest
+ // Format will be "FQTypename[,Assemblyname]:Value"
+
+ // Get the type so we can call ourselves recursive
+ Type objectType = valueObject.GetType();
+
+ // Get the value as string
+ string ourValue = ConvertValueToString(objectType, valueObject);
+
+ // Get the valuetype as string
+ string valueTypeName = objectType.FullName;
+ // Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing)
+ string assemblyName = objectType.Assembly.FullName;
+ // correct assemblyName, this also has version information etc.
+ if (assemblyName.StartsWith("Green")) {
+ assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
+ }
+ return String.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
+ } else {
+ TypeConverter converter = TypeDescriptor.GetConverter(valueType);
+ if (converter != null) {
+ return converter.ConvertToInvariantString(valueObject);
+ }
+ }
+ // All other types
+ return valueObject.ToString();
+ }
+
+
}
}
\ No newline at end of file