Visual Studio 솔루션의 모든 프로젝트에 대한 대상 프레임 워크 변경


104

모든 프로젝트의 대상 프레임 워크를 변경해야합니다. 수백 개의 프로젝트가있는 많은 솔루션이 있습니다.

여기에 새로운 것이 있습니까? 아니면 모든 프로젝트를 변경해야합니까?

답변:


37

CodeProject에서 사용할 수있는 Scott Dorman의 Visual Studio 매크로를 사용하여이를 수행 할 수 있습니다.

Visual Studio 2010 및 대상 프레임 워크 버전

아래 코드는 <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacros폴더에 다운로드 하고 Visual Studio 매크로 IDE (Alt-F11)를 열고 "MyMacros"프로젝트에 기존 항목으로 추가합니다.

'------------------------------------------------------------------------------
' Visual Studio 2008 Macros
'
' ProjectUtilities.vb
'
'------------------------------------------------------------------------------
' Copyright (C) 2007-2008 Scott Dorman (sj_dorman@hotmail.com)
'
' 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

3
코드에 +1. CodeProject의 링크가 더 이상 작동하지 않는 것 같기 때문입니다.
Hannele 2012 년

81

방금 게시 된 Target Framework Migrator , 여러 .Net 프로젝트를 한 번에 대상 프레임 워크 변경하기위한 Visual Studio Extension


2013 년에는 아직 공놀이가 아닙니다.
Jon Egerton 2013 년

1
VS 2013에서 작동하려면 vsixmanifest에서 단일 버전 번호 변경 만 필요합니다
Panagiotis Kanavos

이 확장은 실제 시간을 절약 해줍니다. :)
합병

3
VS2015의 경우 : vsixmanifest에서 다운로드, 압축 해제 : InstallationTarget 버전을 14.0으로 변경하고 종속성을 4.6으로 변경
Jeroen K

5
VS2015 및 4.6을 지원하는 새 버전이 갤러리에 업로드되었습니다.
Pavel Samokha 2015 년

35

내 작업에 사용한 PowerShell 스크립트입니다. 분명히 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
}

1
훌륭하지만 내 시스템에서 오류가 발생 script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies하여 명령 set-executionpolicy remotesigned을 실행 하여 수정합니다.
kuncevic.dev 2013 년

예시 리, 빅. 시스템에서 기본적으로 스크립트를 실행할 수 없다는 것은 당연한 일이라고 생각합니다. 지적 해 주셔서 감사합니다. 모두 Set-ExecutionPolicy RemoteSigned를 위해 인증서 서명없이 로컬 PowerShell 스크립트를 실행할 수 있습니다. 자세한 내용은 다음을 참조하십시오. technet.microsoft.com/en-us/library/ee176961.aspx
Russell B

2
이것이 바로 제가 찾던 것입니다. 모든 .proj 파일을 변경하는 가장 우아하고 유연한 솔루션입니다.
Ole Viaud-Murat

1
나에게 마이그레이션은 프로젝트 파일, app.configs 및 디자이너를 수정합니다
Tomas Kubes

10

항상 단순합니다. notepad ++와 같은 괜찮은 텍스트 편집기에는 파일에서 찾기 / 바꾸기 기능이 포함됩니다. csproj / vbproj 파일에서 현재 버전 문자열을 검색하면됩니다.

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

새 버전으로 교체

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

그래도 먼저 확인하는 것이 좋습니다 ...


1
이것이 제가 찾은 가장 좋은 방법입니다. 저는 Sublime을 사용하여 모든 것을 변경했습니다
cuongle

7

bash에서 :

$find . -name "*.csproj" -exec sed -b -i "s,<TargetFrameworkVersion>[^<]*</TargetFrameworkVersion>,<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>," {} \;

6

이 작업을 수행하는 가장 쉬운 방법은 검색 및 바꾸기 도구를 사용하는 것입니다. 정규식을 지원하면 장점입니다.

거기에 꽤 많은 것이있을 것입니다-제가 테스트 한 첫 번째 것은 저를 위해 일했습니다 : http://www.ecobyte.com/replacetext/

Win7에 몇 가지 문제가 있다는 메모가 있지만 경험하지 못했습니다.

