/// <summary> /// Given a root path and a set of native asset paths, tries to see if /// the files exist and if they do, sets <see cref="IcuVersion"/>. /// </summary> /// <param name="baseDirectory">Root path to append asset paths to.</param> /// <param name="nativeAssetPaths">Set of native asset paths to check.</param> /// <returns>true if it was able to find the directory for all the asset /// paths given; false otherwise.</returns> private static bool TrySetIcuPathFromDirectory(DirectoryInfo baseDirectory, string[] nativeAssetPaths) { if (nativeAssetPaths == null || nativeAssetPaths.Length == 0) { return(false); } Trace.WriteLine("Assets: " + Environment.NewLine + string.Join(Environment.NewLine + "\t-", nativeAssetPaths)); var assetPaths = nativeAssetPaths .Select(asset => new FileInfo(Path.Combine(baseDirectory.FullName, asset))); var fileInfos = assetPaths.ToList(); var doAllAssetsExistInDirectory = fileInfos.All(x => x.Exists); if (doAllAssetsExistInDirectory) { var directories = fileInfos.Select(file => file.Directory).ToArray(); if (directories.Length > 1) { Trace.TraceWarning($"There are multiple directories for these runtime assets: {string.Join(Path.PathSeparator.ToString(), directories.Select(x => x.FullName))}. There should only be one... Using first directory."); } var icuDirectory = directories.First(); if (TryGetIcuVersionNumber(icuDirectory, out int version)) { IcuVersion = new IcuVersionInfo(icuDirectory, version); } } return(doAllAssetsExistInDirectory); }
/// <summary> /// Tries to get path and version to Icu when running on .NET Core or Windows. /// </summary> /// <returns>The path and version of icu binaries if found. Check /// <see cref="IcuVersionInfo.Success"/> to see if the values were set.</returns> public static IcuVersionInfo GetIcuVersionInfoForNetCoreOrWindows() { // We've already tried to set the path to native assets. Don't try again. if (IcuVersion != null) { return(IcuVersion); } // Set the default to IcuVersion with an empty path and no version set. IcuVersion = new IcuVersionInfo(); if (TryGetPathFromAssemblyDirectory()) { return(IcuVersion); } // That's odd.. I guess we use normal search paths from %PATH% then. // One possibility is that it is not a dev machine and the application // is a published app... but then it should have returned true in // TryGetPathFromAssemblyDirectory. if (string.IsNullOrEmpty(NugetPackageDirectory)) { Trace.TraceWarning($"{nameof(NugetPackageDirectory)} is empty and application was unable to set path from current assembly directory."); return(IcuVersion); } #if !NET40 var context = DependencyContext.Default; // If this is false, something went wrong. These files should have // either been found above or we should have been able to locate the // asset paths (for .NET Core and NuGet v3+ projects). if (!TryGetNativeAssetPaths(context, out string[] nativeAssetPaths))
private static bool TryPreferredDirectory() { if (string.IsNullOrEmpty(NativeMethods.PreferredDirectory)) { return(false); } var preferredDirectory = new DirectoryInfo(NativeMethods.PreferredDirectory); if (TryGetIcuVersionNumber(preferredDirectory, out var version)) { IcuVersion = new IcuVersionInfo(preferredDirectory, version); return(true); } return(false); }
/// <summary> /// Tries to set the native library using the <see cref="NativeMethods.DirectoryOfThisAssembly"/> /// as the root directory. The following scenarios could happen: /// 1. {directoryOfAssembly}/icu*.dll /// Occurs when the project is published using the .NET Core CLI /// against the full .NET framework. /// 2. {directoryOfAssembly}/lib/{arch}/icu*.dll /// Occurs when the project is using NuGet v2, the traditional /// .NET Framework csproj or the new VS2017 projects. /// 3. {directoryOfAssembly}/runtimes/{runtimeId}/native/icu*.dll /// Occurs when the project is published using the .NET Core CLI. /// If one of the scenarios match, sets the <see cref="IcuVersion"/>. /// </summary> /// <returns>True if it was able to find the icu binaries within /// <see cref="NativeMethods.DirectoryOfThisAssembly"/>, false otherwise. /// </returns> private static bool TryGetPathFromAssemblyDirectory() { var assemblyDirectory = new DirectoryInfo(NativeMethods.DirectoryOfThisAssembly); // 1. Check in {assemblyDirectory}/ if (TryGetIcuVersionNumber(assemblyDirectory, out var version)) { IcuVersion = new IcuVersionInfo(assemblyDirectory, version); return(true); } // 2. Check in {assemblyDirectory}/lib/*{architecture}*/ var libDirectory = Path.Combine(assemblyDirectory.FullName, "lib"); if (Directory.Exists(libDirectory)) { var candidateDirectories = Directory .EnumerateDirectories(libDirectory, $"*{Platform.ProcessArchitecture}*") .Select(x => new DirectoryInfo(x)); foreach (var directory in candidateDirectories) { if (TryGetIcuVersionNumber(directory, out version)) { IcuVersion = new IcuVersionInfo(directory, version); return(true); } } } string[] nativeAssetPaths = null; #if !NET40 // 3. Check in {directoryOfAssembly}/runtimes/{runtimeId}/native/ if (!TryGetNativeAssetPaths(DependencyContext.Default, out nativeAssetPaths)) { Trace.WriteLine("Could not locate icu native assets from DependencyModel."); return(false); } #endif // If we found the icu*.dll files under {directoryOfAssembly}/runtimes/{rid}/native/, // they should ALL be there... or else something went wrong in publishing the app or // restoring the files, or packaging the NuGet package. // ReSharper disable once ExpressionIsAlwaysNull return(TrySetIcuPathFromDirectory(assemblyDirectory, nativeAssetPaths)); }
/// <summary> /// Tries to get path and version to Icu when running on .NET Core or Windows. /// </summary> /// <returns>The path and version of icu binaries if found. Check /// <see cref="IcuVersionInfo.Success"/> to see if the values were set.</returns> public static IcuVersionInfo GetIcuVersionInfoForNetCoreOrWindows() { // We've already tried to set the path to native assets. Don't try again. if (IcuVersion != null) { return(IcuVersion); } // Set the default to IcuVersion with an empty path and no version set. IcuVersion = new IcuVersionInfo(); if (TryPreferredDirectory()) { return(IcuVersion); } if (TryGetPathFromAssemblyDirectory()) { return(IcuVersion); } // That's odd.. I guess we use normal search paths from %PATH% then. // One possibility is that it is not a dev machine and the application // is a published app... but then it should have returned true in // TryGetPathFromAssemblyDirectory. if (string.IsNullOrEmpty(NugetPackageDirectory)) { Trace.TraceWarning($"{nameof(NugetPackageDirectory)} is empty and application was unable to set path from current assembly directory."); return(IcuVersion); } #if !NET40 var context = DependencyContext.Default; // If this is false, something went wrong. These files should have // either been found above or we should have been able to locate the // asset paths (for .NET Core and NuGet v3+ projects). if (!TryGetNativeAssetPaths(context, out var nativeAssetPaths)) { Trace.WriteLine("Could not locate icu native assets from DependencyModel."); return(IcuVersion); } var icuLib = context.CompileLibraries .FirstOrDefault(x => x.Name.StartsWith(Icu4c, StringComparison.OrdinalIgnoreCase)); if (icuLib == default(CompilationLibrary)) { Trace.TraceWarning("Could not find Icu4c compilation library. Possible that the library writer did not include the Icu4c.Win.Full.Lib or Icu4c.Win.Full.Lib NuGet package."); return(IcuVersion); } if (!TryResolvePackagePath(icuLib, NugetPackageDirectory, out string packagePath)) { Trace.WriteLine("Could not resolve nuget package directory...."); return(IcuVersion); } TrySetIcuPathFromDirectory(new DirectoryInfo(packagePath), nativeAssetPaths); #endif return(IcuVersion); }
/// <summary> /// Reset the member variables /// </summary> public static void Reset() { IcuVersion = null; }