Modifier le framework cible pour tous mes projets dans une solution Visual Studio

104

J'ai besoin de changer le cadre cible pour tous les projets. J'ai de nombreuses solutions avec des centaines de projets.

Y a-t-il quelque chose de nouveau ici ou dois-je changer chaque projet?

Ezombort
la source

Réponses:

37

Vous pouvez le faire en utilisant la macro Visual Studio de Scott Dorman disponible sur CodeProject:

Visual Studio 2010 et version du Framework cible

Vous trouverez ci-dessous le code, téléchargez-le dans votre <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacrosdossier, ouvrez l'IDE de macro Visual Studio (Alt-F11) et ajoutez-le en tant qu'élément existant au projet "MyMacros":

'------------------------------------------------------------------------------
' 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
la source
3
+1 pour le code, car le lien sur CodeProject ne semble plus fonctionner.
Hannele
81

Vient de publier Target Framework Migrator , Visual Studio Extension pour modifier plusieurs projets .Net Target Framework à la fois

Pavel Samokha
la source
Cela ne joue pas encore en 2013.
Jon Egerton
1
Un seul changement de numéro de version dans vsixmanifest est nécessaire pour fonctionner dans VS 2013
Panagiotis Kanavos
Cette extension est un véritable gain de temps :)
fusion du
3
Pour VS2015: télécharger, décompresser, dans vsixmanifest: changer la version d'InstallationTarget en 14.0 et la dépendance en 4.6
Jeroen K
5
Nouvelle version avec prise en charge de VS2015 et 4.6 téléchargée dans la galerie.
Pavel Samokha du
35

Un script PowerShell que j'ai utilisé pour faire le mien. Certes, 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
la source
1
Super mais sur mon système, j'ai eu une erreur, script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policiesalors j'exécute la commande set-executionpolicy remotesignedpour résoudre ce problème.
kuncevic.dev
Yessirree, bigb. Ne pas pouvoir exécuter des scripts par défaut sur un système est un problème que je prends juste pour acquis. Merci d'avoir fait remarquer cela. For all y'all Set-ExecutionPolicy RemoteSignedvous permet d'exécuter des scripts PowerShell locaux sans les signer par certificat. Pour plus de détails, voir ici: technet.microsoft.com/en-us/library/ee176961.aspx
Russell B
2
C'est exactement ce que je recherchais. Solution la plus élégante et flexible pour modifier tous ces fichiers .proj.
Ole Viaud-Murat
1
Pour moi, la migration modifie les fichiers de projet, app.configs et les concepteurs
Tomas Kubes
10

Il y a toujours du simple. Un éditeur de texte décent tel que notepad ++ inclura une fonction de recherche / remplacement dans les fichiers. Recherchez simplement la chaîne de version actuelle dans vos fichiers csproj / vbproj:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

et remplacer par la nouvelle version

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Bonne idée à vérifier d'abord ...

Jon Egerton
la source
1
C'est le meilleur moyen que j'ai trouvé, j'ai utilisé Sublime pour tout changer
cuongle
7

De bash:

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

Je pense que le moyen de loin le plus simple de le faire est d'utiliser un outil de recherche et de remplacement. C'est un avantage s'il prend en charge les regex.

Il doit y en avoir pas mal là-bas - le premier que j'ai testé a fonctionné pour moi, cependant: http://www.ecobyte.com/replacetext/

Il y a une note indiquant qu'il y a des problèmes sur Win7, mais je ne l'ai pas vécu.

