Ändern Sie das Zielframework für alle meine Projekte in einer Visual Studio-Lösung

104

Ich muss das Ziel-Framework für alle Projekte ändern. Ich habe viele Lösungen mit Hunderten von Projekten.

Gibt es hier etwas Neues oder muss ich jedes einzelne Projekt ändern?

Ezombort
quelle

Antworten:

37

Sie können dies mit dem Visual Studio-Makro von Scott Dorman tun, das auf CodeProject verfügbar ist:

Visual Studio 2010 und Target Framework-Version

Unten finden Sie den Code. Laden Sie ihn in Ihren <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacrosOrdner herunter , öffnen Sie die Visual Studio-Makro-IDE (Alt-F11) und fügen Sie ihn als vorhandenes Element zum Projekt „MyMacros“ hinzu:

'------------------------------------------------------------------------------
' Visual Studio 2008 Macros
'
' ProjectUtilities.vb
'
'------------------------------------------------------------------------------
' Copyright (C) 2007-2008 Scott Dorman ([email protected])
'
' This library is free software; you can redistribute it and/or
' modify it under the terms of the Microsoft Public License (Ms-PL).
'
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' Microsoft Public License (Ms-PL) for more details.
'------------------------------------------------------------------------------
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module ProjectUtilities

    Private Class ProjectGuids
        Public Const vsWindowsCSharp As String = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
        Public Const vsWindowsVBNET As String = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"
        Public Const vsWindowsVisualCPP As String = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"
        Public Const vsWebApplication As String = "{349C5851-65DF-11DA-9384-00065B846F21}"
        Public Const vsWebSite As String = "{E24C65DC-7377-472B-9ABA-BC803B73C61A}"
        Public Const vsDistributedSystem As String = "{F135691A-BF7E-435D-8960-F99683D2D49C}"
        Public Const vsWCF As String = "{3D9AD99F-2412-4246-B90B-4EAA41C64699}"
        Public Const vsWPF As String = "{60DC8134-EBA5-43B8-BCC9-BB4BC16C2548}"
        Public Const vsVisualDatabaseTools As String = "{C252FEB5-A946-4202-B1D4-9916A0590387}"
        Public Const vsDatabase As String = "{A9ACE9BB-CECE-4E62-9AA4-C7E7C5BD2124}"
        Public Const vsDatabaseOther As String = "{4F174C21-8C12-11D0-8340-0000F80270F8}"
        Public Const vsTest As String = "{3AC096D0-A1C2-E12C-1390-A8335801FDAB}"
        Public Const vsLegacy2003SmartDeviceCSharp As String = "{20D4826A-C6FA-45DB-90F4-C717570B9F32}"
        Public Const vsLegacy2003SmartDeviceVBNET As String = "{CB4CE8C6-1BDB-4DC7-A4D3-65A1999772F8}"
        Public Const vsSmartDeviceCSharp As String = "{4D628B5B-2FBC-4AA6-8C16-197242AEB884}"
        Public Const vsSmartDeviceVBNET As String = "{68B1623D-7FB9-47D8-8664-7ECEA3297D4F}"
        Public Const vsWorkflowCSharp As String = "{14822709-B5A1-4724-98CA-57A101D1B079}"
        Public Const vsWorkflowVBNET As String = "{D59BE175-2ED0-4C54-BE3D-CDAA9F3214C8}"
        Public Const vsDeploymentMergeModule As String = "{06A35CCD-C46D-44D5-987B-CF40FF872267}"
        Public Const vsDeploymentCab As String = "{3EA9E505-35AC-4774-B492-AD1749C4943A}"
        Public Const vsDeploymentSetup As String = "{978C614F-708E-4E1A-B201-565925725DBA}"
        Public Const vsDeploymentSmartDeviceCab As String = "{AB322303-2255-48EF-A496-5904EB18DA55}"
        Public Const vsVSTA As String = "{A860303F-1F3F-4691-B57E-529FC101A107}"
        Public Const vsVSTO As String = "{BAA0C2D2-18E2-41B9-852F-F413020CAA33}"
        Public Const vsSharePointWorkflow As String = "{F8810EC1-6754-47FC-A15F-DFABD2E3FA90}"
    End Class

    '' Defines the valid target framework values.
    Enum TargetFramework
        Fx40 = 262144
        Fx35 = 196613
        Fx30 = 196608
        Fx20 = 131072
    End Enum

    '' Change the target framework for all projects in the current solution.
    Sub ChangeTargetFrameworkForAllProjects()
        Dim project As EnvDTE.Project
        Dim clientProfile As Boolean = False

        Write("--------- CHANGING TARGET .NET FRAMEWORK VERSION -------------")
        Try
            If Not DTE.Solution.IsOpen Then
                Write("There is no solution open.")
            Else              
                Dim targetFrameworkInput As String = InputBox("Enter the target framework version (Fx40, Fx35, Fx30, Fx20):", "Target Framework", "Fx40")
                Dim targetFramework As TargetFramework = [Enum].Parse(GetType(TargetFramework), targetFrameworkInput)

                If targetFramework = ProjectUtilities.TargetFramework.Fx35 Or targetFramework = ProjectUtilities.TargetFramework.Fx40 Then
                    Dim result As MsgBoxResult = MsgBox("The .NET Framework version chosen supports a Client Profile. Would you like to use that profile?", MsgBoxStyle.Question Or MsgBoxStyle.YesNo, "Target Framework Profile")
                    If result = MsgBoxResult.Yes Then
                        clientProfile = True
                    End If
                End If

                For Each project In DTE.Solution.Projects
                    If project.Kind <> Constants.vsProjectKindSolutionItems And project.Kind <> Constants.vsProjectKindMisc Then
                        ChangeTargetFramework(project, targetFramework, clientProfile)
                    Else
                        For Each projectItem In project.ProjectItems
                            If Not (projectItem.SubProject Is Nothing) Then
                                ChangeTargetFramework(projectItem.SubProject, targetFramework, clientProfile)
                            End If
                        Next

                    End If
                Next
            End If
        Catch ex As System.Exception
            Write(ex.Message)
        End Try
    End Sub

    '' Change the target framework for a project.
    Function ChangeTargetFramework(ByVal project As EnvDTE.Project, ByVal targetFramework As TargetFramework, ByVal clientProfile As Boolean) As Boolean
        Dim changed As Boolean = True

        If project.Kind = Constants.vsProjectKindSolutionItems Or project.Kind = Constants.vsProjectKindMisc Then
            For Each projectItem In project.ProjectItems
                If Not (projectItem.SubProject Is Nothing) Then
                    ChangeTargetFramework(projectItem.SubProject, targetFramework, clientProfile)
                End If
            Next
        Else
            Try
                If IsLegalProjectType(project) Then
                    SetTargetFramework(project, targetFramework, clientProfile)
                Else
                    Write("Skipping project: " + project.Name + " (" + project.Kind + ")")
                End If
            Catch ex As Exception
                Write(ex.Message)
                changed = False
            End Try
        End If

        Return changed
    End Function

    '' Determines if the project is a project that actually supports changing the target framework.
    Function IsLegalProjectType(ByVal proejct As EnvDTE.Project) As Boolean
        Dim legalProjectType As Boolean = True

        Select Case proejct.Kind
            Case ProjectGuids.vsDatabase
                legalProjectType = False
            Case ProjectGuids.vsDatabaseOther
                legalProjectType = False
            Case ProjectGuids.vsDeploymentCab
                legalProjectType = False
            Case ProjectGuids.vsDeploymentMergeModule
                legalProjectType = False
            Case ProjectGuids.vsDeploymentSetup
                legalProjectType = False
            Case ProjectGuids.vsDeploymentSmartDeviceCab
                legalProjectType = False
            Case ProjectGuids.vsDistributedSystem
                legalProjectType = False
            Case ProjectGuids.vsLegacy2003SmartDeviceCSharp
                legalProjectType = False
            Case ProjectGuids.vsLegacy2003SmartDeviceVBNET
                legalProjectType = False
            Case ProjectGuids.vsSharePointWorkflow
                legalProjectType = False
            Case ProjectGuids.vsSmartDeviceCSharp
                legalProjectType = True
            Case ProjectGuids.vsSmartDeviceVBNET
                legalProjectType = True
            Case ProjectGuids.vsTest
                legalProjectType = False
            Case ProjectGuids.vsVisualDatabaseTools
                legalProjectType = False
            Case ProjectGuids.vsVSTA
                legalProjectType = True
            Case ProjectGuids.vsVSTO
                legalProjectType = True
            Case ProjectGuids.vsWCF
                legalProjectType = True
            Case ProjectGuids.vsWebApplication
                legalProjectType = True
            Case ProjectGuids.vsWebSite
                legalProjectType = True
            Case ProjectGuids.vsWindowsCSharp
                legalProjectType = True
            Case ProjectGuids.vsWindowsVBNET
                legalProjectType = True
            Case ProjectGuids.vsWindowsVisualCPP
                legalProjectType = True
            Case ProjectGuids.vsWorkflowCSharp
                legalProjectType = False
            Case ProjectGuids.vsWorkflowVBNET
                legalProjectType = False
            Case ProjectGuids.vsWPF
                legalProjectType = True
            Case Else
                legalProjectType = False
        End Select
        Return legalProjectType
    End Function

    '' Sets the target framework for the project to the specified framework.
    Sub SetTargetFramework(ByVal project As EnvDTE.Project, ByVal targetFramework As TargetFramework, ByVal clientProfile As Boolean)
        Dim currentTargetFramework As TargetFramework = CType(project.Properties.Item("TargetFramework").Value, TargetFramework)
        Dim targetMoniker As String = GetTargetFrameworkMoniker(targetFramework, clientProfile)
        Dim currentMoniker As String = project.Properties.Item("TargetFrameworkMoniker").Value

        If currentMoniker <> targetMoniker Then
            Write("Changing project: " + project.Name + " from " + currentMoniker + " to " + targetMoniker + ".")
            project.Properties.Item("TargetFrameworkMoniker").Value = targetMoniker
            project.Properties.Item("TargetFramework").Value = targetFramework
        Else
            Write("Skipping project: " + project.Name + ", already at the correct target framework.")
        End If
    End Sub

    Function GetTargetFrameworkMoniker(ByVal targetFramework As TargetFramework, ByVal clientProfile As Boolean) As String
        Dim moniker As String = ".NETFramework,Version=v"
        Select Case targetFramework
            Case ProjectUtilities.TargetFramework.Fx20
                moniker += "2.0"

            Case ProjectUtilities.TargetFramework.Fx30
                moniker += "3.0"

            Case ProjectUtilities.TargetFramework.Fx35
                moniker += "3.5"

            Case ProjectUtilities.TargetFramework.Fx40
                moniker += "4.0"

        End Select

        If clientProfile Then
            moniker += ",Profile=Client"
        End If

        Return moniker
    End Function

    '' Writes a message to the output window
    Sub Write(ByVal s As String)
        Dim out As OutputWindowPane = GetOutputWindowPane("Change Target Framework", True)
        out.OutputString(s)
        out.OutputString(vbCrLf)
    End Sub

    '' Gets an instance of the output window
    Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
        Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        If show Then win.Visible = True
        Dim ow As OutputWindow = win.Object
        Dim owpane As OutputWindowPane
        Try
            owpane = ow.OutputWindowPanes.Item(Name)
        Catch e As System.Exception
            owpane = ow.OutputWindowPanes.Add(Name)
        End Try
        owpane.Activate()
        Return owpane
    End Function

