Ubah Target Framework untuk semua proyek saya dalam solusi Visual Studio


104

Saya perlu mengubah kerangka target untuk semua proyek. Saya punya banyak solusi dengan ratusan proyek.

Ada yang baru di sini atau apakah saya harus mengubah setiap proyek?

Jawaban:


37

Anda dapat melakukannya menggunakan makro Visual Studio Scott Dorman yang tersedia di CodeProject:

Visual Studio 2010 dan Target Framework Version

Di bawah ini adalah kode, unduh ke <UserProfile>\Documents\Visual Studio 2010\Projects\VSMacros80\MyMacrosfolder Anda , buka Visual Studio Macro IDE (Alt-F11) dan tambahkan sebagai item yang sudah ada ke proyek "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 untuk kode, karena tautan pada CodeProject tampaknya tidak berfungsi lagi.
Hannele

81

Baru saja menerbitkan Migrator Kerangka Kerja Target , Ekstensi Visual Studio untuk mengubah beberapa proyek .Net Target Kerangka sekaligus


Ini belum bermain bola pada tahun 2013.
Jon Egerton

1
Hanya membutuhkan satu perubahan nomor versi dalam vsixmanifest untuk bekerja di VS 2013
Panagiotis Kanavos

Ekstensi ini adalah penghemat waktu nyata :)
penggabungan

3
Untuk VS2015: unduh, unzip, di vsixmanifest: ubah versi InstallationTarget ke 14.0 dan ketergantungan ke 4.6
Jeroen K

5
Versi baru dengan dukungan VS2015 dan 4.6 diunggah ke galeri.
Pavel Samokha

35

Skrip PowerShell yang biasa saya lakukan untuk saya. Memang 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
Bagus, tetapi di sistem saya, saya mendapat kesalahan script1.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policiesjadi saya menjalankan perintah set-executionpolicy remotesigneduntuk memperbaikinya.
kuncevic.dev

Yessirree, Bigb. Tidak dapat menjalankan skrip secara default pada sistem adalah kerumitan yang saya anggap remeh. Terima kasih telah menunjukkannya. Untuk semua Set-ExecutionPolicy RemoteSignedmemungkinkan Anda untuk menjalankan skrip PowerShell lokal tanpa menandatangani sertifikat. Untuk detailnya lihat di sini: technet.microsoft.com/en-us/library/ee176961.aspx
Russell B

2
Inilah yang sebenarnya saya cari selama ini. Solusi paling elegan dan fleksibel untuk mengubah semua file .proj tersebut.
Ole Viaud-Murat

1
Bagi saya, migrasi memodifikasi file proyek, app.configs, dan desainer
Tomas Kubes

10

Selalu ada yang sederhana. Editor teks yang layak seperti notepad ++ akan menyertakan fungsi temukan / ganti dalam file. Cukup cari string versi saat ini di file csproj / vbproj Anda:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

dan ganti dengan versi baru

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Ide bagus untuk check out dulu ...


1
Ini adalah cara terbaik yang saya temukan, saya menggunakan Sublime untuk mengubah semua
cuongle

7

Dari bash:

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

6

Saya pikir sejauh ini cara termudah untuk melakukan ini adalah menggunakan alat pencarian dan ganti. Ini adalah keuntungan jika mendukung regex.

Pasti ada cukup banyak di luar sana - yang pertama saya uji bekerja untuk saya, meskipun: http://www.ecobyte.com/replacetext/

Ada catatan yang mengatakan itu memiliki beberapa masalah di Win7, tetapi saya tidak mengalaminya.

