Ejemplo n.º 1
0
        /// <summary>
        ///     Removes an symbolic link of the specified file or directory link based on command
        ///     prompt which allows a simple solution for the elevated execution of this order.
        /// </summary>
        /// <param name="path">
        ///     The link to be removed.
        /// </param>
        /// <param name="pathIsDir">
        ///     true to determine that the path is a directory; otherwise, false.
        /// </param>
        /// <param name="backup">
        ///     true to restore found backups; otherwise, false.
        /// </param>
        /// <param name="elevated">
        ///     true to remove this link with highest privileges; otherwise, false.
        /// </param>
        public static bool Destroy(string path, bool pathIsDir, bool backup = false, bool elevated = false)
        {
            var link   = PathEx.Combine(path);
            var isLink = PathEx.DirOrFileIsLink(link);

            var sb = new StringBuilder();

            sb.AppendFormat(CultureConfig.GlobalCultureInfo, pathIsDir ? "RMDIR /Q \"{0}\"" : isLink ? "DEL /F /Q /A:L \"{0}\"" : "DEL /F /Q \"{0}\"", link);

            var prior = string.Format(CultureConfig.GlobalCultureInfo, Resources.BackupFormat, link, EnvironmentEx.MachineId);

            if (backup && PathEx.DirOrFileExists(prior))
            {
                sb.AppendFormat(CultureConfig.GlobalCultureInfo, " && MOVE /Y \"{0}\" \"{1}\"", prior, link);
            }

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

            int?exitCode;

            using (var p = ProcessEx.Send(sb.ToString(), elevated, false))
            {
                if (p?.HasExited ?? false)
                {
                    p.WaitForExit();
                }
                exitCode = p?.ExitCode;
            }

            return(exitCode == 0 && isLink);
        }
Ejemplo n.º 2
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">
        ///     true to determine that the destination path is a directory; otherwise, false.
        /// </param>
        /// <param name="backup">
        ///     true to create an backup for existing files; otherwise, false.
        /// </param>
        /// <param name="elevated">
        ///     true to create this link with highest privileges; otherwise, 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 = string.Format(CultureConfig.GlobalCultureInfo, Resources.BackupFormat, link, EnvironmentEx.MachineId);
                    sb.AppendFormat(CultureConfig.GlobalCultureInfo, "MOVE /Y \"{0}\" \"{1}\"", link, prior);
                }
                else
                {
                    Destroy(link, true, true, elevated);
                }
            }

            if (PathEx.DirOrFileExists(link))
            {
                if (sb.Length > 0)
                {
                    sb.Append(" & ");
                }
                sb.AppendFormat(CultureConfig.GlobalCultureInfo, 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.AppendFormat(CultureConfig.GlobalCultureInfo, " \"{0}\" \"{1}\" && ATTRIB +H \"{0}\" /L", link, dest);
            }

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

            int?exitCode;
            using (var p = ProcessEx.Send(sb.ToString(), elevated, false))
            {
                if (p?.HasExited ?? false)
                {
                    p.WaitForExit();
                }
                exitCode = p?.ExitCode;
            }
            return(exitCode == 0 && PathEx.DirOrFileIsLink(link));
        }
Ejemplo n.º 3
0
        /// <summary>
        ///     <para>
        ///         Deletes any file or directory.
        ///     </para>
        ///     <para>
        ///         Immediately stops all specified processes that are locking this file or directory.
        ///     </para>
        /// </summary>
        /// <param name="path">
        ///     The path of the file or directory to be deleted.
        /// </param>
        /// <param name="elevated">
        ///     true to run this task with administrator privileges if the deletion fails; otherwise,
        ///     false.
        /// </param>
        /// <param name="timelimit">
        ///     The time limit in milliseconds.
        /// </param>
        public static bool ForceDelete(string path, bool elevated = false, int timelimit = 60000)
        {
            var target = Combine(path);

            try
            {
                if (!DirOrFileExists(target))
                {
                    throw new PathNotFoundException(target);
                }

                var locked = false;
                using (var current = Process.GetCurrentProcess())
                {
                    foreach (var p in GetLocks(target).Where(x => x != current))
                    {
                        if (ProcessEx.Terminate(p) || locked)
                        {
                            continue;
                        }
                        locked = true;
                    }
                    if (!locked)
                    {
                        foreach (var p in GetLocks(target).Where(x => x != current))
                        {
                            if (!locked)
                            {
                                locked = true;
                            }
                            p?.Dispose();
                        }
                    }
                }

                var sb      = new StringBuilder();
                var curName = $"{ProcessEx.CurrentName}.exe";
                if (IsDir(target))
                {
                    var tmpDir = DirectoryEx.GetUniqueTempPath();
                    if (!Directory.Exists(tmpDir))
                    {
                        Directory.CreateDirectory(tmpDir);
                    }

                    var helper = FileEx.GetUniqueTempPath("tmp", ".cmd");
                    sb.AppendLine("@ECHO OFF");
                    sb.AppendFormatLine("ROBOCOPY \"{0}\" \"{1}\" /MIR", tmpDir, target);
                    sb.AppendFormatLine("RMDIR /S /Q \"{0}\"", tmpDir);
                    sb.AppendFormatLine("RMDIR /S /Q \"{0}\"", target);
                    sb.AppendLine("EXIT");
                    File.WriteAllText(helper, sb.ToString());

                    var call = $"CALL \"{helper}\"";
                    if (locked)
                    {
                        ProcessEx.SendHelper.WaitForExitThenCmd(call, curName, elevated);
                    }
                    else
                    {
                        using (var p = ProcessEx.Send(call, elevated, false))
                            if (p?.HasExited ?? false)
                            {
                                p.WaitForExit(timelimit);
                            }
                    }

                    DirectoryEx.Delete(tmpDir);
                    DirectoryEx.Delete(target);
                    ProcessEx.SendHelper.WaitThenDelete(helper, elevated);
                }
                else
                {
                    try
                    {
                        File.Delete(target);
                    }
                    catch (Exception ex) when(ex.IsCaught())
                    {
                        if (locked)
                        {
                            ProcessEx.SendHelper.WaitForExitThenDelete(target, curName, true);
                        }
                        else
                        {
                            using (var p = ProcessEx.Send(sb.ToString(), elevated, false))
                                if (p?.HasExited ?? false)
                                {
                                    p.WaitForExit(timelimit);
                                }
                        }
                    }
                }
            }
            catch (Exception ex) when(ex.IsCaught())
            {
                Log.Write(ex);
            }
            return(!DirOrFileExists(target));
        }