End Module
Dirk Vollmar
quelle
3
+1 für Code, da der Link auf CodeProject nicht mehr zu funktionieren scheint.
Hannele
81

Gerade veröffentlichter Target Framework Migrator , Visual Studio Extension zum gleichzeitigen Ändern mehrerer .NET-Projekte Target Framework

Pavel Samokha
quelle
Dies spielt 2013 noch keinen Ball.
Jon Egerton
1
Benötigt nur eine einzige Änderung der Versionsnummer in vsixmanifest, um in VS 2013 zu funktionieren
Panagiotis Kanavos
Diese Erweiterung ist eine echte Zeitersparnis :)
Fusion
3
Für VS2015: herunterladen, entpacken, in vsixmanifest: InstallationTarget-Version auf 14.0 und Abhängigkeit auf 4.6 ändern
Jeroen K
5
Neue Version mit VS2015- und 4.6-Unterstützung in Galerie hochgeladen.
Pavel Samokha
35

Ein PowerShell-Skript, mit dem ich meins erstellt habe. Zugegeben, Bruce Force-ish.

Get-ChildItem . -Recurse -Filter *.*proj |ForEach {
    $content = Get-Content $_.FullName
    $content |ForEach {
        $_.Replace("<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>", "<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>")
    } |Set-Content $_.FullName
}
Russell B.
quelle
1
Großartig, aber auf meinem System ist ein Fehler aufgetreten, script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policiesdaher führe ich einen Befehl aus set-executionpolicy remotesigned, um das zu beheben.
Kuncevic.dev
Yessirree, bigb. Nicht in der Lage zu sein, Skripte standardmäßig auf einem System auszuführen, ist ein Ärger, den ich für selbstverständlich halte. Vielen Dank für den Hinweis. Für alle Set-ExecutionPolicy RemoteSignedkönnen Sie lokale PowerShell-Skripte ausführen, ohne sie mit einem Zertifikat zu signieren. Für Details siehe hier: technet.microsoft.com/en-us/library/ee176961.aspx
Russell B
2
Genau das habe ich gesucht. Die eleganteste und flexibelste Lösung zum Ändern all dieser .proj-Dateien.
Ole Viaud-Murat
1
Für mich ändert die Migration Projektdateien, app.configs und Designer
Tomas Kubes
10