해당 도구의 단계별 지침 :

  1. 바꾸기 | 그룹 추가 | 이름을 지정합니다 (예 : "MyGroup").
  2. MyGroup을 마우스 오른쪽 버튼으로 클릭 | 파일 추가)...
  3. 소스를 선택하십시오 (예 : 폴더 사용, 변경하려는 프로젝트의 루트 폴더로 이동).
  4. 필요한 경우 포함 파일 필터를 설정합니다 (예 : * .csproj).
  5. 원본 텍스트 아래 행을 마우스 오른쪽 버튼으로 클릭 | 고급 편집 ...
  6. (예를 들어, 검색 텍스트 상자에 정규 표현식을 입력 <TargetFrameworkVersion>.*</TargetFrameworkVersion>)
  7. 검색 텍스트 아래의 콤보 상자에서 "정규식 검색"을 선택하십시오.
  8. 대체 텍스트를 입력합니다 (예를 들어 <TargetFrameworkVersion>4.0</TargetFrameworkVersion>)
  9. 대상 및 백업 설정 선택 (기본적으로 백업 생성)
  10. 바꾸기 시작 (Ctrl + R)

이제 어떤 이유로 코드에서 이것을해야한다면 아마도 그렇게 할 수있을 것입니다 (이 질문을 찾은 방법입니다). 이 경우 코멘트에서 요청하십시오.


여기에 이미지 설명 입력


좋아, 방금 ShellShocks 답변 아래 0xA3의 의견을 읽었습니다. 문제가 될 것 같습니다. 코딩 된 솔루션으로 이동하기 전에 정규 표현식을 생각해 보겠습니다.
Mike Fuchs


2

조건부 정규식 으로 인해 두통이 생깁니다 . 그래서 여기에 검색 / 바꾸기를위한 코딩 된 솔루션이 있습니다 (가능한 한 EnvDTE를 피하고 있습니다).

순서는 프로젝트 파일 항목 에 중요하지 않은 것 같습니다 .

그 라인을 따라 무언가를 시도하십시오.

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;
        }
    }
}

1

매크로를 사용하여이 작업을 수행하거나 VS 프로젝트 파일이 텍스트 파일이라는 것을 기억할 수 있습니다. 즉, 간단한 전역 검색 및 바꾸기로 동일한 결과를 얻을 수 있으며 많은 프로젝트 파일을 동일하게 변경하는보다 일반적인 기술입니다.

먼저 기존 프로젝트 파일을 백업 한 다음 원하는대로 변경합니다 (예 : 대상 프레임 워크 변경). WinDiff 또는 WinMerge 를 사용하여 새 프로젝트 파일을 백업과 비교합니다. 이렇게하면 변경해야 할 사항을 알 수 있습니다. 그런 다음 Visual Studio IDE의 파일에서 찾기 및 바꾸기 기능을 사용하여 모든 프로젝트 파일을 변경합니다.


2
대상 프레임 워크를 지정하지 않은 프로젝트 파일 (예 : 원래 VS 2005에서 생성 된 파일)에 대해서는 단순 검색 및 바꾸기가 실패합니다. 이러한 프로젝트 파일의 경우 더 복잡한 검색 및 바꾸기 표현식으로 대상 프레임 워크 요소를 삽입 할 올바른 위치를 찾아야합니다.
Dirk Vollmar

0

외부 도구가없는 대안 (및 ToolsVersion과 같은 다른 설정을 변경할 수있는 기능) :

  1. Visual Studio를 사용하여 임시 디렉터리에 새 C # 콘솔 프로젝트 'ManageCSProjFiles'(또는 원하는 이름)를 만듭니다. '솔루션과 프로젝트를 같은 디렉터리에 배치'를 확인하십시오.
  2. 프로젝트에서 Program.cs 및 Properties / AssemblyInfo.cs를 제거합니다. 프로젝트를 컴파일 할 필요가 없습니다.
  3. 프로젝트를 저장하고 Visual Studio를 닫습니다.
  4. 텍스트 편집기를 사용하여 ManageCSProjFiles.csproj를 엽니 다. 마지막 줄 앞에 다음 줄을 맨 아래에 추가하십시오.
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. ManageCSProjFiles.sln 및 ManageCSProjFiles.csproj를 솔루션 트리의 최상위 디렉터리에 복사합니다.
  2. Visual Studio에서 ManageCSProjFiles 솔루션을로드하면 이제 모든 .csproj 파일이 표시되며 Visual Studio의 검색 / 바꾸기 도구를 사용하여 변경할 수 있습니다.

이것은 다른 프로젝트 유형에 대해 쉽게 확장 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.