13

多数のプロジェクト ファイルを含む大規模な Visual Studio ソリューションがあります。すべてのプロジェクトがプロパティ設定で特定の規則に従っていることを確認し、新しいプロジェクトが追加された場合にこれらの規則を適用するにはどうすればよいでしょうか。たとえば、すべてのプロジェクトに以下があることを確認します。

TargetFrameworkVersion = "v4.5"
Platform = "AnyCPU"
WarningLevel = 4
TreatWarningsAsErrors = true
OutputPath = $(SolutionDir)bin
SignAssembly = true
AssemblyName = $(ProjectFolderName)

私自身、以下の回答に追加する 2 つの方法を知っていますが、人々がこの種のプロジェクト テストをどのように行っているのか疑問に思っていました。新しいものを発明したり、ゼロから作成したりする必要があるのではなく、ライブラリやビルドタスクなどの利用可能なソリューションについて学ぶことに特に興味があります。

4

10 に答える 10

6

次の一覧は、Visual Studio .NET 統合開発環境 (IDE) を使用してソリューションがソース管理に追加されたときに、VSS に自動的に追加される主要なファイルの種類を示しています。

ソリューション ファイル ( .sln)。これらのファイル内に維持される重要な項目には、構成プロジェクトのリスト、依存関係情報、ビルド構成の詳細、およびソース管理プロバイダーの詳細が含まれます。プロジェクト ファイル ( .csproj または *.vbproj)。これらのファイル内で維持される重要な項目には、アセンブリ ビルド設定、参照アセンブリ (名前とパスによる)、およびファイル インベントリが含まれます。アプリケーション構成ファイル。これらは、プロジェクトの実行時の動作のさまざまな側面を制御するために使用される拡張マークアップ言語 (XML) に基づく構成ファイルです。

可能な限り単一のソリューション モデルを使用する

参照: https://msdn.microsoft.com/en-us/library/ee817677.aspxhttps://msdn.microsoft.com/en-us/library/ee817675.aspx