Es gibt immer das Einfache. Ein anständiger Texteditor wie Notepad ++ enthält eine Funktion zum Suchen / Ersetzen in Dateien. Suchen Sie einfach in Ihren csproj / vbproj-Dateien nach der aktuellen Versionszeichenfolge:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

und durch die neue Version ersetzen

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Gute Idee, zuerst auszuchecken ...

Jon Egerton
quelle
1
Dies ist der beste Weg, den ich gefunden habe. Ich habe Sublime verwendet, um alles zu ändern
cuongle
7

Von Bash:

$find . -name "*.csproj" -exec sed -b -i "s,<TargetFrameworkVersion>[^<]*</TargetFrameworkVersion>,<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>," {} \;
Robert Jørgensgaard Engdahl
quelle
6

Ich denke, der mit Abstand einfachste Weg, dies zu tun, ist die Verwendung eines Such- und Ersetzungswerkzeugs. Es ist von Vorteil, wenn es Regex unterstützt.

Es muss einige geben - der erste, den ich getestet habe, hat für mich funktioniert: http://www.ecobyte.com/replacetext/

Es gibt einen Hinweis, dass es einige Probleme unter Win7 gibt, aber das habe ich nicht erlebt.

Schritt-für-Schritt-Anleitung in diesem Tool:

  1. Ersetzen | Gruppe hinzufügen | Nennen Sie es (zB "MyGroup")
  2. Klicken Sie mit der rechten Maustaste auf MyGroup | Dateien hinzufügen)...
  3. Wählen Sie Ihre Quelle aus (z. B. Ordner verwenden, navigieren Sie zum Stammordner der Projekte, die Sie ändern möchten).
  4. Stellen Sie bei Bedarf den Filter "Datei einschließen" ein (z. B. * .csproj).
  5. Klicken Sie mit der rechten Maustaste auf die Zeile unter Originaltext | Erweiterte Bearbeitung ...
  6. Geben Sie Ihren regulären Ausdruck in Textfeld Suche (zB <TargetFrameworkVersion>.*</TargetFrameworkVersion>)
  7. Wählen Sie "Suche nach regulären Ausdrücken" in der Combobox unter dem Suchtext
  8. Ersatztext eingeben (zB <TargetFrameworkVersion>4.0</TargetFrameworkVersion>)
  9. Wählen Sie Ziel- und Sicherungseinstellungen (erstellt standardmäßig eine Sicherung)
  10. Ersetzen starten (Strg + R)

