Ejemplo n.º 1
0
        /// <summary>
        ///     Creates a symbolic link to the specified file or directory based on command
        ///     prompt which allows a simple solution for the elevated execution of this
        ///     order.
        /// </summary>
        /// <param name="linkPath">
        ///     The file or directory to be linked.
        /// </param>
        /// <param name="destPath">
        ///     The fully qualified name of the new link.
        /// </param>
        /// <param name="destIsDir">
        ///     <see langword="true"/> to determine that the destination path is a
        ///     directory; otherwise, <see langword="false"/>.
        /// </param>
        /// <param name="backup">
        ///     <see langword="true"/> to create an backup for existing files; otherwise,
        ///     <see langword="false"/>.
        /// </param>
        /// <param name="elevated">
        ///     <see langword="true"/> to create this link with highest privileges;
        ///     otherwise, <see langword="false"/>.
        /// </param>
        public static bool Create(string linkPath, string destPath, bool destIsDir, bool backup = false, bool elevated = false)
        {
            #region p/invoke

            /*
             * The idea was to replace the code below with this code that uses the
             * p/invoke method to create symbolic links. But this doesn't work
             * without administrator privileges while a CMD function called
             * MKLINK can do that simply as normal user...
             *
             * var dest = PathEx.Combine(targetPath);
             * try
             * {
             *  if (targetIsDir)
             *  {
             *      if (!Directory.Exists(dest))
             *          Directory.CreateDirectory(dest);
             *  }
             *  else
             *  {
             *      if (!File.Exists(dest))
             *          File.Create(dest).Close();
             *  }
             * }
             * catch (Exception ex)
             * {
             *  Log.Write(ex);
             *  return false;
             * }
             *
             * var link = PathEx.Combine(linkPath);
             * try
             * {
             *  var linkDir = Path.GetDirectoryName(link);
             *  if (linkDir != null && !Directory.Exists(linkDir))
             *      Directory.CreateDirectory(linkDir);
             * }
             * catch (Exception ex)
             * {
             *  Log.Write(ex);
             *  return false;
             * }
             *
             * if (PathEx.DirOrFileExists(link))
             *  if (!DirIsLink(link) && backup)
             *      try
             *      {
             *          File.Move(link, link + $"-{{{EnvironmentEx.MachineId}}}.backup");
             *      }
             *      catch (Exception ex)
             *      {
             *          Log.Write(ex);
             *          return false;
             *      }
             *  else
             *      try
             *      {
             *          if (Directory.Exists(link))
             *              Directory.Delete(link);
             *          if (File.Exists(link))
             *              File.Delete(link);
             *      }
             *      catch (Exception ex)
             *      {
             *          Log.Write(ex);
             *      }
             *
             *
             * if (!PathEx.DirOrFileExists(dest) || PathEx.DirOrFileExists(link))
             *  return false;
             *
             * var created = WinApi.SafeNativeMethods.CreateSymbolicLink(link, dest, (WinApi.SymbolicLinkFlags)Convert.ToInt32(targetIsDir));
             * if (created)
             *  SetAttributes(link, FileAttributes.Hidden);
             *
             * return created;
             */

            #endregion

            var dest = PathEx.Combine(destPath);
            try
            {
                if (destIsDir)
                {
                    if (!Directory.Exists(dest))
                    {
                        Directory.CreateDirectory(dest);
                    }
                }
                else
                {
                    if (!File.Exists(dest))
                    {
                        File.Create(dest).Close();
                    }
                }
            }
            catch (Exception ex) when(ex.IsCaught())
            {
                Log.Write(ex);
                return(false);
            }

            var link = PathEx.Combine(linkPath);
            try
            {
                var linkDir = Path.GetDirectoryName(link);
                if (!Directory.Exists(linkDir) && linkDir != null)
                {
                    Directory.CreateDirectory(linkDir);
                }
            }
            catch (Exception ex) when(ex.IsCaught())
            {
                Log.Write(ex);
                return(false);
            }

            var sb = new StringBuilder();
            if (backup && PathEx.DirOrFileExists(link))
            {
                if (!DirectoryEx.IsLink(link))
                {
                    var prior = Resources.BackupFormat.FormatCurrent(link, EnvironmentEx.MachineId);
                    sb.AppendFormatCurrent("MOVE /Y \"{0}\" \"{1}\"", link, prior);
                }
                else
                {
                    Destroy(link, true, true, elevated);
                }
            }

            if (PathEx.DirOrFileExists(link))
            {
                if (sb.Length > 0)
                {
                    sb.Append(" & ");
                }
                sb.AppendFormatCurrent(destIsDir ? "RMDIR /S /Q \"{0}\"" : "DEL /F /Q \"{0}\"", link);
            }

            if (PathEx.DirOrFileExists(dest))
            {
                if (sb.Length > 0)
                {
                    sb.Append(" & ");
                }
                sb.Append("MKLINK");
                if (destIsDir)
                {
                    sb.Append(" /J");
                }
                sb.AppendFormatCurrent(" \"{0}\" \"{1}\" && ATTRIB +H \"{0}\" /L", link, dest);
            }

            if (sb.Length <= 0)
            {
                return(false);
            }

            int?exitCode;
            using (var p = CmdExec.Send(sb.ToStringThenClear(), elevated, false))
            {
                if (p?.HasExited ?? false)
                {
                    p.WaitForExit();
                }
                exitCode = p?.ExitCode;
            }
            return(exitCode == 0 && PathEx.DirOrFileIsLink(link));
        }
Ejemplo n.º 2
0
 /// <summary>
 ///     Determines whether the specified path is specified as reparse
 ///     point.
 /// </summary>
 /// <param name="path">
 ///     The file or directory to check.
 /// </param>
 public static bool DirOrFileIsLink(string path) =>
 IsDir(path) ? DirectoryEx.IsLink(path) : FileEx.IsLink(path);