├── .gitignore ├── ConvertToMsBuildSdk ├── App.config ├── AssemblyInfo.fs ├── ConvertToMsBuildSdk.fsproj ├── Program.fs └── packages.config ├── DNTools.sln └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.suo 3 | *.cache 4 | *.ncrunchsolution 5 | *.dgml 6 | bin 7 | obj 8 | packages 9 | .vs 10 | *~ 11 | all.userprefs 12 | *.mdb 13 | -------------------------------------------------------------------------------- /ConvertToMsBuildSdk/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ConvertToMsBuildSdk/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace ConvertToMsBuildSdk.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /ConvertToMsBuildSdk/ConvertToMsBuildSdk.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ConvertToMsBuildSdk/Program.fs: -------------------------------------------------------------------------------- 1 |  2 | open System.IO 3 | open System.Linq 4 | open System.Xml.Linq 5 | 6 | #nowarn "0077" // op_Explicit 7 | let inline (!>) (x : ^a) : ^b = (((^a or ^b) : (static member op_Explicit : ^a -> ^b) x)) 8 | 9 | 10 | let NsMsBuild = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003") 11 | let NsNone = XNamespace.None 12 | 13 | 14 | 15 | let convertPackageConfig (projectFile : FileInfo) = 16 | let packageFileName = projectFile.Directory.GetFiles("packages.config").SingleOrDefault() 17 | if packageFileName |> isNull |> not then 18 | let xdoc = XDocument.Load (packageFileName.FullName) 19 | packageFileName.Delete() 20 | 21 | let pkgs = xdoc.Descendants(NsNone + "package") 22 | |> Seq.map (fun x -> XElement(NsNone + "PackageReference", 23 | XAttribute(NsNone + "Include", (!> x.Attribute(NsNone + "id") : string)), 24 | XAttribute(NsNone + "Version", (!> x.Attribute(NsNone + "version") : string)))) 25 | XElement(NsNone + "ItemGroup", pkgs) 26 | else 27 | null 28 | 29 | 30 | 31 | // http://www.natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/ 32 | let convertProject (projectFile : FileInfo) = 33 | let projectFileName = projectFile.Name |> Path.GetFileNameWithoutExtension 34 | let xdoc = XDocument.Load (projectFile.FullName) 35 | 36 | let rewrite (xel : XElement) = 37 | if xel |> isNull |> not then 38 | XElement(NsNone + xel.Name.LocalName, 39 | xel.Attributes() |> Seq.map (fun x -> XAttribute(NsNone + x.Name.LocalName, x.Value)), 40 | xel.Nodes() |> Seq.filter (fun x -> x.NodeType = System.Xml.XmlNodeType.Text)) 41 | else 42 | null 43 | 44 | // https://docs.microsoft.com/en-us/dotnet/standard/frameworks 45 | let xTargetFx = match !> xdoc.Descendants(NsMsBuild + "TargetFrameworkVersion").First() : string with 46 | | "v3.5" -> "net35" 47 | | "v4.0" -> "net40" 48 | | "v4.5" -> "net45" 49 | | "v4.5.1" -> "net451" 50 | | "v4.5.2" -> "net452" 51 | | "v4.6" -> "net46" 52 | | "v4.6.1" -> "net461" 53 | | "v4.6.2" -> "net462" 54 | | "v4.7" -> "net47" 55 | | "v4.7.1" -> "net471" 56 | | "v4.7.2" -> "net472" 57 | | x -> failwithf "Unsupported TargetFrameworkVersion %A" x 58 | |> (fun x -> XElement(NsNone + "TargetFramework", x)) 59 | 60 | let xPlatform = match !> xdoc.Descendants(NsMsBuild + "Platform").FirstOrDefault() : string with 61 | | null -> null 62 | | "AnyCPU" -> null 63 | | x -> XElement(NsNone + "PlatformTarget", x) 64 | 65 | let xunsafe = xdoc.Descendants(NsMsBuild + "AllowUnsafeBlocks").FirstOrDefault() |> rewrite 66 | 67 | let xSignAss = xdoc.Descendants(NsMsBuild + "SignAssembly").FirstOrDefault() |> rewrite 68 | 69 | let xOriginatorSign = xdoc.Descendants(NsMsBuild + "AssemblyOriginatorKeyFile").FirstOrDefault() |> rewrite 70 | 71 | let xAssName = match !> xdoc.Descendants(NsMsBuild + "AssemblyName").FirstOrDefault() : string with 72 | | x when x <> projectFileName -> XElement(NsNone + "AssemblyName", x) 73 | | _ -> null 74 | 75 | let xRootNs = match !> xdoc.Descendants(NsMsBuild + "RootNamespace").FirstOrDefault() : string with 76 | | x when x <> projectFileName -> XElement(NsNone + "RootNamespace", x) 77 | | _ -> null 78 | 79 | let xOutType = match !> xdoc.Descendants(NsMsBuild + "OutputType").FirstOrDefault() : string with 80 | | null -> null 81 | | "Library" -> null 82 | | x -> XElement(NsNone + "OutputType", x) 83 | 84 | let xWarnAsErr = xdoc.Descendants(NsMsBuild + "TreatWarningsAsErrors").FirstOrDefault() |> rewrite 85 | 86 | let xWarns = xdoc.Descendants(NsMsBuild + "WarningsAsErrors").FirstOrDefault() |> rewrite 87 | 88 | let isFSharp = xdoc.Descendants(NsMsBuild + "Compile") 89 | |> Seq.exists (fun x -> (!> x.Attribute(NsNone + "Include") : string).EndsWith(".fs")) 90 | let src = xdoc.Descendants(NsMsBuild + "Compile") 91 | |> Seq.filter (fun x -> isFSharp || (!> x.Attribute(NsNone + "Include") : string).StartsWith("..")) 92 | |> Seq.map rewrite 93 | let res = xdoc.Descendants(NsMsBuild + "EmbeddedResource") 94 | |> Seq.filter (fun x -> (!> x.Attribute(NsNone + "Include") : string).StartsWith("..")) 95 | |> Seq.map rewrite 96 | let content = xdoc.Descendants(NsMsBuild + "Content") 97 | |> Seq.map rewrite 98 | let none = xdoc.Descendants(NsMsBuild + "None") 99 | |> Seq.filter (fun x -> (!> x.Attribute(NsNone + "Include") : string) <> "packages.config") 100 | |> Seq.map rewrite 101 | let xSrc = XElement(NsNone + "ItemGroup", src, content, res, none) 102 | 103 | let prjRefs = xdoc.Descendants(NsMsBuild + "ProjectReference") 104 | |> Seq.map rewrite 105 | let xPrjRefs = if prjRefs.Any() then XElement(NsNone + "ItemGroup", prjRefs) 106 | else null 107 | 108 | let refs = xdoc.Descendants(NsMsBuild + "Reference") 109 | |> Seq.filter (fun x -> x.HasElements |> not) 110 | |> Seq.map rewrite 111 | let xRefs = if refs.Any() then XElement(NsNone + "ItemGroup", refs) 112 | else null 113 | 114 | let xPkgs = convertPackageConfig projectFile 115 | 116 | XDocument( 117 | XElement(NsNone + "Project", 118 | XAttribute(NsNone + "Sdk", "Microsoft.NET.Sdk"), 119 | XElement(NsNone + "PropertyGroup", 120 | XElement(NsNone + "AutoGenerateBindingRedirects", "true"), 121 | XElement(NsNone + "GenerateAssemblyInfo", "false"), 122 | xTargetFx, 123 | xPlatform, 124 | xunsafe, 125 | xSignAss, 126 | xOriginatorSign, 127 | xAssName, 128 | xRootNs, 129 | xOutType, 130 | xWarnAsErr, 131 | xWarns), 132 | xRefs, 133 | xPkgs, 134 | xSrc, 135 | xPrjRefs)) 136 | 137 | let isCandidate (projectFile : FileInfo) = 138 | let xdoc = XDocument.Load (projectFile.FullName) 139 | xdoc.Root.Attribute(NsNone + "Sdk") |> isNull 140 | 141 | 142 | let saveProject (projectFile : FileInfo, content : XDocument) = 143 | content.Save (projectFile.FullName) 144 | 145 | 146 | let searchProjects (rootFolder : DirectoryInfo) = 147 | rootFolder.EnumerateFiles("*.csproj", SearchOption.AllDirectories) 148 | |> Seq.append (rootFolder.EnumerateFiles("*.vbproj", SearchOption.AllDirectories)) 149 | |> Seq.append (rootFolder.EnumerateFiles("*.fsproj", SearchOption.AllDirectories)) 150 | 151 | [] 152 | let main argv = 153 | if argv |> Array.length = 0 then failwithf "Usage: ConvertToMsBuildSdk " 154 | let rootFolder = argv.[0] |> DirectoryInfo 155 | if rootFolder.Exists |> not then failwithf "Directory %A does not exist" rootFolder 156 | 157 | rootFolder |> searchProjects 158 | |> Seq.filter isCandidate 159 | |> Seq.map (fun x -> x, convertProject x) 160 | |> Seq.iter saveProject 161 | 0 162 | 163 | -------------------------------------------------------------------------------- /ConvertToMsBuildSdk/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /DNTools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2009 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ConvertToMsBuildSdk", "ConvertToMsBuildSdk\ConvertToMsBuildSdk.fsproj", "{D426D8BE-EF8E-4B22-9040-80752C526B57}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D426D8BE-EF8E-4B22-9040-80752C526B57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D426D8BE-EF8E-4B22-9040-80752C526B57}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D426D8BE-EF8E-4B22-9040-80752C526B57}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D426D8BE-EF8E-4B22-9040-80752C526B57}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {47078017-2B2D-42A5-90E5-7006415A49E1} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ConvertToMsBuildSdk 2 | ConvertToMsBuildSdk converts msbuild .NET projects to new project style (Sdk). 3 | 4 | Usage: 5 | ``` 6 | ConvertToMsBuildSdk 7 | ``` 8 | 9 | It will look for projects (*.csproj, *.vbproj, *.fsproj) and convert them to new format. 10 | 11 | What is being converted is covered here for the most part: 12 | http://www.natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/ 13 | 14 | ## Restrictions 15 | * NuGet packages are converted to PackageReference. Paket is not supported for the moment. 16 | * Imports are discarded 17 | * DefineConstants are discarded 18 | * AutoGenerateBindingRedirects is forced to true 19 | * GenerateAssemblyInfo is forced to false 20 | * only .net fx 3.5+ is supported 21 | 22 | ## Disclaimer 23 | Converted projects are overwritten !! 24 | I can't be liable if you lose something or things do not work as expected ! 25 | You have been warned ! 26 | 27 | ## License 28 | Do what you want with this source code! 29 | --------------------------------------------------------------------------------