Cambiar el marco de destino para todos mis proyectos en una solución de Visual Studio

104

Necesito cambiar el marco de destino para todos los proyectos. Tengo muchas soluciones con cientos de proyectos.

¿Algo nuevo aquí o tengo que cambiar cada proyecto?

Ezombort
fuente

Respuestas:

37

Puede hacerlo utilizando la macro de Visual Studio de Scott Dorman disponible en CodeProject:

Versión de Visual Studio 2010 y Target Framework

A continuación se muestra el código, descárguelo en su <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacroscarpeta, abra Visual Studio Macro IDE (Alt-F11) y agréguelo como un elemento existente al proyecto "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
fuente
3
+1 para el código, porque el enlace en CodeProject parece que ya no funciona.
Hannele
81

Recién publicado Target Framework Migrator , extensión de Visual Studio para cambiar múltiples proyectos .Net Target Framework a la vez

Pavel Samokha
fuente
Esto no es un juego en 2013 todavía.
Jon Egerton
1
Solo se necesita un único cambio de número de versión en vsixmanifest para funcionar en VS 2013
Panagiotis Kanavos
Esta extensión es un verdadero ahorro de tiempo :)
fusión
3
Para VS2015: descargar, descomprimir, en vsixmanifest: cambiar la versión InstallationTarget a 14.0 y la dependencia a 4.6
Jeroen K
5
Nueva versión con soporte VS2015 y 4.6 subido a la galería.
Pavel Samokha
35

Un script de PowerShell que solía hacer el mío. Es cierto que 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
fuente
1
Genial, pero en mi sistema recibí un error, script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policiesasí que ejecuté el comando set-executionpolicy remotesignedpara solucionarlo.
kuncevic.dev
Sí, señor, bigb. No poder ejecutar scripts de forma predeterminada en un sistema es una molestia que simplemente doy por sentado. Gracias por señalar eso. Para todos ustedes le Set-ExecutionPolicy RemoteSignedpermite ejecutar scripts de PowerShell locales sin firmarlos con certificado. Para obtener más información, consulte aquí: technet.microsoft.com/en-us/library/ee176961.aspx
Russell B
2
Esto es exactamente lo que estaba buscando. La solución más elegante y flexible para cambiar todos esos archivos .proj.
Ole Viaud-Murat
1
Para mí, la migración modifica los archivos del proyecto, app.configs y diseñadores
Tomas Kubes
10

Siempre está lo simple. Un editor de texto decente como notepad ++ incluirá una función de buscar / reemplazar en archivos. Simplemente busque la cadena de la versión actual en sus archivos csproj / vbproj:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

y reemplazar con la nueva versión

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Sin embargo, es una buena idea comprobar primero ...

Jon Egerton
fuente
1
Esta es la mejor manera que encontré, usé Sublime para cambiar todo
cuongle
7

Desde bash:

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

Creo que, con mucho, la forma más sencilla de hacerlo es utilizando una herramienta de búsqueda y reemplazo. Es una ventaja si admite expresiones regulares.

Debe haber bastantes, sin embargo, el primero que probé funcionó para mí: http://www.ecobyte.com/replacetext/

Hay una nota que dice que tiene algunos problemas en Win7, pero yo no experimenté eso.

Instrucciones paso a paso en esa herramienta:

  1. Reemplazar | Agregar grupo | Nómbrelo (por ejemplo, "MiGrupo")
  2. Haga clic con el botón derecho en MyGroup | Agregar archivos)...
  3. Elija su fuente (por ejemplo, Usar carpeta, busque la carpeta raíz de los proyectos que desea cambiar)
  4. Configure el filtro de archivo de inclusión si es necesario (por ejemplo, * .csproj)
  5. Haga clic con el botón derecho en la fila debajo de Texto original | Edición avanzada ...
  6. Ingrese su expresión regular en el cuadro de texto de búsqueda (por ejemplo <TargetFrameworkVersion>.*</TargetFrameworkVersion>)
  7. Seleccione "Búsqueda de expresiones regulares" en el cuadro combinado debajo del texto de búsqueda
  8. Ingrese texto de reemplazo (p <TargetFrameworkVersion>4.0</TargetFrameworkVersion>. Ej. )
  9. Elija la configuración de destino y copia de seguridad (creará una copia de seguridad de forma predeterminada)
  10. Comenzar a reemplazar (Ctrl + R)

Ahora bien, si por alguna razón necesita hacer esto en código, probablemente yo también pueda hacerlo (así es como encontré esta pregunta). En ese caso, solicítelo en un comentario.


ingrese la descripción de la imagen aquí

Mike Fuchs
fuente
Ok, acabo de leer el comentario de 0xA3 debajo de la respuesta de ShellShocks. Supongo que eso podría ser un problema. Intentaré crear una expresión regular antes de pasar a la solución codificada.
Mike Fuchs
2

Las expresiones regulares condicionales me están dando dolor de cabeza. Así que aquí hay una solución codificada para buscar / reemplazar (estoy evitando EnvDTE tanto como sea posible).

El orden no parece importar para las entradas del archivo del proyecto:

Prueba algo en ese sentido:

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
fuente
1

Puede usar una macro para hacer esto, o recordar que los archivos del proyecto VS son archivos de texto, lo que significa que una simple búsqueda global y reemplazo puede lograr lo mismo, y es una técnica más general para realizar el mismo cambio en muchos archivos del proyecto.

Primero haga una copia de seguridad de un archivo de proyecto existente, luego realice el cambio que desee (por ejemplo, cambie el marco de trabajo de destino). Utilice WinDiff o WinMerge para comparar el nuevo archivo de proyecto con la copia de seguridad. Esto le indicará el cambio que debe realizar. Luego, use la función Buscar y reemplazar en archivos del IDE de Visual Studio para realizar el cambio en todos los archivos de su proyecto.

Polyfun
fuente
2
Una simple búsqueda y reemplazo fallará para archivos de proyecto que no especifiquen un marco de destino (por ejemplo, archivos creados originalmente en VS 2005). Para tales archivos de proyecto, tendría que encontrar la posición correcta para insertar el elemento de marco de destino con una expresión de búsqueda y reemplazo más complicada.
Dirk Vollmar
0

Una alternativa sin herramientas externas (y la capacidad de cambiar otras configuraciones, por ejemplo, ToolsVersion):

  1. Con Visual Studio, cree un nuevo proyecto de consola de c # 'ManageCSProjFiles' (o el nombre que desee) en un directorio temporal. Asegúrese de marcar 'Colocar solución y proyecto en el mismo directorio'
  2. Elimine Program.cs y Properties / AssemblyInfo.cs del proyecto. No es necesario compilar nunca el proyecto.
  3. Guarde el proyecto y cierre Visual Studio.
  4. Con un editor de texto, abra ManageCSProjFiles.csproj. Agregue las siguientes líneas en la parte inferior, antes de la última línea:
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. Copie ManageCSProjFiles.sln y ManageCSProjFiles.csproj en el directorio superior de su árbol de soluciones.
  2. Si carga la solución ManageCSProjFiles en Visual Studio, ahora mostrará todos sus archivos .csproj y puede cambiarlos con las herramientas de búsqueda / reemplazo en Visual Studio.

Esto se puede ampliar fácilmente para otros tipos de proyectos.

tranquilamente seguro
fuente