Petunjuk langkah demi langkah di alat itu:

  1. Ganti | Tambahkan Grup | Beri nama (mis. "MyGroup")
  2. Klik kanan MyGroup | Tambahkan File ...
  3. Pilih sumber Anda (misalnya Gunakan Folder, telusuri folder root dari proyek yang ingin Anda ubah)
  4. Setel Filter Sertakan File jika perlu (mis. * .Csproj)
  5. Klik kanan baris di bawah Teks Asli | Edit Lanjutan ...
  6. Masukkan ekspresi reguler Anda di Kotak Teks Penelusuran (mis. <TargetFrameworkVersion>.*</TargetFrameworkVersion>)
  7. Pilih "Pencarian Ekspresi Reguler" di kotak kombo di bawah Teks Pencarian
  8. Masukkan Teks Pengganti (mis. <TargetFrameworkVersion>4.0</TargetFrameworkVersion>)
  9. Pilih pengaturan Tujuan dan Cadangan (akan membuat cadangan secara default)
  10. Mulai Mengganti (Ctrl + R)

Sekarang Jika karena alasan tertentu Anda perlu melakukan ini dalam kode, saya mungkin bisa melakukannya juga (begitulah cara saya menemukan pertanyaan ini). Dalam hal ini, silakan memintanya dalam komentar.


masukkan deskripsi gambar di sini


Ok, saya baru saja membaca komentar 0xA3 di bawah jawaban ShellShocks. Saya kira itu mungkin menjadi masalah. Saya akan mencoba menghasilkan ekspresi reguler untuk itu sebelum pergi ke solusi berkode.
Mike Fuchs


2

Regex bersyarat membuatku pusing. Jadi di sini adalah solusi berkode untuk pencarian / ganti (saya menghindari EnvDTE selama mungkin).

Urutan tampaknya tidak menjadi masalah untuk entri file proyek:

Cobalah sesuatu seperti itu:

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

Anda dapat menggunakan makro untuk melakukan ini, atau ingat bahwa file proyek VS adalah file teks, yang berarti pencarian dan penggantian global sederhana dapat mencapai hal yang sama, dan merupakan teknik yang lebih umum untuk membuat perubahan yang sama pada banyak file proyek.

Pertama, cadangkan file proyek yang ada, lalu buat perubahan yang Anda inginkan (misalnya, ubah kerangka target). Gunakan WinDiff atau WinMerge untuk membandingkan file proyek baru dengan cadangan. Ini akan memberi tahu Anda perubahan yang perlu Anda lakukan. Kemudian gunakan fungsi Find and Replace in Files Visual Studio IDE untuk membuat perubahan ke semua file proyek Anda.


2
Pencarian dan penggantian sederhana akan gagal untuk file proyek yang tidak menentukan kerangka kerja target (misalnya file yang aslinya dibuat pada VS 2005). Untuk file proyek seperti itu, Anda harus menemukan posisi yang benar untuk menyisipkan elemen kerangka kerja target dengan ekspresi pencarian & ganti yang lebih rumit.
Dirk Vollmar

0

Alternatif tanpa alat eksternal (dan kemampuan untuk mengubah pengaturan lain, misalnya ToolsVersion):

  1. Menggunakan Visual Studio, buat proyek konsol c # baru 'ManageCSProjFiles' (atau nama apa pun yang Anda suka) di direktori sementara. Pastikan untuk memeriksa 'Tempatkan solusi dan proyek dalam direktori yang sama'
  2. Hapus Program.cs dan Properties / AssemblyInfo.cs dari proyek. Tidak perlu mengkompilasi proyek.
  3. Simpan proyek dan tutup Visual Studio.
  4. Menggunakan editor teks, buka ManageCSProjFiles.csproj. Tambahkan baris berikut di bagian bawah, sebelum baris terakhir:
  <ItemGroup>
    <None Include="**\*.csproj" />
  </ItemGroup>
  1. Salin ManageCSProjFiles.sln dan ManageCSProjFiles.csproj ke direktori paling atas dari pohon solusi Anda.
  2. Jika Anda memuat solusi ManageCSProjFiles di Visual Studio, sekarang akan menampilkan semua file .csproj Anda dan Anda dapat mengubahnya dengan alat cari / ganti di Visual Studio.

Ini dapat dengan mudah diperpanjang untuk jenis proyek lainnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.