/// <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);
        }
Example #2
0
        /// <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;
 }