185 lines
8.3 KiB
C#
185 lines
8.3 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Security;
|
|
using Microsoft.Internal.Web.Utils;
|
|
using Microsoft.Web.Infrastructure;
|
|
|
|
namespace System.Web.WebPages.Deployment
|
|
{
|
|
internal static class AssemblyUtils
|
|
{
|
|
// Copied from AssemblyRefs.cs
|
|
private const string SharedLibPublicKey = "31bf3856ad364e35";
|
|
|
|
internal static readonly AssemblyName ThisAssemblyName = new AssemblyName(typeof(AssemblyUtils).Assembly.FullName);
|
|
private static readonly Version WebPagesV1Version = new Version(1, 0, 0, 0);
|
|
private static readonly string _binFileName = Path.GetFileName(ThisAssemblyName.Name) + ".dll";
|
|
|
|
// Special case MWI because it does not share the same assembly version as the rest of WebPages.
|
|
private static readonly Version _mwiVersion = new AssemblyName(typeof(InfrastructureHelper).Assembly.FullName).Version;
|
|
|
|
private static readonly AssemblyName _mwiAssemblyName = GetFullName("Microsoft.Web.Infrastructure", _mwiVersion);
|
|
|
|
private static readonly AssemblyName[] _version1AssemblyList = new[]
|
|
{
|
|
_mwiAssemblyName,
|
|
GetFullName("System.Web.Razor", WebPagesV1Version),
|
|
GetFullName("System.Web.Helpers", WebPagesV1Version),
|
|
GetFullName("System.Web.WebPages", WebPagesV1Version),
|
|
GetFullName("System.Web.WebPages.Administration", WebPagesV1Version),
|
|
GetFullName("System.Web.WebPages.Razor", WebPagesV1Version),
|
|
GetFullName("WebMatrix.Data", WebPagesV1Version),
|
|
GetFullName("WebMatrix.WebData", WebPagesV1Version)
|
|
};
|
|
|
|
private static readonly AssemblyName[] _versionCurrentAssemblyList = new[]
|
|
{
|
|
_mwiAssemblyName,
|
|
GetFullName("System.Web.Razor", ThisAssemblyName.Version),
|
|
GetFullName("System.Web.Helpers", ThisAssemblyName.Version),
|
|
GetFullName("System.Web.WebPages", ThisAssemblyName.Version),
|
|
GetFullName("System.Web.WebPages.Administration", ThisAssemblyName.Version),
|
|
GetFullName("System.Web.WebPages.Razor", ThisAssemblyName.Version),
|
|
GetFullName("WebMatrix.Data", ThisAssemblyName.Version),
|
|
GetFullName("WebMatrix.WebData", ThisAssemblyName.Version)
|
|
};
|
|
|
|
internal static Version GetMaxWebPagesVersion()
|
|
{
|
|
return GetMaxWebPagesVersion(GetLoadedAssemblies());
|
|
}
|
|
|
|
internal static Version GetMaxWebPagesVersion(IEnumerable<AssemblyName> loadedAssemblies)
|
|
{
|
|
return GetWebPagesAssemblies(loadedAssemblies).Max(c => c.Version);
|
|
}
|
|
|
|
internal static bool IsVersionAvailable(Version version)
|
|
{
|
|
return IsVersionAvailable(GetLoadedAssemblies(), version);
|
|
}
|
|
|
|
internal static bool IsVersionAvailable(IEnumerable<AssemblyName> loadedAssemblies, Version version)
|
|
{
|
|
return GetWebPagesAssemblies(loadedAssemblies).Any(c => c.Version == version);
|
|
}
|
|
|
|
private static IEnumerable<AssemblyName> GetWebPagesAssemblies(IEnumerable<AssemblyName> loadedAssemblies)
|
|
{
|
|
return (from otherName in loadedAssemblies
|
|
where NamesMatch(ThisAssemblyName, otherName, matchVersion: false)
|
|
select otherName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the version of a System.Web.WebPages.Deployment.dll if it is present in the bin and matches the name and
|
|
/// public key token of the current assembly.
|
|
/// </summary>
|
|
/// <returns>Version from bin if present, null otherwise.</returns>
|
|
internal static Version GetVersionFromBin(string binDirectory, IFileSystem fileSystem, Func<string, AssemblyName> getAssemblyNameThunk = null)
|
|
{
|
|
// If a version of the assembly is present both in the bin and the GAC, the GAC would win.
|
|
// To work around this, we'll look for a physical file on disk with the same name as the current assembly and load it to determine the version.
|
|
// Determine if the Deployment assembly is present in the bin
|
|
var assemblyInBin = Path.Combine(binDirectory, _binFileName);
|
|
if (fileSystem.FileExists(assemblyInBin))
|
|
{
|
|
try
|
|
{
|
|
getAssemblyNameThunk = getAssemblyNameThunk ?? AssemblyName.GetAssemblyName;
|
|
AssemblyName assemblyName = getAssemblyNameThunk(assemblyInBin);
|
|
if (NamesMatch(ThisAssemblyName, assemblyName, matchVersion: false))
|
|
{
|
|
return assemblyName.Version;
|
|
}
|
|
}
|
|
catch (BadImageFormatException)
|
|
{
|
|
// Do nothing.
|
|
}
|
|
catch (SecurityException)
|
|
{
|
|
// Do nothing
|
|
}
|
|
catch (FileLoadException)
|
|
{
|
|
// Do nothing.
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal static bool NamesMatch(AssemblyName left, AssemblyName right, bool matchVersion)
|
|
{
|
|
return Equals(left.Name, right.Name) &&
|
|
Equals(left.CultureInfo, right.CultureInfo) &&
|
|
Enumerable.SequenceEqual(left.GetPublicKeyToken(), right.GetPublicKeyToken()) &&
|
|
(!matchVersion || Equals(left.Version, right.Version));
|
|
}
|
|
|
|
internal static IEnumerable<AssemblyName> GetLoadedAssemblies()
|
|
{
|
|
return AppDomain.CurrentDomain.GetAssemblies()
|
|
.Select(GetAssemblyName)
|
|
.ToList();
|
|
}
|
|
|
|
internal static IEnumerable<AssemblyName> GetAssembliesForVersion(Version version)
|
|
{
|
|
if (version == WebPagesV1Version)
|
|
{
|
|
return _version1AssemblyList;
|
|
}
|
|
return _versionCurrentAssemblyList;
|
|
}
|
|
|
|
private static AssemblyName GetAssemblyName(Assembly assembly)
|
|
{
|
|
return new AssemblyName(assembly.FullName);
|
|
}
|
|
|
|
private static AssemblyName GetFullName(string name, Version version, string publicKeyToken)
|
|
{
|
|
return new AssemblyName(String.Format(CultureInfo.InvariantCulture,
|
|
"{0}, Version={1}, Culture=neutral, PublicKeyToken={2}",
|
|
name, version, publicKeyToken));
|
|
}
|
|
|
|
internal static AssemblyName GetFullName(string name, Version version)
|
|
{
|
|
return GetFullName(name, version, SharedLibPublicKey);
|
|
}
|
|
|
|
public static IDictionary<string, Version> GetAssembliesMatchingOtherVersions(IDictionary<string, IEnumerable<string>> references)
|
|
{
|
|
var webPagesAssemblies = AssemblyUtils.GetAssembliesForVersion(AssemblyUtils.ThisAssemblyName.Version);
|
|
if (webPagesAssemblies == null || !webPagesAssemblies.Any())
|
|
{
|
|
return new Dictionary<string, Version>(0);
|
|
}
|
|
|
|
var matchingVersions = from item in references
|
|
let matchedVersion = GetMatchingVersion(webPagesAssemblies, item.Value)
|
|
where matchedVersion != null
|
|
select new KeyValuePair<string, Version>(item.Key, matchedVersion);
|
|
return matchingVersions.ToDictionary(k => k.Key, k => k.Value);
|
|
}
|
|
|
|
private static Version GetMatchingVersion(IEnumerable<AssemblyName> webPagesAssemblies, IEnumerable<string> references)
|
|
{
|
|
// Return assemblies that match in name but not in version.
|
|
var matchingVersions = from webPagesAssembly in webPagesAssemblies
|
|
from referenceName in references
|
|
let referencedAssembly = new AssemblyName(referenceName)
|
|
where AssemblyUtils.NamesMatch(webPagesAssembly, referencedAssembly, matchVersion: false) && webPagesAssembly.Version != referencedAssembly.Version
|
|
select referencedAssembly.Version;
|
|
return matchingVersions.FirstOrDefault();
|
|
}
|
|
}
|
|
}
|