Avoiding Process Cannot Access File Errors with ASP.NET Deployments

A common error message you might see when deploying an ASP.NET application with BuildMaster is “The process cannot access the file ... because it is being used by another process.”.

BuildMaster File Lock Error

What this error is saying?

As the error indicates, the process (in this case BuildMaster service or agent) can’t overwrite a file (in this case, AWSSDK.dll in the /bin folder). There are 3 reasons why this error might be happening:

  1. The file is Read-Only, and can’t be overwritten
  2. The service principal (user account) doesn’t have permission to access the file
  3. The file is being locked and cannot be accessed while locked

If the error only happens intermittently, then the cause is most certainly file locking. Windows File Management can get a bit complicated, but long story short, when one program opens a file, it generally requests that the file be locked as to prevent other programs from writing to it.

For example, when two people on the same network try to open the same Word Document (or PowerPoint, etc). The second person to open it will get a warning like this:
Window's file lock message

This makes sense, because without it, multiple people would be altering the same document and would constantly have to try merging changes.

Why does the error happen… sometimes?

First, let’s consider the behavior of ASP.NET applications (be it MVC, WebForms, etc): if you (or any other process) adds or removes files or directories within the application (/bin) sub-folder, or modifies the web.config file or global.asax file, then the ASP.NET runtime will restart the application.

If the application you’re deploying has only 1 or two small files in the /bin folder, then the restart will succeed, your application will be updated, and everything will work fine.

But what happens where there are more files? We end up with a bit of a race condition.

As BuildMaster is overwriting files into the /bin folder, ASP.NET is restarting the application on each file change. To do this, ASP.NET looks in the bin folder and, file-by-file, locks each .dll, loads it in memory, and then unlocks the file.

When BuildMaster tries to overwrite a file that ASP.NET is currently reading, we get that cannot access file error message.

How can this be prevented?

The old adage of “try, try again” is not a good idea; having ASP.NET constantly load, unload a partially deployed application is an invitation for lots of strange errors down the line.

Instead, you should surround the Deploy Build Artifact step in your deployment plan with commands to stop and the start the Application Pool.

Stopping the app pool will allow all of the files in the /bin folder to be modified without causing ASP.NET to restart your application. Starting the app pool after the artifact has been deployed will automatically reload your web application, using the newly deployed, modified files.

Adding these steps in BuildMaster is really easy. In your deployment plan, click on the green plus button and click the [iis] tag. You’ll see options for stopping and starting application pools.

Then, select the Start IIS App Pool Action and pick your Application pool:
BuildMaster File Lock image 1

After adding in the stop and start actions you’ll have something that looks like:
BuildMaster File Lock image 2

Of course, you can also use Variables for all or part of the application pool name, such as “My_Web$EnvironmentName”, if you have multiple application pools named for each environment.