および継続的な統合の場合: MSBuild、Jenkins、Apache の Continuum、Cruise Control (CC)、および Hudson (プラグインは c# に拡張可能) などの多くのツールが利用可能です。

于 2015-10-15T05:52:27.567 に答える
4

まったく別のことを試してみましょう。テンプレートから生成するか、 CMakeなどのビルド生成ツールを使用することで、構築によって一貫性を保つことができます。これは、事後に一貫性を持たせようとするよりも簡単かもしれません。

于 2015-10-16T15:22:12.143 に答える
4

私たちの仕事では、プロジェクト設定をチェックし、それらが正しくない場合は変更する powershell スクリプトを使用します。たとえば、この方法でデバッグ構成を削除し、C++ 最適化と SSE2 サポートを無効にします。手動で実行しますが、ビルド前/後ステップなどで自動的に実行することも可能です。

例の下:

`function Prepare-Solution {  
param (  
    [string]$SolutionFolder
)  
$files = gci -Recurse -Path $SolutionFolder -file *.vcxproj | select -    ExpandProperty fullname  
$files | %{  
    $file = $_  
    [xml]$xml = get-content $file  

    #Deleting Debug configurations...
    $xml.Project.ItemGroup.ProjectConfiguration | ?{$_.Configuration -eq "Debug"} | %{$_.ParentNode.RemoveChild($_)} | Out-Null
    $xml.SelectNodes("//*[contains(@Condition,'Debug')]") |%{$_.ParentNode.RemoveChild($_)} | Out-Null

    if($xml.Project.ItemDefinitionGroup.ClCompile) {  
        $xml.Project.ItemDefinitionGroup.ClCompile | %{  
            #Disable SSE2
            if (-not($_.EnableEnhancedInstructionSet)){
                $_.AppendChild($xml.CreateElement("EnableEnhancedInstructionSet", $xml.DocumentElement.NamespaceURI)) | Out-Null  
            }   

            if($_.ParentNode.Condition.Contains("Win32")){  
                $_.EnableEnhancedInstructionSet = "StreamingSIMDExtensions"
            }
            elseif($_.ParentNode.Condition.Contains("x64")) {
                $_.EnableEnhancedInstructionSet = "NotSet"
            } else {
                Write-Host "Neither x86 nor x64 config. Very strange!!"
            }

            #Disable Optimization
            if (-not($_.Optimization)){  
                $_.AppendChild($xml.CreateElement("Optimization", $xml.DocumentElement.NamespaceURI)) | Out-Null  
            }   
            $_.Optimization = "Disabled" 
        } 
    } 
    $xml.Save($file);  
} }`
于 2015-10-16T23:44:09.187 に答える
4

ソリューションをテキスト ファイルとして開き、参照されているすべての csproj ファイルを識別し、次にこれらのファイルをそれぞれ xml ファイルとして開き、ユニット テストを記述して、プロジェクトの特定のノードが期待どおりであることを確認するコードを記述できます。

これは簡単で汚いソリューションですが、CI で機能し、気にしないノードを無視する柔軟性を提供します。それは実際にはちょっと便利に聞こえます。私もスキャンしたい35のプロジェクトを含むソリューションがあります。

于 2015-10-12T19:02:35.963 に答える
4

これは私が自分自身を持っているものです:

これを行う 1 つの方法は、エラー条件を含む MSBuild ターゲットを作成することです。

<Error Condition="'$(TreatWarningsAsErrors)'!='true'" Text="Invalid project setting" />

このアプローチは MSBuild と統合されており、早期にエラーが発生するので気に入っていますが、すべてのプロジェクトを変更してプロジェクトにインポートするか、すべてのチーム メンバーに、カスタム プレフィックスを挿入する環境変数を含む特別なコマンド プロンプトを使用させる必要があります。ビルド中にプロジェクトにステップを組み込むのは面倒です。

私が知っている 2 番目のアプローチは、テストできるプロパティをプロジェクトするためのAPIを提供するVSUnitTestのようなライブラリを使用することです。VSUnitTest は現在、オープン ソースではなく、NuGet サービスからリストされていません。

于 2015-10-03T23:53:05.343 に答える
3

ファイルが管理されていて、そのメタデータにアセンブリ エントリが含まれている場合に限り、ファイルはアセンブリです。アセンブリとメタデータの詳細については、アセンブリ マニフェストのトピックを参照してください。

ファイルがアセンブリかどうかを手動で判断する方法

  1. Ildasm.exe(IL 逆アセンブラー)を開始します。
  2. テストするファイルをロードします。
  3. ファイルがポータブル実行可能 (PE) ファイルではないことが ILDASM によって報告された場合、そのファイルはアセンブリではありません。
    詳細については、トピック「方法: アセンブリの内容を表示する」を参照してください。

ファイルがアセンブリかどうかをプログラムで判断する方法

  1. GetAssemblyNameテストするファイルの完全なファイル パスと名前を渡して、メソッドを呼び出します。
  2. 例外がスローされた場合BadImageFormatException、ファイルはアセンブリではありません。

この例では、DLL がアセンブリであるかどうかをテストします。

class TestAssembly
{
static void Main()
   {

    try
    {
        System.Reflection.AssemblyName testAssembly = System.Reflection.AssemblyName.GetAssemblyName(@"C:\Windows\Microsoft.NET\Framework\v3.5\System.Net.dll");

        System.Console.WriteLine("Yes, the file is an assembly.");
    }

    catch (System.IO.FileNotFoundException)
    {
        System.Console.WriteLine("The file cannot be found.");
    }

    catch (System.BadImageFormatException)
    {
        System.Console.WriteLine("The file is not an assembly.");
    }

    catch (System.IO.FileLoadException)
    {
        System.Console.WriteLine("The assembly has already been loaded.");
    }
   }
}
  // Output (with .NET Framework 3.5 installed):
 // Yes, the file is an assembly.

Framework はインストールされている最上位のバージョンで、SP はそのバージョンのサービス パックです。

  RegistryKey installed_versions =   Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP");
  string[] version_names = installed_versions.GetSubKeyNames();
  //version names start with 'v', eg, 'v3.5' which needs to be trimmed off    before conversion
  double Framework = Convert.ToDouble(version_names[version_names.Length - 1].Remove(0, 1), CultureInfo.InvariantCulture);
  int SP =  Convert.ToInt32(installed_versions.OpenSubKey(version_names[version_names.Length     - 1]).GetValue("SP", 0));

 For .Net 4.5


 using System;
 using Microsoft.Win32;


 ...


 private static void Get45or451FromRegistry()
{
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,    RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework  Setup\\NDP\\v4\\Full\\")) {
    int releaseKey = Convert.ToInt32(ndpKey.GetValue("Release"));
    if (true) {
        Console.WriteLine("Version: " + CheckFor45DotVersion(releaseKey));
     }
   }
 }


 ...


