Thay đổi Khung mục tiêu cho tất cả các dự án của tôi trong Giải pháp Visual Studio


104

Tôi cần thay đổi khung mục tiêu cho tất cả các dự án. Tôi có nhiều giải pháp với hàng trăm dự án.

Có gì mới ở đây không hay tôi phải thay đổi từng dự án?

Câu trả lời:


37

Bạn có thể làm điều đó bằng cách sử dụng macro Visual Studio của Scott Dorman có sẵn trên CodeProject:

Visual Studio 2010 và phiên bản khung mục tiêu

Dưới đây là mã, hãy tải nó xuống <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacrosthư mục của bạn , mở Visual Studio Macro IDE (Alt-F11) và thêm nó làm mục hiện có vào dự án “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 cho mã, vì liên kết trên CodeProject dường như không hoạt động nữa.
Hannele

81

Vừa mới xuất bản Target Framework Migrator , Visual Studio Extension để thay đổi nhiều dự án .Net Target Framework cùng một lúc


Đây không phải là bóng vào năm 2013.
Jon Egerton

1
Chỉ cần một lần thay đổi số phiên bản duy nhất trong vsixmanifest để hoạt động trong VS 2013
Panagiotis Kanavos

Phần mở rộng này là một trình tiết kiệm thời gian thực sự :)
hợp nhất

3
Đối với VS2015: tải xuống, giải nén, trong vsixmanifest: thay đổi phiên bản InstallTarget thành 14.0 và phụ thuộc thành 4.6
Jeroen K

5
Phiên bản mới với hỗ trợ VS2015 và 4.6 được tải lên thư viện.
Pavel Samokha

35

Một tập lệnh PowerShell mà tôi đã từng sử dụng. Phải thừa nhận rằng lực lượng-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
Tuyệt vời nhưng trên hệ thống của tôi, tôi gặp lỗi script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policiesnên tôi chạy lệnh set-executionpolicy remotesignedđể sửa lỗi đó.
kuncevic.dev

Yessirree, bigb. Không thể chạy các tập lệnh theo mặc định trên một hệ thống là một rắc rối mà tôi chỉ coi đó là điều hiển nhiên. Cảm ơn vì đã chỉ ra điều đó. Đối với tất cả, tất cả Set-ExecutionPolicy RemoteSignedcho phép bạn chạy các tập lệnh PowerShell cục bộ với việc ký chứng chỉ cho chúng. Để biết chi tiết, xem tại đây: technet.microsoft.com/en-us/library/ee176961.aspx
Russell B

2
Đây chính xác là những gì tôi đã tìm kiếm. Giải pháp thanh lịch và linh hoạt nhất để thay đổi tất cả các tệp .proj đó.
Ole Viaud-Murat

1
Đối với tôi, Sửa di cư dự án tác phẩm, app.configs và nhà thiết kế
Tomas Kubes

10

Luôn luôn có những điều đơn giản. Một trình soạn thảo văn bản tốt như notepad ++ sẽ bao gồm chức năng tìm / thay thế trong tệp. Chỉ cần tìm kiếm chuỗi phiên bản hiện tại trong tệp csproj / vbproj của bạn:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

và thay thế bằng phiên bản mới

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Tuy nhiên, ý tưởng hay là hãy kiểm tra trước ...


1
Đây là cách tốt nhất mà tôi thấy, tôi đã sử dụng Sublime thay đổi tất cả
Cuongle

7

Từ bash:

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

6

Tôi nghĩ cách dễ nhất để làm điều này là sử dụng công cụ tìm kiếm và thay thế. Đó là một lợi thế nếu nó hỗ trợ regex.

Chắc hẳn có khá nhiều thứ ngoài kia - cái đầu tiên tôi thử nghiệm phù hợp với tôi, tuy nhiên: http://www.ecobyte.com/replacetext/

Có một ghi chú nói rằng nó có một số vấn đề trên Win7, nhưng tôi không gặp phải vấn đề đó.