Instructions étape par étape dans cet outil:

  1. Remplacer | Ajouter un groupe | Nommez-le (par exemple "MyGroup")
  2. Cliquez avec le bouton droit sur MyGroup | Ajouter des fichiers)...
  3. Choisissez votre source (par exemple, Utiliser le dossier, accédez au dossier racine des projets que vous souhaitez modifier)
  4. Définissez le filtre d'inclusion de fichier si nécessaire (par exemple * .csproj)
  5. Cliquez avec le bouton droit de la souris sur la ligne sous Texte d'origine | Modification avancée ...
  6. Entrez votre expression régulière dans la zone de texte de recherche (par exemple <TargetFrameworkVersion>.*</TargetFrameworkVersion>)
  7. Sélectionnez "Recherche d'expression régulière" dans la liste déroulante sous le texte de recherche
  8. Entrez le texte de remplacement (par exemple <TargetFrameworkVersion>4.0</TargetFrameworkVersion>)
  9. Choisissez les paramètres de destination et de sauvegarde (créera une sauvegarde par défaut)
  10. Commencer le remplacement (Ctrl + R)

Maintenant, si pour une raison quelconque vous devez le faire dans le code, je pourrais probablement le faire aussi (c'est ainsi que j'ai trouvé cette question). Dans ce cas, veuillez le demander dans un commentaire.


entrez la description de l'image ici

Mike Fuchs
la source
Ok, je viens de lire le commentaire de 0xA3 sous la réponse ShellShocks. Je suppose que cela pourrait être un problème. Je vais essayer de trouver une expression régulière pour cela avant de passer à la solution codée.
Mike Fuchs
2

Les expressions régulières conditionnelles me donnent mal à la tête. Voici donc une solution codée pour rechercher / remplacer (j'évite EnvDTE le plus longtemps possible).

L'ordre ne semble pas avoir d'importance pour les entrées du fichier de projet:

Essayez quelque chose du genre:

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
la source
1

Vous pouvez utiliser une macro pour ce faire ou vous rappeler que les fichiers de projet VS sont des fichiers texte, ce qui signifie qu'une simple recherche globale et un remplacement peuvent atteindre le même résultat, et il s'agit d'une technique plus générale pour apporter la même modification à de nombreux fichiers de projet.

Sauvegardez d'abord un fichier de projet existant, puis effectuez la modification souhaitée (par exemple, changez le cadre cible). Utilisez WinDiff ou WinMerge pour comparer le nouveau fichier de projet avec la sauvegarde. Cela vous indiquera le changement que vous devez apporter. Utilisez ensuite la fonction Rechercher et remplacer dans les fichiers de l'IDE de Visual Studio pour apporter la modification à tous vos fichiers de projet.

Polyfun
la source
2
Une simple recherche et remplacement échouera pour les fichiers de projet qui ne spécifient pas de cadre cible (par exemple, les fichiers créés à l'origine dans VS 2005). Pour de tels fichiers de projet, vous devrez trouver la position correcte pour insérer l'élément de cadre cible avec une expression de recherche et de remplacement plus compliquée.
Dirk Vollmar
0

Une alternative sans outils externes (et la possibilité de modifier d'autres paramètres, par exemple ToolsVersion):

  1. À l'aide de Visual Studio, créez un nouveau projet de console c # 'ManageCSProjFiles' (ou le nom de votre choix) dans un répertoire temporaire. Assurez-vous de cocher «Placer la solution et le projet dans le même répertoire»
  2. Supprimez Program.cs et Properties / AssemblyInfo.cs du projet. Il n'est jamais nécessaire de compiler le projet.
  3. Enregistrez le projet et fermez Visual Studio.
  4. À l'aide d'un éditeur de texte, ouvrez ManageCSProjFiles.csproj. Ajoutez les lignes suivantes en bas, avant la dernière ligne:
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. Copiez ManageCSProjFiles.sln et ManageCSProjFiles.csproj dans le répertoire supérieur de votre arborescence de solutions.
  2. Si vous chargez la solution ManageCSProjFiles dans Visual Studio, elle affichera désormais tous vos fichiers .csproj et vous pourrez les modifier avec les outils de recherche / remplacement dans Visual Studio.

Cela peut facilement être étendu à d'autres types de projets.

tranquillement confiant
la source