// Checking the version using >= will enable forward compatibility,  
// however you should always compile your code on newer versions of 
// the framework to ensure your app works the same. 
private static string CheckFor45DotVersion(int releaseKey)
{
if (releaseKey >= 393273) {
   return "4.6 RC or later";
}
if ((releaseKey >= 379893)) {
    return "4.5.2 or later";
}
if ((releaseKey >= 378675)) {
    return "4.5.1 or later";
}
if ((releaseKey >= 378389)) {
    return "4.5 or later";
}
// This line should never execute. A non-null release key should mean 
// that 4.5 or later is installed. 
return "No 4.5 or later version detected";
}
于 2015-10-13T11:37:13.793 に答える
1

手書きの C#、スクリプト、powershell などを使用して、正規表現の検索と置換を行うことができます。しかし、以下の問題があります。

  • 読みにくい(きれいな正規表現を 3 か月以上かけて読む)
  • 拡張が困難(新しい検索/置換/チェック機能の新しい正規表現)
  • 壊れやすい(ms ビルド プロジェクトの新しいリリース/形式または予測されないタグが機能しない可能性があります)
  • テストが困難(意図しない一致が発生しないことを確認する必要があります)
  • 維持するのが難しい(上記のため)

次の利点があります。

  • あらゆる種類のプロジェクト (モノラルまたはビジュアル) で動作させる (可能性がある)追加の検証を行いません。
  • 気にしません\r :)

最善の方法は、Microsoft.Build.Evaluationを使用して、 すべてのテスト/チェック/修正などを行う C# ツールをビルドすることです。

ソースファイルリスト(Monoで使用)を使用し、 csprojのソースを更新するコマンドラインツールと、csprojのコンテンツをコンソールにダンプする別のコマンドラインツールを作成しました。簡単に実行でき、非常に簡単で、テストも簡単でした。

ただし、「非」Ms ツール (Mono Studio など) によって変更されたプロジェクト、または\rがないために失敗する可能性があります (私が経験したように) 。良いメッセージ。

Microsoft.Build.dll を使用したサンプルを次に示します (廃止されているため、Microsof.Build.Engine は使用しないでください)。

using System;
using Microsoft.Build.Evaluation;

internal class Program
{
    private static void Main(string[] args)
    {
        var project = new Project("PathToYourProject.csproj");
        Console.WriteLine(project.GetProperty("TargetFrameworkVersion", true, string.Empty));
        Console.WriteLine(project.GetProperty("Platform", true, string.Empty));
        Console.WriteLine(project.GetProperty("WarningLevel", true, string.Empty));
        Console.WriteLine(project.GetProperty("TreatWarningsAsErrors", true, "false"));
        Console.WriteLine(project.GetProperty("OutputPath", false, string.Empty));
        Console.WriteLine(project.GetProperty("SignAssembly", true, "false"));
        Console.WriteLine(project.GetProperty("AssemblyName", false, string.Empty));
        Console.ReadLine();
    }
}

public static class ProjectExtensions
{
    public static string GetProperty(this Project project, string propertyName, bool afterEvaluation, string defaultValue)
    {
        var property = project.GetProperty(propertyName);
        if (property != null)
        {
            if (afterEvaluation)
                return property.EvaluatedValue;
            return property.UnevaluatedValue;
        }
        return defaultValue;
    }
}
于 2015-10-17T14:32:19.247 に答える
1

同様の目的で、次のように、プロジェクト間で共有したい共通のプロパティを持つカスタム MSBuild フラグメントを使用します ( build.common.propsファイル)。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
    <PlatformToolset>v90</PlatformToolset>
    <OutputPath>$(SolutionDir)..\bin\$(PlatformPath)\$(Configuration)\</OutputPath>

   <!-- whatever you need here -->
  </PropertyGroup>

</Project>

そして、これらのプロパティを適用したい実際の VS プロジェクトにこのフラグメントを含めます。

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <CommonProps>$(SolutionDir)..\Build\build.common.props</CommonProps>
  </PropertyGroup>

  <Import Project="$(CommonProps)" />

  <!-- the rest of the project -->

</Project>

このアプローチを使用して多くのことを処理します。

  • あなたが言及したように、共通のプロパティ
  • 静的分析 (FxCop、StyleCop)
  • アセンブリのデジタル署名

これらの MSBuild フラグメントを各プロジェクト ファイルに含める必要があるという唯一の欠点がありますが、それを行うと、管理と更新が容易なモジュラー ビルド システムのすべての利点が得られます。

于 2015-10-17T14:48:10.033 に答える
0

私もこの問題に直面し、詳細を含む csv ファイルを作成して矛盾を特定する小さなソリューションを作成しました。こちらのURLで見れます

https://github.com/gdlmanuv/VSProjectConsistencyChecker

于 2022-02-18T17:45:09.863 に答える