Wenn Sie dies aus irgendeinem Grund im Code tun müssen, könnte ich das wahrscheinlich auch tun (so habe ich diese Frage gefunden). In diesem Fall fordern Sie dies bitte in einem Kommentar an.


Geben Sie hier die Bildbeschreibung ein

Mike Fuchs
quelle
Ok, ich habe gerade den Kommentar von 0xA3 unter der ShellShocks-Antwort gelesen. Ich nehme an, das könnte ein Problem sein. Ich werde versuchen, einen regulären Ausdruck dafür zu finden, bevor ich zur codierten Lösung gehe.
Mike Fuchs
2

Bedingte reguläre Ausdrücke bereiten mir Kopfschmerzen. Hier ist also eine codierte Lösung für das Suchen / Ersetzen (ich vermeide EnvDTE so lange wie möglich).

Ordnung scheint keine Rolle zu spielen für die Einträge in der Projektdatei zu spielen:

Versuchen Sie etwas in diese Richtung:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace TextReplaceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ReplaceTargetFrameworkVersion("v4.0", "c:/projekt/2005", "*.csproj");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// Inserts the denoted targetFramework into all occurrences of TargetFrameworkVersion.
        /// If the TargetFrameworkVersion is not present in the file, the method searches for the 
        /// OutputType tag, which should be present, and inserts the TargetFrameworkVersion before that.
        /// </summary>
        /// <param name="targetFramework">New target framework (e.g. "v4.0")</param>
        /// <param name="rootDirectory">Root directory for the file search (e.g. "c:\Projects\2005")</param>
        /// <param name="fileSearchPattern">Pattern to find the project files (e.g. "*.csproj). 
        /// Will get all files for empty parameter.</param>
        public static void ReplaceTargetFrameworkVersion(string targetFramework, string rootDirectory, string fileSearchPattern)
        {
            if (string.IsNullOrEmpty(targetFramework)) throw new ArgumentNullException("targetFramework");
            if (string.IsNullOrEmpty(rootDirectory)) throw new ArgumentNullException("rootDirectory");
            if (string.IsNullOrEmpty(fileSearchPattern)) fileSearchPattern = "*.*";

            string regexPattern = "<TargetFrameworkVersion>.*</TargetFrameworkVersion>";
            string insertText = string.Format("<TargetFrameworkVersion>{0}</TargetFrameworkVersion>", targetFramework);
            string alternativeMarker = "<OutputType>";

            // get all files
            List<FileInfo> files = GetAllFiles(rootDirectory, fileSearchPattern);

            // iterate over found files
            foreach (var file in files)
            {
                string fileContent = File.ReadAllText(file.FullName);
                Match match = Regex.Match(fileContent, regexPattern);
                string newfileContent = null;
                if (match.Success)
                {
                    // replace <TargetFrameworkVersion>
                    newfileContent = fileContent.Replace(match.Value, insertText);
                }
                else if (fileContent.Contains(alternativeMarker))
                {
                    // create <TargetFrameworkVersion>
                    newfileContent = fileContent.Replace(alternativeMarker,
                        insertText + Environment.NewLine + "    " + alternativeMarker);
                }

                // overwrite file
                if (newfileContent != null)
                    File.WriteAllText(file.FullName, newfileContent);
            }
        }


        /// <summary>
        /// Recursive function to find all files in a directory by a searchPattern
        /// </summary>
        /// <param name="path">Path to the root directory</param>
        /// <param name="searchPattern">Pattern for the file search, e.g. "*.txt"</param>
        public static List<FileInfo> GetAllFiles(string path, string searchPattern)
        {
            List<FileInfo> files = new List<FileInfo>();

            DirectoryInfo dir = new DirectoryInfo(path);

            if (dir.Exists)
            {
                // get all files in directory
                files.AddRange(dir.GetFiles(searchPattern));

                // get all files of subdirectories
                foreach (var subDir in dir.GetDirectories())
                {
                    files.AddRange(GetAllFiles(subDir.FullName, searchPattern));
                }
            }
            return files;
        }
    }
}
Mike Fuchs
quelle
1

