diff --git a/data/options/SharpDevelop-tools.xml b/data/options/SharpDevelop-tools.xml
index 2eb7879ed7..5f8dedf2bd 100644
--- a/data/options/SharpDevelop-tools.xml
+++ b/data/options/SharpDevelop-tools.xml
@@ -9,14 +9,14 @@
${TargetDir}
"${TargetPath}"
- ${NetSdkDir}bin\ILDasm.exe
+ ${SdkToolPath:ILDasm.exe}
IL Dasm
False
${TargetDir}
- ${NetSdkDir}bin\FUSLOGVW.exe
+ ${SdkToolPath:FUSLOGVW.exe}
Assembly Binding Log Viewer
False
diff --git a/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs b/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs
index 50bb62d6be..e8f49f3eed 100644
--- a/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs
+++ b/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs
@@ -15,6 +15,10 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Commands
{
+ ///
+ /// Provides tag to string mapping for SharpDevelop. Tags are mapped to strings by several methods
+ /// such as registry and resource files.
+ ///
public class SharpDevelopStringTagProvider : IStringTagProvider
{
readonly static string[] tags = new string[] {
@@ -26,8 +30,7 @@ namespace ICSharpCode.SharpDevelop.Commands
"CombineDir", "CombineFilename",
"SolutionDir", "SolutionFilename",
"Startuppath",
- "TaskService.Warnings", "TaskService.Errors", "TaskService.Messages",
- "NetSdkDir"
+ "TaskService.Warnings", "TaskService.Errors", "TaskService.Messages"
};
public string[] Tags {
@@ -70,8 +73,6 @@ namespace ICSharpCode.SharpDevelop.Commands
}
switch (tag.ToUpperInvariant()) {
- case "NETSDKDIR":
- return FileUtility.NetSdkInstallRoot;
case "ITEMPATH":
try {
return GetCurrentItemPath();
diff --git a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
index dc699a8254..cec37b67fc 100644
--- a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
+++ b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
@@ -227,52 +227,69 @@ namespace ICSharpCode.SharpDevelop.Commands
TaskService.BuildMessageViewCategory.AppendText(output + Environment.NewLine + "${res:XML.MainMenu.ToolMenu.ExternalTools.ExitedWithCode} " + p.ExitCode + Environment.NewLine);
}
+
+ ///
+ /// This handler gets called when a tool in the Tool menu is clicked on.
+ ///
+ /// The MenuCommand that sent the event.
+ /// Event arguments.
void ToolEvt(object sender, EventArgs e)
{
MenuCommand item = (MenuCommand)sender;
+ // TODO: ToolLoader.Tool should get a string indexor. Overloading List or making it a Dictionary would work.
for (int i = 0; i < ToolLoader.Tool.Count; ++i) {
- if (item.Text == ToolLoader.Tool[i].ToString()) {
- ExternalTool tool = (ExternalTool)ToolLoader.Tool[i];
+ if (item.Text != ToolLoader.Tool[i].ToString()) { continue; }
+ ExternalTool tool = (ExternalTool)ToolLoader.Tool[i];
+
+ // Set these to somewhat useful values in case StingParser.Parse() passes when being called on one of them.
+ string command = tool.Command;
+ string args = tool.Arguments;
+
+ // This needs it's own try/catch because if parsing these messages fail, the catch block after
+ // the second try would also throw because MessageService.ShowError() calls StringParser.Parse()
+ try {
+ command = StringParser.Parse(tool.Command);
+ args = StringParser.Parse(tool.Arguments);
+ } catch (Exception ex) {
+ MessageService.ShowError("${res:XML.MainMenu.ToolMenu.ExternalTools.ExecutionFailed} '" + ex.Message);
+ return;
+ }
- string command = StringParser.Parse(tool.Command);
- string args = StringParser.Parse(tool.Arguments);
+ if (tool.PromptForArguments) {
+ InputBox box = new InputBox();
+ box.Text = tool.MenuCommand;
+ box.Label.Text = ResourceService.GetString("XML.MainMenu.ToolMenu.ExternalTools.EnterArguments");
+ box.TextBox.Text = args;
+ if (box.ShowDialog() != DialogResult.OK)
+ return;
+ args = box.TextBox.Text;
+ }
- if (tool.PromptForArguments) {
- InputBox box = new InputBox();
- box.Text = tool.MenuCommand;
- box.Label.Text = ResourceService.GetString("XML.MainMenu.ToolMenu.ExternalTools.EnterArguments");
- box.TextBox.Text = args;
- if (box.ShowDialog() != DialogResult.OK)
- return;
- args = box.TextBox.Text;
+ try {
+ ProcessStartInfo startinfo;
+ if (args == null || args.Length == 0 || args.Trim('"', ' ').Length == 0) {
+ startinfo = new ProcessStartInfo(command);
+ } else {
+ startinfo = new ProcessStartInfo(command, args);
}
- try {
- ProcessStartInfo startinfo;
- if (args == null || args.Length == 0 || args.Trim('"', ' ').Length == 0) {
- startinfo = new ProcessStartInfo(command);
- } else {
- startinfo = new ProcessStartInfo(command, args);
- }
-
- startinfo.WorkingDirectory = StringParser.Parse(tool.InitialDirectory);
- if (tool.UseOutputPad) {
- startinfo.UseShellExecute = false;
- startinfo.RedirectStandardOutput = true;
- }
- Process process = new Process();
- process.EnableRaisingEvents = true;
- process.StartInfo = startinfo;
- if (tool.UseOutputPad) {
- process.Exited += new EventHandler(ProcessExitEvent);
- }
- process.Start();
- } catch (Exception ex) {
- MessageService.ShowError("${res:XML.MainMenu.ToolMenu.ExternalTools.ExecutionFailed} '" + command + " " + args + "'\n" + ex.Message);
+ startinfo.WorkingDirectory = StringParser.Parse(tool.InitialDirectory);
+ if (tool.UseOutputPad) {
+ startinfo.UseShellExecute = false;
+ startinfo.RedirectStandardOutput = true;
+ }
+ Process process = new Process();
+ process.EnableRaisingEvents = true;
+ process.StartInfo = startinfo;
+ if (tool.UseOutputPad) {
+ process.Exited += new EventHandler(ProcessExitEvent);
}
- break;
+ process.Start();
+ } catch (Exception ex) {
+ MessageService.ShowError("${res:XML.MainMenu.ToolMenu.ExternalTools.ExecutionFailed} '" + command + " " + args + "'\n" + ex.Message);
}
+ return;
}
}
}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/CreateKey.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/CreateKey.cs
index b25408a85e..b82aeac760 100644
--- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/CreateKey.cs
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/CreateKey.cs
@@ -15,10 +15,18 @@ using ICSharpCode.SharpDevelop.Gui.XmlForms;
namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
{
+ ///
+ /// A form that creates keys for assembly signing.
+ ///
public class CreateKeyForm : BaseSharpDevelopForm
{
string baseDirectory;
+ ///
+ /// Initializes the CreateKeyFrom() dialog setting the b ase directory for adding keys to the
+ /// location specified.
+ ///
+ /// The folder for placing the key.
public CreateKeyForm(string baseDirectory)
{
this.baseDirectory = baseDirectory;
@@ -54,6 +62,11 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
}
}
+ ///
+ /// Creates a key with the sn.exe utility.
+ ///
+ /// The path of the key to create.
+ /// True if the key was created correctly.
public static bool CreateKey(string keyPath)
{
if (File.Exists(keyPath)) {
@@ -97,9 +110,13 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
return true;
}
+ ///
+ /// Gets the path of the "strong named" executable. This is used to create keys for strongly signing
+ /// .NET assemblies.
+ ///
public static string StrongNameTool {
get {
- return Path.Combine(FileUtility.NetSdkInstallRoot, "bin\\sn.exe");
+ return FileUtility.GetSdkPath("sn.exe");
}
}
}
diff --git a/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs b/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs
index 97466a6bf0..80463dda5c 100644
--- a/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs
+++ b/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs
@@ -82,7 +82,7 @@ namespace ICSharpCode.SharpDevelop.Project.Converter
{
if (hintPath == null || hintPath.Length == 0)
return false;
- return !FileUtility.IsBaseDirectory(FileUtility.NETFrameworkInstallRoot, hintPath);
+ return !FileUtility.IsBaseDirectory(FileUtility.NetFrameworkInstallRoot, hintPath);
}
string rootNamespace;
diff --git a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs
index 23637281df..c93700ac3d 100644
--- a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs
+++ b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs
@@ -354,6 +354,7 @@ namespace ICSharpCode.SharpDevelop.Project
AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, true);
}
+ // TODO: Add XmlDocBloc to MSBuildError.AppendError()
void AppendError(string file, int lineNumber, int columnNumber, string code, string message, bool isWarning)
{
if (string.Equals(file, activeTaskName, StringComparison.InvariantCultureIgnoreCase)) {
@@ -365,7 +366,9 @@ namespace ICSharpCode.SharpDevelop.Project
}
if (isShortFileName && !File.Exists(file)) {
file = "";
- } else if (FileUtility.IsBaseDirectory(FileUtility.NETFrameworkInstallRoot, file)
+ }
+ //TODO: Do we have to check for other SDKs here.
+ else if (FileUtility.IsBaseDirectory(FileUtility.NetFrameworkInstallRoot, file)
|| FileUtility.IsBaseDirectory(FileUtility.ApplicationRootPath, file))
{
file = "";
diff --git a/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs b/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs
index 3f93ed5549..1868e6c68f 100644
--- a/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs
+++ b/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs
@@ -64,28 +64,68 @@ namespace ICSharpCode.Core
return null;
}
+ #region InstallRoot Properties
+
+
+
+ static string netFramework20InstallRoot = null;
+ ///
+ /// Location of the .NET Framework install root.
+ ///
+ public static string NetFrameworkInstallRoot {
+ get {
+ // Lazy load this.
+ if (netSdk20InstallRoot != null) { return netSdk20InstallRoot; }
+ netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot")
+ ?? string.Empty;
+ return netSdk20InstallRoot;
+ }
+ }
+
+ static string netSdk20InstallRoot = null;
///
- /// Gets the installation root of the .NET Framework (@"C:\Windows\Microsoft.NET\Framework\")
+ /// Location of the .NET 2.0 SDK install root.
///
- public static string NETFrameworkInstallRoot {
+ public static string NetSdk20InstallRoot {
get {
- return GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot") ?? string.Empty;
+ // Lazy load this.
+ if (netSdk20InstallRoot != null) { return netSdk20InstallRoot; }
+ netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0")
+ ?? string.Empty;
+ return netSdk20InstallRoot;
}
}
+ static string netSdk30InstallRoot = null;
///
- /// Gets the Windows Vista SDK installation root. If the Vista SDK is not installed, the
- /// .NET 2.0 SDK installation root is returned. If both are not installed, an empty string is returned.
+ /// Location of the .NET 3.0 SDK (Windows SDK 6.0) install root.
///
- public static string NetSdkInstallRoot {
+ public static string NetSdk30InstallRoot {
get {
- return GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder")
- ?? GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder")
- ?? GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0")
+ // Lazy load this.
+ if (netSdk30InstallRoot != null) { return netSdk30InstallRoot; }
+ netSdk30InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder")
?? string.Empty;
+ return netSdk30InstallRoot;
}
}
+ static string netSdk35InstallRoot = null;
+ ///
+ /// Location of the .NET 3.5 SDK (Windows SDK 6.0a) install root.
+ ///
+ public static string NetSdk35InstallRoot {
+ get {
+ // Lazy load this.
+ if (netSdk35InstallRoot != null) { return netSdk35InstallRoot; }
+ netSdk35InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder")
+ ?? string.Empty;
+ return netSdk35InstallRoot;
+ }
+ }
+
+ #endregion
+
public static string Combine(params string[] paths)
{
if (paths == null || paths.Length == 0) {
@@ -130,6 +170,32 @@ namespace ICSharpCode.Core
return result.ToString();
}
+ ///
+ /// Searches all the .net sdk bin folders and return the path of the
+ /// exe from the latest sdk.
+ ///
+ /// The EXE to search for.
+ /// The path of the executable.
+ ///
+ /// Thrown if the exe is not found.
+ ///
+ public static string GetSdkPath(string exeName) {
+ string execPath;
+ if (Directory.Exists(NetSdk35InstallRoot)) {
+ execPath = Path.Combine(NetSdk35InstallRoot + "\\bin", exeName);
+ if (File.Exists(execPath)) { return execPath; }
+ }
+ if (Directory.Exists(NetSdk30InstallRoot)) {
+ execPath = Path.Combine(NetSdk30InstallRoot + "\\bin", exeName);
+ if (File.Exists(execPath)) { return execPath; }
+ }
+ if (Directory.Exists(NetSdk20InstallRoot)) {
+ execPath = Path.Combine(NetSdk20InstallRoot + "\\bin", exeName);
+ if (File.Exists(execPath)) { return execPath; }
+ }
+ throw new FileNotFoundException(StringParser.Parse("${res:Fileutility.CantFindExecutableError}", new string[,] { {"EXECUTABLE", exeName} }));
+ }
+
///
/// Converts a given absolute path and a given base path to a path that leads
/// from the base path to the absoulte path. (as a relative path)
diff --git a/src/Main/Core/Project/Src/Services/StringParser/StringParser.cs b/src/Main/Core/Project/Src/Services/StringParser/StringParser.cs
index 9afb1d3d23..22c71c379d 100644
--- a/src/Main/Core/Project/Src/Services/StringParser/StringParser.cs
+++ b/src/Main/Core/Project/Src/Services/StringParser/StringParser.cs
@@ -14,7 +14,7 @@ using System.Text;
namespace ICSharpCode.Core
{
///
- /// this class parses internal ${xyz} tags of sd.
+ /// This class parses internal ${xyz} tags of #Develop.
/// All environment variables are avaible under the name env.[NAME]
/// where [NAME] represents the string under which it is avaiable in
/// the environment.
@@ -94,31 +94,6 @@ namespace ICSharpCode.Core
///
public static string Parse(string input, string[,] customTags)
{
- // Parse is a important method and should have good performance,
- // so we don't use an expensive Regex here.
-
- /* old code using regex:
- string output = input;
- if (input != null) {
- foreach (Match m in pattern.Matches(input)) {
- if (m.Length > 0) {
- string token = m.ToString();
- string propertyName = m.Groups[1].Captures[0].Value;
-
- string propertyValue = GetValue(propertyName, customTags);
-
- if (propertyValue != null) {
- if (m.Length == input.Length) {
- // safe a replace operation when input is a property on its own.
- return propertyValue;
- }
- output = output.Replace(token, propertyValue);
- }
- }
- }
- }
- return output;
- */
if (input == null)
return null;
int pos = 0;
@@ -170,9 +145,11 @@ namespace ICSharpCode.Core
static string GetValue(string propertyName, string[,] customTags)
{
+
+ // most properties start with res: in lowercase,
+ // so we can save 2 string allocations here, in addition to all the jumps
+ // All other prefixed properties {prefix:Key} shoulg get handled in the switch below.
if (propertyName.StartsWith("res:")) {
- // most properties start with res: in lowercase,
- // so we can safe 2 string allocations here
try {
return Parse(ResourceService.GetString(propertyName.Substring(4)), customTags);
} catch (ResourceNotFoundException) {
@@ -210,6 +187,8 @@ namespace ICSharpCode.Core
string prefix = propertyName.Substring(0, k);
propertyName = propertyName.Substring(k + 1);
switch (prefix.ToUpperInvariant()) {
+ case "SDKTOOLPATH":
+ return FileUtility.GetSdkPath(propertyName);
case "ADDINPATH":
foreach (AddIn addIn in AddInTree.AddIns) {
if (addIn.Manifest.Identities.ContainsKey(propertyName)) {