in src/Deprecated/Conversion/ProjectFileConverter.cs [425:702]
private void ConvertInMemoryToMSBuildProject()
{
// Make sure we were passed in non-empty source and destination project
// file names.
error.VerifyThrowArgument((this.oldProjectFile != null) && (this.oldProjectFile.Length > 0),
"MissingOldProjectFile");
// Make sure the source project file exists.
error.VerifyThrowArgument(File.Exists(oldProjectFile), "ProjectFileNotFound",
oldProjectFile);
Initialize();
// Load the old project file as an XML document.
XmlDocumentWithLocation oldProjectDocument = new XmlDocumentWithLocation();
oldProjectDocument.PreserveWhitespace = true;
TextReader oldProjectFileReader = new OldVSProjectFileReader(oldProjectFile);
try
{
// We have our own custom XML reader to read in the old VS7/Everett project
// file. This is because the VS7/Everett project file format supported
// having characters like <, >, &, etc. embedded inside XML attribute
// values, but the default XmlTextReader won't handle this.
using (XmlTextReader xmlReader = new XmlTextReader(oldProjectFileReader))
{
xmlReader.DtdProcessing = DtdProcessing.Ignore;
oldProjectDocument.Load(xmlReader);
}
}
catch (Exception e)
{
throw new InvalidProjectFileException(e.Message);
}
finally
{
oldProjectFileReader.Close();
}
// Get the top-level nodes from the XML.
XmlNodeList rootNodes = oldProjectDocument.ChildNodes;
XmlElementWithLocation visualStudioProjectElement = null;
// The XML parser will guarantee that we only have one real root element,
// but since XML comments may appear outside of the <VisualStudioProject> scope,
// it's possible to get more than one child node. Just find the first
// non-comment node. That should be the <VisualStudioProject> element.
foreach(XmlNode childNode in rootNodes)
{
if ((childNode.NodeType != XmlNodeType.Comment) &&
(childNode.NodeType != XmlNodeType.XmlDeclaration) &&
(childNode.NodeType != XmlNodeType.Whitespace))
{
visualStudioProjectElement = (XmlElementWithLocation) childNode;
break;
}
}
IElementLocation oldProjectDocumentLocation = ElementLocation.Create(oldProjectDocument.FullPath, 1, 1);
// Verify that we found a non-comment root node.
ProjectErrorUtilities.VerifyThrowInvalidProject(visualStudioProjectElement != null,
oldProjectDocumentLocation,
"NoRootProjectElement", VSProjectElements.visualStudioProject);
// If the root element is <Project>, then assume that this project is
// already in XMake format.
if (visualStudioProjectElement.Name == XMakeProjectStrings.project)
{
this.xmakeProject = ProjectRootElement.Open(oldProjectFile);
// For Whidbey project just need to set the "ToolsVersion" attribute for the main project file
// and remove imports like <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
// because the Fidalgo stuff is part of .NET Framework 3.5
// For upgraded workflow projects, the workflow targets need to reference the new v3.5 targets instead of v3.0 targets
// this change is required to fix the msbuild break when building workflow rules.
// e.g. before upgrade :<Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets" />
// after upgrade <Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.Targets" />
string oldToolsVersion = xmakeProject.ToolsVersion;
xmakeProject.ToolsVersion = XMakeProjectStrings.toolsVersion;
List<ProjectImportElement> listOfImportsToBeDeleted = new List<ProjectImportElement>();
List<ProjectImportElement> listOfWFImportsToBeDeleted = new List<ProjectImportElement>();
List<string> workflowImportsToAdd = new List<string>();
string workflowTargetsBasePath = @"$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\";
string workflowOldWhidbeyTargetsPath = workflowTargetsBasePath + @"v3.0\";
string workflowOldOrcasTargetsPath = workflowTargetsBasePath + @"v3.5\";
string workflowNewTargetsPath = @"$(MSBuildToolsPath)\";
bool removedWFWhidbeyTargets = false;
bool changedProject = false;
// Find matching imports but don't delete whilst enumerating else it will throw an error
foreach (ProjectImportElement nextImport in xmakeProject.Imports)
{
if (String.Compare(nextImport.Project, @"$(MSBuildBinPath)\Microsoft.WinFX.targets", StringComparison.OrdinalIgnoreCase) == 0)
{
listOfImportsToBeDeleted.Add(nextImport);
}
if (nextImport.Project.Contains(workflowOldWhidbeyTargetsPath))
{
listOfWFImportsToBeDeleted.Add(nextImport);
workflowImportsToAdd.Add(nextImport.Project.Replace(workflowOldWhidbeyTargetsPath, workflowNewTargetsPath));
removedWFWhidbeyTargets = true;
}
if (nextImport.Project.Contains(workflowOldOrcasTargetsPath))
{
listOfWFImportsToBeDeleted.Add(nextImport);
workflowImportsToAdd.Add(nextImport.Project.Replace(workflowOldOrcasTargetsPath, workflowNewTargetsPath));
}
}
// Now delete any matching imports
foreach (ProjectImportElement importToDelete in listOfWFImportsToBeDeleted)
{
this.xmakeProject.RemoveChild(importToDelete);
changedProject = true;
}
bool removedWinFXTargets = false;
foreach (ProjectImportElement importToDelete in listOfImportsToBeDeleted)
{
this.xmakeProject.RemoveChild(importToDelete);
removedWinFXTargets = true;
changedProject = true;
}
// If we removed WinFX targets this is a sparkle project and should use v3.0
if (removedWinFXTargets)
{
xmakeProject.AddProperty(XMakeProjectStrings.TargetFrameworkVersion, "v3.0");
changedProject = true;
}
//If we removed WFWhidbey imports, we should target this project to v3.0
if (removedWFWhidbeyTargets)
{
xmakeProject.AddProperty(XMakeProjectStrings.TargetFrameworkVersion, "v3.0");
changedProject = true;
}
// Re-add the workflow imports with the v4.0 targets.
foreach (string workflowImportToAdd in workflowImportsToAdd)
{
this.xmakeProject.AddImport(workflowImportToAdd);
changedProject = true;
}
// Find all the XAML files in the project and give them the custom attributes
// <Generator>MSBuild:Compile</Generator> (DevDiv Bugs bug 81222)
// <SubType>Designer</SubType> (DevDiv Bugs bug 82748)
// Find all references to old VC project files (.vcproj extension) and change the
// extension to .vcxproj instead. NOTE: we assume that the actual .vcproj -> .vcxproj
// conversion has already been / is being / will be done elsewhere.
// Dev10 Bug 557388
foreach (ProjectItemElement nextItem in xmakeProject.Items)
{
if ((!nextItem.ItemType.Equals("Reference", StringComparison.OrdinalIgnoreCase)) &&
(nextItem.Include.Trim().EndsWith(".xaml", StringComparison.OrdinalIgnoreCase)))
{
if (!nextItem.Metadata.Any(m => String.Equals(m.Name, "Generator", StringComparison.OrdinalIgnoreCase)))
{
nextItem.AddMetadata("Generator", "MSBuild:Compile");
changedProject = true;
}
if (!nextItem.Metadata.Any(m => String.Equals(m.Name, "SubType", StringComparison.OrdinalIgnoreCase)))
{
nextItem.AddMetadata("SubType", "Designer");
changedProject = true;
}
}
if (String.Equals(nextItem.ItemType, "ProjectReference", StringComparison.OrdinalIgnoreCase) &&
nextItem.Include.Trim().EndsWith(".vcproj", StringComparison.OrdinalIgnoreCase))
{
nextItem.Include = Path.ChangeExtension(nextItem.Include, ".vcxproj");
changedProject = true;
}
}
// DevDiv Bugs bug 100701: if we removed the Microsoft.WinFX.targets import,
// and if there is no ProjectTypeGuids property, add the WPF flavor GUID
if (removedWinFXTargets)
{
ProjectPropertyElement currentGuidsProperty = FindPropertyIfPresent(this.xmakeProject, XMakeProjectStrings.projectTypeGuids);
string newGuids = "{" + XMakeProjectStrings.wpfFlavorGuid + "}";
if (currentGuidsProperty == null || currentGuidsProperty.Value.Length == 0)
{
string currentGuids = String.Empty;
// To have a flavor GUID we need a base GUID.
if (oldProjectFile.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
{
currentGuids = "{" + XMakeProjectStrings.cSharpGuid + "}";
}
if (oldProjectFile.EndsWith(".vbproj", StringComparison.OrdinalIgnoreCase))
{
currentGuids = "{" + XMakeProjectStrings.visualBasicGuid + "}";
}
xmakeProject.AddProperty(XMakeProjectStrings.projectTypeGuids, newGuids + ";" + currentGuids);
changedProject = true;
}
}
// Fix up TargetFrameworkSubset
changedProject = FixTargetFrameworkSubset() || changedProject;
var hasFSharpSpecificConversions = FSharpSpecificConversions(true);
changedProject = hasFSharpSpecificConversions || changedProject;
changedProject = VBSpecificConversions() || changedProject;
// Do asset compat repair for any project that was previously a TV < 12.0
if (
String.IsNullOrEmpty(oldToolsVersion) ||
String.Equals(oldToolsVersion, "3.5", StringComparison.OrdinalIgnoreCase) ||
String.Equals(oldToolsVersion, "4.0", StringComparison.OrdinalIgnoreCase)
)
{
changedProject = DoRepairForAssetCompat() || changedProject;
}
// Remove any default fully qualified Code Analysis paths.
// DevDiv bug 63415
changedProject = FixCodeAnalysisPaths() || changedProject;
if (hasFSharpSpecificConversions && !String.IsNullOrEmpty(oldToolsVersion))
{
// for Bug 609702:A ToolsVersion=12.0 F# project fails to load in VS 2012
// for F# project after upgrade we restore previous value of ToolsVersion so Dev11 still can load upgraded project
// however if old ToolsVersion as 3.5 - it will be upgraded to 4.0 to avoid any unexpected behavior in Dev10\Dev11
xmakeProject.ToolsVersion = String.Equals(oldToolsVersion, "3.5", StringComparison.OrdinalIgnoreCase) ? "4.0" : oldToolsVersion;
}
else if (this.isMinorUpgrade ||
(!changedProject &&
!String.IsNullOrEmpty(oldToolsVersion) &&
!String.Equals(oldToolsVersion, "3.5", StringComparison.OrdinalIgnoreCase))
)
{
// If it's minor upgrade, or nothing changed and the project was already TV 4.0 or higher,
// set the ToolsVersion back to its old value.
xmakeProject.ToolsVersion = oldToolsVersion;
}
}
else
{
// OK, we have to start with a fresh project and assemble it
this.xmakeProject = ProjectRootElement.Create();
// This root node must be a <VisualStudioProject> node.
ProjectErrorUtilities.VerifyThrowInvalidProject(visualStudioProjectElement.Name ==
VSProjectElements.visualStudioProject,
visualStudioProjectElement.Location, "UnrecognizedElement", visualStudioProjectElement.Name);
// Set the "DefaultTargets" attribute for the main project file.
if (!isUserFile)
{
xmakeProject.DefaultTargets = XMakeProjectStrings.defaultTargets;
}
// Set the "ToolsVersion" attribute for the main project file.
if (!isUserFile)
{
xmakeProject.ToolsVersion = XMakeProjectStrings.toolsVersion;
}
// Process the <VisualStudioProject> element in the source project file,
// adding the necessary stuff to the XMake project.
this.ProcessVisualStudioProjectElement(visualStudioProjectElement);
}
}