Sie können dazu ein Makro verwenden oder sich daran erinnern, dass es sich bei den VS-Projektdateien um Textdateien handelt. Dies bedeutet, dass durch einfaches globales Suchen und Ersetzen dasselbe erreicht werden kann. Dies ist eine allgemeinere Methode, um viele Projektdateien gleich zu ändern.

Sichern Sie zuerst eine vorhandene Projektdatei und nehmen Sie dann die gewünschte Änderung vor (z. B. ändern Sie das Zielframework). Verwenden Sie WinDiff oder WinMerge , um die neue Projektdatei mit der Sicherung zu vergleichen. Hier erfahren Sie, welche Änderungen Sie vornehmen müssen. Verwenden Sie dann die Funktion Suchen und Ersetzen in Dateien der Visual Studio-IDE, um die Änderung an all Ihren Projektdateien vorzunehmen.

Polyfun
quelle
2
Ein einfaches Suchen und Ersetzen schlägt für Projektdateien fehl, die kein Zielframework angeben (z. B. Dateien, die ursprünglich in VS 2005 erstellt wurden). Für solche Projektdateien müssten Sie die richtige Position finden, um das Ziel-Framework-Element mit einem komplizierteren Such- und Ersetzungsausdruck einzufügen.
Dirk Vollmar
0