Hướng dẫn từng bước trong công cụ đó:

  1. Thay thế | Thêm nhóm | Đặt tên cho nó (ví dụ: "MyGroup")
  2. Nhấp chuột phải vào MyGroup | Thêm các tập tin)...
  3. Chọn nguồn của bạn (ví dụ: Sử dụng Thư mục, duyệt đến thư mục gốc của các dự án bạn muốn thay đổi)
  4. Đặt Bộ lọc Tệp Bao gồm nếu cần (ví dụ: * .csproj)
  5. Bấm chuột phải vào hàng bên dưới Văn bản gốc | Chỉnh sửa nâng cao ...
  6. Nhập biểu thức chính quy của bạn vào Hộp văn bản tìm kiếm (ví dụ <TargetFrameworkVersion>.*</TargetFrameworkVersion>:)
  7. Chọn "Tìm kiếm Cụm từ Thông dụng" trong hộp tổ hợp bên dưới Văn bản Tìm kiếm
  8. Nhập Văn bản Thay thế (ví dụ <TargetFrameworkVersion>4.0</TargetFrameworkVersion>)
  9. Chọn cài đặt Đích và Sao lưu (sẽ tạo một bản sao lưu theo mặc định)
  10. Bắt đầu thay thế (Ctrl + R)

Bây giờ Nếu vì lý do nào đó bạn cần làm điều này trong mã, tôi có thể cũng có thể làm điều đó (đó là cách tôi tìm thấy câu hỏi này). Trong trường hợp đó, vui lòng yêu cầu nó trong một bình luận.


nhập mô tả hình ảnh ở đây


Ok, tôi vừa đọc nhận xét của 0xA3 bên dưới câu trả lời của ShellShocks. Tôi cho rằng đó có thể là một vấn đề. Tôi sẽ cố gắng đưa ra một biểu thức chính quy cho nó trước khi đi đến giải pháp mã hóa.
Mike Fuchs


2

Regex có điều kiện có đang làm tôi đau đầu. Vì vậy, đây là một giải pháp được mã hóa để tìm kiếm / thay thế (Tôi tránh EnvDTE càng lâu càng tốt).

Thứ tự dường như không quan trọng đối với các mục nhập tệp dự án:

Hãy thử một cái gì đó dọc theo những dòng đó:

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

Bạn có thể sử dụng macro để thực hiện việc này hoặc nhớ rằng tệp dự án VS là tệp văn bản, có nghĩa là tìm kiếm toàn cục và thay thế đơn giản có thể đạt được kết quả tương tự và là một kỹ thuật chung hơn để thực hiện cùng một thay đổi đối với nhiều tệp dự án.

Đầu tiên hãy sao lưu tệp dự án hiện có, sau đó thực hiện thay đổi bạn muốn (ví dụ: thay đổi khung mục tiêu). Sử dụng WinDiff hoặc WinMerge để so sánh tệp dự án mới với bản sao lưu. Điều này sẽ cho bạn biết thay đổi bạn cần thực hiện. Sau đó, sử dụng chức năng Tìm và Thay thế trong Tệp của Visual Studio IDE để thực hiện thay đổi đối với tất cả các tệp dự án của bạn.


2
Một tìm kiếm và thay thế đơn giản sẽ không thành công đối với các tệp dự án không chỉ định khung đích (ví dụ: tệp được tạo ban đầu trong VS 2005). Đối với các tệp dự án như vậy, bạn sẽ phải tìm vị trí chính xác để chèn phần tử khung mục tiêu với biểu thức tìm kiếm & thay thế phức tạp hơn.
Dirk Vollmar

0

Một giải pháp thay thế không có công cụ bên ngoài (và khả năng thay đổi các cài đặt khác, ví dụ: ToolsVersion):

  1. Sử dụng Visual Studio, tạo một dự án bảng điều khiển c # mới 'ManageCSProjFiles' (hoặc bất kỳ tên nào bạn thích) trong một thư mục tạm thời. Hãy chắc chắn kiểm tra 'Đặt giải pháp và dự án trong cùng một thư mục'
  2. Loại bỏ Program.cs và Thuộc tính / AssemblyInfo.cs khỏi dự án. Không cần phải biên dịch dự án.
  3. Lưu dự án và đóng Visual Studio.
  4. Sử dụng trình soạn thảo văn bản, mở ManageCSProjFiles.csproj. Thêm các dòng sau vào cuối, trước dòng cuối cùng:
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. Sao chép ManageCSProjFiles.sln và ManageCSProjFiles.csproj vào thư mục trên cùng của cây giải pháp của bạn.
  2. Nếu bạn tải giải pháp ManageCSProjFiles trong Visual Studio, bây giờ nó sẽ hiển thị tất cả các tệp .csproj của bạn và bạn có thể thay đổi chúng bằng các công cụ tìm kiếm / thay thế trong Visual Studio.

Điều này có thể dễ dàng được mở rộng cho các loại dự án khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.