title: Handling failed file and directory operations in C#
body: <p><strong>The Problem:</strong> During an installation process, files and folders are created, moved, and renamed. Services are also starting and stopping during installation, which can cause locking issues on one or more files or folders. I have a solution to avoid most locking scenarios, but would like a better approach that will not waste time or CPU, and will prevent the user from having to deal with an Abort/Retry/Ignore dialog as much as possible.</p>
  
  <p><strong>The Background:</strong> In an optimal scenario, the logic handling the starting and stopping of services, and other operations that would place locks on files and folders would prevent locks from still existing by the time the create/move/rename section of the installer occurs. In this case, I do not have control over those parts of the installation process, but I do need to avoid showing the user error dialogs as much as possible when files or folders are unable to be altered. </p>
  
  <p>I am unable to simply loop for long periods of time since there are legitimate error cases where third-party applications are locking necessary resources, and we need to be able to promptly display this information to the user, and show them information regarding the offending processes. However, there are a lot of false positives in my use case, and I want to minimize user intervention.</p>
  
  <p>My current solutiuon looks something like this:</p>
  
  <pre><code>private const int MaxRetry = 3;
  private const int RetryDelayMs = 250;
  
  private static bool DoAction(FileSystemAction action, String src, String dest = "")
  {
      bool retval = false;
      bool inprogress = true;
  
      // (Re)Attempt to perform the desired action until the user aborts.
      while (inprogress)
      {
          try
          {
              // Automatically retry N times with a delay of M milliseconds.
              // This is meant to reduce the number of times a user sees an error dialog.
              var autoretry = true;
              var retryCounter = 0;
              while (autoretry)
              {
                  try
                  {
                      // CODE: Attempt to perform the file system action.
  
                      // Only get here if we succeeded.
                      autoretry = false;
                  }
                  catch (Exception)
                  {
                      // If this operation failed, try a few times.
                      if (retryCounter &gt;= MaxRetry)
                          throw;
                      retryCounter++;
                      Thread.Sleep(RetryDelayMs);
                  }
              }
  
              // If we get here without exception, success!
              inprogress = false;
              retval = true;
          }
          catch (Exception ex)
          {
              // Since there was an error, we now do the following:
              //   - Determine if locked files are the cause.
              //   - If locked files are the cause:
              //       - Show a custom Locked File dialog, providing information.
              //   - Otherwise:
              //       - Select message string based on action to inform the user.
              //       - Allow the user to Retry/Abort/Ignore the failed operation.
  
              // CODE: Logic goes here.
          }
      }
  
      return retval;
  }
  </code></pre>
  
  <p>I browsed several examples of handling locked files and failed file system operations on here when I first wrote this logic; however, I'm not content with this solution as it does not prevent the user from seeing the dialog in all false positive situations (where there is a race condition). Any ideas on improving this without being able to rewrite the offending service logic?</p>