Skip to content
Browse files

Handle error conditions when .NET 3.5 is not installed and the user t…

…ries to open/build .NET 2.0/3.0/3.5 projects.
  • Loading branch information...
1 parent abfd457 commit 69759876bcf07cd4958af13a25f9d3fa1f800d98 @dgrunwald dgrunwald committed Mar 1, 2012
View
8 src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs
@@ -109,7 +109,13 @@ public override void StartBuild(ProjectBuildOptions options, IBuildFeedbackSink
public override IEnumerable<CompilerVersion> GetAvailableCompilerVersions()
{
- return new[] { msbuild20, msbuild35, msbuild40 };
+ List<CompilerVersion> versions = new List<CompilerVersion>();
+ if (DotnetDetection.IsDotnet35SP1Installed()) {
+ versions.Add(msbuild20);
+ versions.Add(msbuild35);
+ }
+ versions.Add(msbuild40);
+ return versions;
}
/*
View
2 src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -367,6 +367,7 @@
<Compile Include="Src\Project\ProjectStartException.cs" />
<Compile Include="Src\Project\ProjectLoadException.cs" />
<Compile Include="Src\Project\ProjectPropertyChangedEventArgs.cs" />
+ <Compile Include="Src\Project\ProjectUpgradeException.cs" />
<Compile Include="Src\Project\Solution\Project_TypeGuids.cs" />
<Compile Include="Src\Project\TargetFramework.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />
@@ -794,6 +795,7 @@
<Compile Include="Src\Gui\Dialogs\ReferenceDialog\DiscoveryNetworkCredential.cs" />
<Compile Include="Src\Services\ProjectService\ProjectLoader.cs" />
<Compile Include="Src\Services\WebProjectService\WebProjectService.cs" />
+ <Compile Include="Src\Util\DotnetDetection.cs" />
<Compile Include="Src\Util\FakeXmlViewContent.cs" />
<Compile Include="Src\Util\ReactiveExtensions.cs" />
<Compile Include="Src\Util\TreeNode.cs" />
View
2 src/Main/Base/Project/Src/Gui/Dialogs/NewProjectDialog.cs
@@ -164,7 +164,7 @@ protected void CategoryChange(object sender, TreeViewEventArgs e)
targetFrameworkComboBox.Items.Clear();
if (categoryTreeView.SelectedNode != null) {
foreach (TargetFramework fx in TargetFramework.TargetFrameworks) {
- if (fx.DisplayName == null)
+ if (fx.DisplayName == null || !fx.IsAvailable())
continue;
foreach (TemplateItem item in ((Category)categoryTreeView.SelectedNode).Templates) {
if (item.Template.HasSupportedTargetFrameworks && item.Template.SupportsTargetFramework(fx)) {
View
16 src/Main/Base/Project/Src/Project/CompilableProject.cs
@@ -551,7 +551,13 @@ protected virtual void AddOrRemoveExtensions()
public virtual IEnumerable<CompilerVersion> GetAvailableCompilerVersions()
{
- return new[] { msbuild20, msbuild35, msbuild40 };
+ List<CompilerVersion> versions = new List<CompilerVersion>();
+ if (DotnetDetection.IsDotnet35SP1Installed()) {
+ versions.Add(msbuild20);
+ versions.Add(msbuild35);
+ }
+ versions.Add(msbuild40);
+ return versions;
}
public virtual void UpgradeProject(CompilerVersion newVersion, TargetFramework newFramework)
@@ -560,6 +566,14 @@ public virtual void UpgradeProject(CompilerVersion newVersion, TargetFramework n
lock (SyncRoot) {
TargetFramework oldFramework = this.CurrentTargetFramework;
if (newVersion != null && GetAvailableCompilerVersions().Contains(newVersion)) {
+ string newToolsVersion = newVersion.MSBuildVersion.Major + "." + newVersion.MSBuildVersion.Minor;
+ if (!MSBuildProjectCollection.ContainsToolset(newToolsVersion)) {
+ string errorMessage = "MSBuild Tools version '" + newToolsVersion + "' is not available.";
+ if (newToolsVersion == "2.0" || newToolsVersion == "3.5") {
+ errorMessage += Environment.NewLine + "Please install the .NET Framework 3.5 SP1.";
+ }
+ throw new ProjectUpgradeException(errorMessage);
+ }
SetToolsVersion(newVersion.MSBuildVersion.Major + "." + newVersion.MSBuildVersion.Minor);
}
if (newFramework != null) {
View
2 src/Main/Base/Project/Src/Project/Converter/IUpgradableProject.cs
@@ -43,6 +43,7 @@ public interface IUpgradableProject
/// </summary>
/// <param name="newVersion">The new compiler version. If this property is null, the compiler version is not changed.</param>
/// <param name="newFramework">The new target framework. If this property is null, the target framework is not changed.</param>
+ /// <exception cref="ProjectUpgradeException">Upgrading the project failed.</exception>
void UpgradeProject(CompilerVersion newVersion, TargetFramework newFramework);
}
@@ -56,6 +57,7 @@ public virtual IEnumerable<TargetFramework> GetSupportedTargetFrameworks()
return from fx in TargetFramework.TargetFrameworks
where fx.MinimumMSBuildVersion != null
where MSBuildVersion >= fx.MinimumMSBuildVersion
+ where fx.IsAvailable()
select fx;
}
View
23 src/Main/Base/Project/Src/Project/Converter/UpgradeView.xaml.cs
@@ -7,7 +7,6 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
-
using ICSharpCode.Core.Presentation;
namespace ICSharpCode.SharpDevelop.Project.Converter
@@ -130,16 +129,13 @@ void UpdateTargetFrameworkComboBox()
// -> available target frameworks is the intersection of all compiler's target framework,
// and "Do not change" is always available
- var supportedTargetFrameworks =
+ availableFrameworks = (
from Entry entry in listView.SelectedItems
where entry.CompilerVersion != null
- select entry.CompilerVersion.GetSupportedTargetFrameworks();
+ from fx in entry.CompilerVersion.GetSupportedTargetFrameworks()
+ select fx
+ ).Distinct().ToList();
- if (supportedTargetFrameworks.Any()) {
- availableFrameworks = supportedTargetFrameworks.Aggregate((a, b) => a.Intersect(b)).ToList();
- } else {
- availableFrameworks = new List<TargetFramework>();
- }
doNotChangeAllowed = true;
} else {
// Specific compiler version is selected
@@ -181,7 +177,8 @@ void UpdateTargetFrameworkComboBox()
TargetFramework oldSelectedFramework = newFrameworkComboBox.SelectedValue as TargetFramework;
if (!newFrameworkSelectionSetByUser || oldSelectedFramework == null) {
newFrameworkSelectionSetByUser = false;
- newFrameworkComboBox.SelectedValue = frameworkUsedByAllProjects;
+ if (availableFrameworks.Contains(frameworkUsedByAllProjects))
+ newFrameworkComboBox.SelectedValue = frameworkUsedByAllProjects;
}
newFrameworkSelectionChangingByCode = false;
UpdateConvertButtonEnabled();
@@ -233,8 +230,14 @@ void convertButton_Click(object sender, RoutedEventArgs e)
foreach (Entry entry in listView.SelectedItems) {
- entry.UpgradeProject(selectedCompiler, selectedFramework);
+ try {
+ entry.UpgradeProject(selectedCompiler, selectedFramework);
+ } catch (ProjectUpgradeException ex) {
+ Core.MessageService.ShowError("Cannot upgrade '" + entry.Name + "': " + ex.Message);
+ break;
+ }
}
+
solution.Save();
UpdateCompilerComboBox();
}
View
52 src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs
@@ -123,6 +123,7 @@ protected void SetToolsVersion(string newToolsVersion)
projectFile.ToolsVersion = newToolsVersion;
userProjectFile.ToolsVersion = newToolsVersion;
});
+
if (MinimumSolutionVersionChanged != null)
MinimumSolutionVersionChanged(this, EventArgs.Empty);
}
@@ -1207,7 +1208,13 @@ public MSBuildBasedProject(ProjectLoadInformation loadInformation)
this.Name = loadInformation.ProjectName;
isLoading = true;
try {
- LoadProjectInternal(loadInformation);
+ try {
+ LoadProjectInternal(loadInformation);
+ } catch (InvalidProjectFileException ex) {
+ if (!(ex.ErrorCode == "MSB4132" && UpgradeToolsVersion(loadInformation))) {
+ throw;
+ }
+ }
} catch (InvalidProjectFileException ex) {
LoggingService.Warn(ex);
LoggingService.Warn("ErrorCode = " + ex.ErrorCode);
@@ -1217,13 +1224,56 @@ public MSBuildBasedProject(ProjectLoadInformation loadInformation)
}
}
+ const string autoUpgradeNewToolsVersion = "4.0";
+
+ bool UpgradeToolsVersion(ProjectLoadInformation loadInformation)
+ {
+ if (loadInformation.upgradeToolsVersion != null)
+ return false;
+ if (!CanUpgradeToolsVersion())
+ return false;
+ loadInformation.ProgressMonitor.ShowingDialog = true;
+ StringTagPair[] tags = {
+ new StringTagPair("ProjectName", loadInformation.ProjectName),
+ new StringTagPair("OldToolsVersion", projectFile.ToolsVersion),
+ new StringTagPair("NewToolsVersion", autoUpgradeNewToolsVersion)
+ };
+ string message = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Project.UpgradeView.UpdateOnLoadDueToMissingMSBuild}", tags);
+ string upgradeButton = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Project.UpgradeView.UpdateToMSBuildButton}", tags);
+ int result = MessageService.ShowCustomDialog(
+ "${res:ICSharpCode.SharpDevelop.Project.UpgradeView.Title}",
+ message,
+ 0, 1, upgradeButton, "${res:Global.CancelButtonText}");
+ loadInformation.ProgressMonitor.ShowingDialog = false;
+ if (result == 0) {
+ loadInformation.upgradeToolsVersion = true;
+ LoadProjectInternal(loadInformation);
+ return true;
+ } else {
+ loadInformation.upgradeToolsVersion = false;
+ return false;
+ }
+ }
+
+ bool CanUpgradeToolsVersion()
+ {
+ if (projectFile == null)
+ return false;
+ if (string.IsNullOrEmpty(projectFile.ToolsVersion))
+ return true;
+ return projectFile.ToolsVersion == "2.0" || projectFile.ToolsVersion == "3.5";
+ }
+
void LoadProjectInternal(ProjectLoadInformation loadInformation)
{
this.projectCollection = loadInformation.ParentSolution.MSBuildProjectCollection;
this.FileName = loadInformation.FileName;
this.ActivePlatform = loadInformation.Platform;
projectFile = ProjectRootElement.Open(loadInformation.FileName, projectCollection);
+ if (loadInformation.upgradeToolsVersion == true && CanUpgradeToolsVersion()) {
+ projectFile.ToolsVersion = autoUpgradeNewToolsVersion;
+ }
string userFileName = loadInformation.FileName + ".user";
if (File.Exists(userFileName)) {
View
7 src/Main/Base/Project/Src/Project/MSBuildEngine/MSBuildEngine.cs
@@ -265,7 +265,12 @@ void StartBuild()
}
if (projectMinimumSolutionVersion <= Solution.SolutionVersionVS2008) {
- BuildWorkerManager.MSBuild35.RunBuildJob(job, loggerChain, OnDone, feedbackSink.ProgressMonitor.CancellationToken);
+ if (DotnetDetection.IsDotnet35SP1Installed()) {
+ BuildWorkerManager.MSBuild35.RunBuildJob(job, loggerChain, OnDone, feedbackSink.ProgressMonitor.CancellationToken);
+ } else {
+ loggerChain.HandleError(new BuildError(job.ProjectFileName, ".NET 3.5 SP1 is required to build this project."));
+ OnDone(false);
+ }
} else {
BuildWorkerManager.MSBuild40.RunBuildJob(job, loggerChain, OnDone, feedbackSink.ProgressMonitor.CancellationToken);
}
View
2 src/Main/Base/Project/Src/Project/ProjectLoadInformation.cs
@@ -19,6 +19,8 @@ public class ProjectLoadInformation
public IList<ProjectSection> ProjectSections {get; set;}
internal string Guid { get; set; }
+ internal bool? upgradeToolsVersion;
+
Gui.IProgressMonitor progressMonitor = new Gui.DummyProgressMonitor();
/// <summary>
View
31 src/Main/Base/Project/Src/Project/ProjectUpgradeException.cs
@@ -0,0 +1,31 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Runtime.Serialization;
+
+namespace ICSharpCode.SharpDevelop.Project
+{
+ /// <summary>
+ /// This exception occurs when upgrading a project fails.
+ /// </summary>
+ [Serializable]
+ public class ProjectUpgradeException : Exception
+ {
+ public ProjectUpgradeException() : base()
+ {
+ }
+
+ public ProjectUpgradeException(string message) : base(message)
+ {
+ }
+
+ public ProjectUpgradeException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected ProjectUpgradeException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
View
22 src/Main/Base/Project/Src/Project/TargetFramework.cs
@@ -9,7 +9,9 @@ public class TargetFramework
{
public readonly static TargetFramework Net20 = new TargetFramework("v2.0", ".NET Framework 2.0") {
SupportedRuntimeVersion = "v2.0.50727",
- MinimumMSBuildVersion = new Version(2, 0)
+ MinimumMSBuildVersion = new Version(2, 0),
+ // .NET 2.0/3.0/3.5 can only be used if .NET 3.5 SP1 is installed
+ IsAvailable = DotnetDetection.IsDotnet35SP1Installed
};
public readonly static TargetFramework Net30 = new TargetFramework("v3.0", ".NET Framework 3.0") {
SupportedRuntimeVersion = "v2.0.50727",
@@ -28,7 +30,8 @@ public class TargetFramework
BasedOn = Net35,
MinimumMSBuildVersion = new Version(4, 0),
SupportedSku = ".NETFramework,Version=v4.0",
- RequiresAppConfigEntry = true
+ RequiresAppConfigEntry = true,
+ IsAvailable = DotnetDetection.IsDotnet40Installed
};
public readonly static TargetFramework Net40Client = new ClientProfileTargetFramework(Net40) {
BasedOn = Net35Client
@@ -38,7 +41,8 @@ public class TargetFramework
MinimumMSBuildVersion = new Version(4, 0),
SupportedRuntimeVersion = "v4.0",
SupportedSku = ".NETFramework,Version=v4.5",
- RequiresAppConfigEntry = true
+ RequiresAppConfigEntry = true,
+ IsAvailable = DotnetDetection.IsDotnet45Installed
};
public readonly static TargetFramework Net45Client = new ClientProfileTargetFramework(Net45) {
BasedOn = Net40Client
@@ -66,6 +70,12 @@ public TargetFramework(string name, string displayName)
this.name = name;
this.displayName = displayName;
this.SupportedRuntimeVersion = name;
+ this.IsAvailable = delegate {
+ if (this.BasedOn != null)
+ return this.BasedOn.IsAvailable();
+ else
+ return true;
+ };
}
public string Name {
@@ -77,6 +87,11 @@ public TargetFramework(string name, string displayName)
}
/// <summary>
+ /// Function that determines if this target framework is available.
+ /// </summary>
+ public Func<bool> IsAvailable { get; set; }
+
+ /// <summary>
/// Supported runtime version string for app.config
/// </summary>
public string SupportedRuntimeVersion { get; set; }
@@ -128,6 +143,7 @@ public ClientProfileTargetFramework(TargetFramework fullFramework)
this.FullFramework = fullFramework;
this.SupportedRuntimeVersion = fullFramework.SupportedRuntimeVersion;
this.MinimumMSBuildVersion = fullFramework.MinimumMSBuildVersion;
+ this.IsAvailable = fullFramework.IsAvailable;
if (fullFramework.SupportedSku != null)
this.SupportedSku = fullFramework.SupportedSku + ",Profile=Client";
else
View
29 src/Main/Base/Project/Src/Util/DotnetDetection.cs
@@ -0,0 +1,29 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using Microsoft.Win32;
+
+namespace ICSharpCode.SharpDevelop
+{
+ public class DotnetDetection
+ {
+ public static bool IsDotnet35SP1Installed()
+ {
+ using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5")) {
+ return key != null && (key.GetValue("SP") as int?) >= 1;
+ }
+ }
+
+ public static bool IsDotnet40Installed()
+ {
+ return true; // required for SD to run
+ }
+
+ public static bool IsDotnet45Installed()
+ {
+ Version dotnet45Beta = new Version(4, 0, 30319, 17379);
+ return Environment.Version >= dotnet45Beta;
+ }
+ }
+}

0 comments on commit 6975987

Please sign in to comment.
Something went wrong with that request. Please try again.