3

これに関連するSOの質問を調べましたが、この問題に関する質問が見つからなかったため、この質問をしています.

AfterBuildタイプ名を検証するためのビルドタスク(ターゲットとして追加)があります。これらの型名は、ビルド中の Silverlight プロジェクトからの完全修飾型名です。

これらの型名を解決するには、 を使用しますType.ReflectionOnlyGetType()。依存アセンブリをロードするには、AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolveイベントを処理して、プロジェクト出力パスからプロジェクト固有のアセンブリをロードし、Silverlight インストール パスから Silverlight ベース アセンブリをロードしますAssembly.ReflectionOnlyLoadFrom(filepath)

VS2010でプロジェクトをビルドすると、これは完全に正常に機能しますが、MSBuild でビルドすると失敗しますC:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "C:\Root\branches\x.x.x\clients.sln" /t:rebuild /p:Configuration=Debug "/p:Platform=Any CPU" /v:quiet /maxcpucount:1

MSBuild でビルド中にReflectionOnlyAssemblyResolveイベントが発生し"System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"、これは Silverlight インストール パスから読み込まれました。しかし、プローブは でこのシステム アセンブリを試行していますが"C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/System.DLL"、メジャー バージョンが一致しないため失敗します。

以下は、この問題に固有のコードの削除されたバージョンです。

  public class ValidateTypeTask : Task
  {
       public override bool Execute()
       {
            Initialize();

            List<string> typeNames = GetTypes();
            foreach (var typeName in typeNames)
            {
                var isResolved = IsResolvable(typeName);
                if (!isResolved)
                {
                    return false;
                }
            }

            CleanUp();

            return true;
        }

        private void Initialize()
        {
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
        }

        Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
        {
            Assembly loadedAssembly = null;
            Exception loadedException = null;
            try
            {
                loadedAssembly = Assembly.ReflectionOnlyLoad(args.Name);//this will fail always
            }
            catch (Exception ex)
            {
                loadedException = ex;
            }

            if (loadedAssembly != null)
            {
                return loadedAssembly;
            }

            string assemblyPath = string.Empty;
            var assemblyName = new AssemblyName(args.Name);
            if (args.Name.StartsWith("System"))
            {
                assemblyPath = @"c:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0";
            }
            else
            {
                assemblyPath = @"C:\Root\branches\x.x.x\bin\debug";
            }
            assemblyPath = string.Format(@"{0}\{1}.dll", assemblyPath, assemblyName.Name);
            if (File.Exists(assemblyPath))
            {
                loadedAssembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
            }

            if (loadedAssembly == null)
            {
                throw loadedException;
            }

            return loadedAssembly;
        }
        private void CleanUp()
        {
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
        }
        private List<string> GetTypes()
        {
            return new List<string>();
        }
        private bool IsResolvable(string typeName)
        {
            Type resolvedType = null;
            try
            {
                resolvedType = Type.ReflectionOnlyGetType(typeName, true, true);
            }
            catch (Exception ex)
            {
            }

            if (resolvedType != null)
            {
                return true;
            }

            return false;
        }
    }

私が得る例外は次のとおりです。

  System.IO.FileLoadException: Could not load file or assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  File name: 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
  at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
  at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
  at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
  at System.Type.ReflectionOnlyGetType(String typeName, Boolean throwIfNotFound, Boolean ignoreCase)
  at  in c:\root\x.xx.x\BuildTasks\ValidateTypesTask.cs line xxx

  Assembly manager loaded from:  C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\clr.dll
  Running under executable  C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe
  --- A detailed error log follows. 

  === Pre-bind state information ===
  LOG: User = domain\username
  LOG: DisplayName = System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
  (Fully-specified)
  LOG: Appbase = file:///C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/
  LOG: Initial PrivatePath = NULL
  Calling assembly : (Unknown).
  ===
  LOG: This is an inspection only bind.
  LOG: Using application configuration file: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe.Config
  LOG: Using host configuration file: 
  LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
  LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/System.DLL.
  WRN: Comparing the assembly name resulted in the mismatch: Major Version
  ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

また、Silverlight アセンブリ パスを AssemblySearchPaths プロジェクト プロパティに含めて、これをプローブ URL の一部にし、同じにすることも試みました。

4

2 に答える 2

1

これは、私が上に投稿した問題に対する答えではないと確信しています。でも、これで解決しました。

フォーラムとドキュメントを調べたところ、DEVENV と MSBUILD の基本的な違いがわかりました。MSBuild でビルドすると、Devenv よりも厳密にアセンブリ解決が行われます。

また、私は と の違いを経験しましAssembly.LoadFromAssembly.ReflectionOnlyLoadFromAssembly.RefelectionOnlyLoadFromファイル名だけを考慮し、バージョンなどをチェックしません。これは、MSBuild が .Net 4.0 スタックから System.dll をロードしていた場所で、Silverlight インストール パスから System.dll をロードする必要があるためです。

これらすべてを念頭に置いて、型を解決するためにAssembly.LoadFromおよび を使用してアセンブリをロードしようとしました。Type.GetType今回は、ロードされたすべてのアセンブリに対してイベントが繰り返しトリガーさStackOverflowExceptionれたため、私は遭遇しました。AssemblyResolve

これは、読み込まれたアセンブリをアンロードできるように、アセンブリを別の appdomain に読み込むことを考えたときです。この記事は非常に役に立ち、同様のパターンに従って問題を解決しました。

解決済みの問題は手元にありますが、この回答でポイントを獲得したくありません。私はまだ、MSBuild の問題に対する答えを提供していないと感じています。

これが他の人に役立つことを願っています。

于 2012-02-09T11:28:42.757 に答える
0

基本クラスとして AppDomainIsolatedTask を使用することを検討し、再試行してください。これにより、アセンブリが msbuild AppDomain に読み込まれないため、アセンブリの処理が非常に簡単になります。

これにより、イベント呼び出しが独自の AppDomain に分離されます。したがって、MsBuild も邪魔することはできません。

于 2016-06-08T19:15:25.967 に答える