Eine Alternative ohne externe Tools (und die Möglichkeit, andere Einstellungen zu ändern, z. B. ToolsVersion):

  1. Erstellen Sie mit Visual Studio ein neues c # -Konsolenprojekt 'ManageCSProjFiles' (oder einen beliebigen Namen) in einem temporären Verzeichnis. Stellen Sie sicher, dass "Lösung und Projekt in dasselbe Verzeichnis stellen" aktiviert ist.
  2. Entfernen Sie Program.cs und Properties / AssemblyInfo.cs aus dem Projekt. Es ist nicht erforderlich, das Projekt jemals zu kompilieren.
  3. Speichern Sie das Projekt und schließen Sie Visual Studio.
  4. Öffnen Sie mit einem Texteditor ManageCSProjFiles.csproj. Fügen Sie die folgenden Zeilen unten vor der letzten Zeile hinzu:
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. Kopieren Sie ManageCSProjFiles.sln und ManageCSProjFiles.csproj in das oberste Verzeichnis Ihres Lösungsbaums.
  2. Wenn Sie die ManageCSProjFiles-Lösung in Visual Studio laden, werden jetzt alle Ihre .csproj-Dateien angezeigt, und Sie können sie mit den Such- / Ersetzungswerkzeugen in Visual Studio ändern.

Dies kann leicht für andere Projekttypen erweitert werden.

leise zuversichtlich
quelle