Services
ConfigService.cs
// Copyright 2003-2008 The AnkhSVN Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.Win32;
using Ankh.UI;
using Ankh.VS;
namespace Ankh.Configuration
{
///
/// Contains functions used to load and save configuration data.
///
[GlobalService(typeof(IAnkhConfigurationService))]
sealed clast ConfigService : AnkhService, IAnkhConfigurationService
{
readonly object _lock = new object();
AnkhConfig _instance;
public ConfigService(IAnkhServiceProvider context)
: base(context)
{
}
public AnkhConfig Instance
{
get { return _instance ?? (_instance = GetNewConfigInstance()); }
}
IAnkhSolutionSettings _settings;
IAnkhSolutionSettings Settings
{
get { return _settings ?? (_settings = GetService()); }
}
///
/// Loads the Ankh configuration file from the given path.
///
/// A Config object.
public AnkhConfig GetNewConfigInstance()
{
AnkhConfig instance = new AnkhConfig();
SetDefaultsFromRegistry(instance);
SetSettingsFromRegistry(instance);
return instance;
}
void IAnkhConfigurationService.LoadConfig()
{
_instance = GetNewConfigInstance();
}
///
/// Loads the default config file. Used as a fallback if the
/// existing config file cannot be loaded.
///
///
public void LoadDefaultConfig()
{
lock (_lock)
{
_instance = new AnkhConfig();
SetDefaultsFromRegistry(_instance);
}
}
void SetDefaultsFromRegistry(AnkhConfig config)
{
using (RegistryKey reg = OpenHKLMCommonKey("Configuration"))
{
if (reg != null)
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(config))
{
string value = reg.GetValue(pd.Name, null) as string;
if (value != null)
try
{
pd.SetValue(config, pd.Converter.ConvertFromInvariantString(value));
}
catch { }
}
}
using (RegistryKey reg = OpenHKLMKey("Configuration"))
{
if (reg != null)
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(config))
{
string value = reg.GetValue(pd.Name, null) as string;
if (value != null)
try
{
pd.SetValue(config, pd.Converter.ConvertFromInvariantString(value));
}
catch { }
}
}
}
void SetSettingsFromRegistry(AnkhConfig config)
{
using (RegistryKey reg = OpenHKCUKey("Configuration"))
{
if (reg == null)
return;
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(config))
{
string value = reg.GetValue(pd.Name, null) as string;
if (pd.Name == "DiffExePaths")
{
RegistryKey diffRegKey = OpenHKCUKey("Configuration");
diffRegKey = diffRegKey.OpenSubKey(pd.Name);
if (diffRegKey != null)
{
config.DiffExePaths.Clear();
foreach (string regKeyName in diffRegKey.GetValueNames())
{
string regValue = diffRegKey.GetValue(regKeyName) as string;
try
{
ExtToolDefinition extToolDef = new ExtToolDefinition();
extToolDef.extension = regKeyName;
extToolDef.exePath = regValue;
config.DiffExePaths.Add(extToolDef);
}
catch
{
}
}
}
}
else if (pd.Name == "MergeExePaths")
{
RegistryKey mergeRegKey = OpenHKCUKey("Configuration");
mergeRegKey = mergeRegKey.OpenSubKey(pd.Name);
if (mergeRegKey != null)
{
config.MergeExePaths.Clear();
foreach (string regKeyName in mergeRegKey.GetValueNames())
{
string regValue = mergeRegKey.GetValue(regKeyName) as string;
try
{
ExtToolDefinition extToolDef = new ExtToolDefinition();
extToolDef.extension = regKeyName;
extToolDef.exePath = regValue;
config.MergeExePaths.Add(extToolDef);
}
catch
{
}
}
}
}
else if (value != null)
try
{
pd.SetValue(config, pd.Converter.ConvertFromInvariantString(value));
}
catch { }
}
}
}
///
/// Saves the supplied Config object
///
///
public void SaveConfig(AnkhConfig config)
{
if (config == null)
throw new ArgumentNullException("config");
lock (_lock)
{
AnkhConfig defaultConfig = new AnkhConfig();
SetDefaultsFromRegistry(defaultConfig);
using (RegistryKey reg = OpenHKCUKey("Configuration"))
{
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(defaultConfig);
foreach (PropertyDescriptor pd in pdc)
{
object value = pd.GetValue(config);
// Set the value only if it is already set previously, or if it's different from the default
if (!pd.ShouldSerializeValue(config) && !pd.ShouldSerializeValue(defaultConfig))
{
reg.DeleteValue(pd.Name, false);
}
else
{
if (value.GetType() == typeof(List))
{
List myExtToolList = value as List;
reg.CreateSubKey(pd.Name);
RegistryKey extToolReg = OpenHKCUKey("Configuration");
extToolReg = extToolReg.OpenSubKey(pd.Name, true);
if (extToolReg != null)
{
foreach (string extToolDef in extToolReg.GetValueNames())
{
extToolReg.DeleteValue(extToolDef, false);
}
foreach (ExtToolDefinition extTool in myExtToolList)
{
extToolReg.SetValue(extTool.extension, extTool.exePath);
}
}
}
else
{
reg.SetValue(pd.Name, pd.Converter.ConvertToInvariantString(value));
}
}
}
}
}
}
RegistryKey OpenHKLMCommonKey(string subKey)
{
if (string.IsNullOrEmpty(subKey))
throw new ArgumentNullException("subKey");
// Opens the specified key or returns null
return Registry.LocalMachine.OpenSubKey("SOFTWARE\\AnkhSVN\\AnkhSVN\\Global\\" + subKey, RegistryKeyPermissionCheck.ReadSubTree);
}
RegistryKey OpenHKLMKey(string subKey)
{
if (string.IsNullOrEmpty(subKey))
throw new ArgumentNullException("subKey");
// Opens the specified key or returns null
return Registry.LocalMachine.OpenSubKey("SOFTWARE\\AnkhSVN\\AnkhSVN\\" + Settings.RegistryHiveSuffix + "\\" + subKey, RegistryKeyPermissionCheck.ReadSubTree);
}
///
/// Opens or creates the HKCU key with the specified name
///
///
///
RegistryKey OpenHKCUKey(string subKey)
{
if (string.IsNullOrEmpty(subKey))
throw new ArgumentNullException("subKey");
// Opens or creates the specified key
return Registry.CurrentUser.CreateSubKey("SOFTWARE\\AnkhSVN\\AnkhSVN\\" + Settings.RegistryHiveSuffix + "\\" + subKey);
}
#region IAnkhConfigurationService Members
RegistryKey IAnkhConfigurationService.OpenUserInstanceKey(string subKey)
{
return OpenHKCUKey(subKey);
}
RegistryKey IAnkhConfigurationService.OpenInstanceKey(string subKey)
{
return OpenHKLMKey(subKey);
}
RegistryKey IAnkhConfigurationService.OpenGlobalKey(string subKey)
{
return OpenHKLMCommonKey(subKey);
}
///
/// Gets the recent log messages.
///
///
public RegistryLifoList GetRecentLogMessages()
{
return new RegistryLifoList(Context, "RecentLogMessages", 32);
}
///
/// Gets the recent Repository Urls
///
///
public RegistryLifoList GetRecentReposUrls()
{
return new RegistryLifoList(Context, "RecentRepositoryUrls", 32);
}
public void SaveColumnsWidths(Type controlType, IDictionary widths)
{
if (controlType == null)
throw new ArgumentNullException("controlType");
if (widths == null || widths.Count == 0)
return;
SaveNumberValues("ColumnWidths", controlType.FullName, widths);
}
public IDictionary GetColumnWidths(Type controlType)
{
if (controlType == null)
throw new ArgumentNullException("controlType");
return GetNumberValues("ColumnWidths", controlType.FullName);
}
public void SaveWindowPlacement(Type controlType, IDictionary placement)
{
if (controlType == null)
throw new ArgumentNullException("controlType");
SaveNumberValues("WindowPlacements", controlType.FullName, placement);
}
public IDictionary GetWindowPlacement(Type controlType)
{
if (controlType == null)
throw new ArgumentNullException("controlType");
return GetNumberValues("WindowPlacements", controlType.FullName);
}
void SaveNumberValues(string regKey, string subKey, IDictionary values)
{
if (string.IsNullOrEmpty(regKey))
throw new ArgumentNullException("regKey");
if (string.IsNullOrEmpty(subKey))
throw new ArgumentNullException("subKey");
if (values == null)
throw new ArgumentNullException("values");
lock (_lock)
{
subKey = regKey + "\\" + subKey;
using (RegistryKey reg = OpenHKCUKey(subKey))
{
if (reg == null)
return;
foreach (KeyValuePair item in values)
{
if (item.Value 0)
values.Add(item, width);
}
}
}
return values;
}
public bool GetWarningBool(AnkhWarningBool ankhWarningBool)
{
using (RegistryKey rk = OpenHKCUKey("Warnings\\Bools"))
{
if (rk == null)
return false;
object v = rk.GetValue(ankhWarningBool.ToString());
if (!(v is int))
return false;
return ((int)v) != 0;
}
}
public void SetWarningBool(AnkhWarningBool ankhWarningBool, bool value)
{
using (RegistryKey rk = OpenHKCUKey("Warnings\\Bools"))
{
if (rk == null)
return;
if (value)
rk.SetValue(ankhWarningBool.ToString(), 1);
else
rk.DeleteValue(ankhWarningBool.ToString());
}
}
#endregion
#region IAnkhConfigurationService Members
public RegistryKey OpenVSInstanceKey(string name)
{
RegistryKey rootKey = null;
ILocalRegistry4 lr4 = GetService(typeof(SLocalRegistry));
if (lr4 == null)
return null;
uint type;
const uint VsLocalRegistryRootHandle_CURRENT_USER = unchecked((uint)-2147483647);
string root;
if (!VSErr.Succeeded(lr4.GetLocalRegistryRootEx(2 /* _VsLocalRegistryType.Configuration */, out type, out root)))
return null;
rootKey = ((type == VsLocalRegistryRootHandle_CURRENT_USER) ? Registry.CurrentUser : Registry.LocalMachine).OpenSubKey(root);
if (rootKey == null)
return null;
else if (string.IsNullOrEmpty(name))
return rootKey;
using (rootKey)
{
return rootKey.OpenSubKey(name);
}
}
public RegistryKey OpenVSUserKey(string name)
{
RegistryKey rootKey = null;
ILocalRegistry4 lr4 = GetService(typeof(SLocalRegistry));
if (lr4 == null)
return null;
uint type;
const uint VsLocalRegistryRootHandle_CURRENT_USER = unchecked((uint)-2147483647);
string root;
if (!VSErr.Succeeded(lr4.GetLocalRegistryRootEx(1 /* _VsLocalRegistryType.UserSettings */, out type, out root)))
return null;
rootKey = ((type == VsLocalRegistryRootHandle_CURRENT_USER) ? Registry.CurrentUser : Registry.LocalMachine).OpenSubKey(root);
if (rootKey == null)
return null;
else if (string.IsNullOrEmpty(name))
return rootKey;
using (rootKey)
{
return rootKey.OpenSubKey(name);
}
}
#endregion
}
}