bin/*.dll locked when deploying website after app_offline.htm copied and active (shadow copy off) - deployment

I am running into an issue deploying a website. Shadow copy is turned off after previous deployment issues with it and deploying the site.
Specifically at deploy time I find that even after copying app_offline.htm and verifying that the site/application is offline, the files in bin/*.dll are often locked.
With shadow copy off I would still expect the locks on the dll's to be free'd when the appdomain is unloaded on app_offline.htm appearance.
I have tried deploying a temporary web.config found on Stack Overflow which aims to prevent changes (to bin/) being picked up immediately just before I try to delete the contents of bin/
I even pause for 10s after copying the new web.config.
?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpRuntime waitChangeNotification="300"
maxWaitChangeNotification="300"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
I have confirmed with the handles util that my application pool (w3wp.exe process) is the holder of a lock on the dlls so am assuming this is the reason why I cannot delete/overwrite the files. If i manually recycle the app pool it frees it up and I am able to deploy just fine. Unfortunately as part of the deploy process copying the app_offline and changing the web.config are possible but performing IIS appcmd recycles are not (for permissions/group policy reasons) so I really need to be able to free up this lock with just app_offline.htm and the web.config.
Turning shadow copy back on does 'solve' this particular issue but if a lock is still held on the dll. However I wonder / and concerned if I am just postponing the problem. Unless the lock on the old dll is free'd when the appdomain is loaded again?
When copying the app_offline.htm the w3wp process id doesn't change like it does with a hard recycle but I assume it is unloading the appdomain which should free the bin/ files it has locked.
Another interesting point is that this only appears to happen on our production servers, I cannot recreate it locally or on our dev/staging sites. I don't believe there is any config difference with the app_pools or IIS config but could this possible cause this behavior.
Also to clarify shadowCopyBinAssemblies has been set to false for over 3 years without this problem happening (same deploy process) so I really feel like something that happened recently caused this, but I have no idea what.
Thanks for any ideas on how to solve this or even what might be causing it.
(I believe the server is IIS7 or 7.5)

I am running into a similar issue where a DLL is locked by IIS even with the presence of app_offline.htm.
Restarting the pool solves the issue but it is manual. Looking for an automated way. In my case the DLL is PDFium.dll it is likely an unmanaged dll

Related

How to force IIS7 to see changes in Web.config immediately?

I don't have command line access (AFAIK). I'm using the IIS7.5 client (remotely)
I've tried resetting the Application Pool but the changes still don't show up (I have a Rewrite from http> httpS that may have a bug. So I deleted it from web.config and uploaded to root.)
So, either IIS7 takes a while to see it's changed, or the Rewrite is somewhere else, but where?

Azure Cloud Deploy Keeps Recycling

I get the following error:
Recycling (Waiting for role to start... Sites are being deployed.
[2012-12-17T05:30:10Z])
Running One or more role instance is unhealthy. 1 Instance: 1
Unhealthy
i was actually trying to convert my web application to a cloud applicaton.
here is what i did:
i added a cloud project to my solutions,
i added a webrole which linked to my web app
i created an sql azure database and copied my whole structure and also the data to the db
i inserted the connection string in my webconfig and tried to run it on emulation, this worked fine
then tried to deploy it by creating a cloud service, running the builder to create the packages and uploading the packages in "staging" mode. this is where i got the errors.
i tried to create an empty cloud app and add a default webrole and load this to the cloud, this worked fine. so i figured, maybe i have something wrong in my settings of my webrole.
I checked the difference between both and i noticed that in both solutions diagnostics was enabled but the storage account was empty in my own solution, so i inserted "UseDevelopmentStorage=true" here. this didn't change anything tho. I also saw a difference in the "packages.config"
default role had:
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.7.0.0" targetFramework="net40" />
<package id="System.Web.Providers" version="1.1" targetFramework="net40" />
<package id="System.Web.Providers.Core" version="1.0" targetFramework="net40" />
<package id="WindowsAzure.Storage" version="1.7.0.0" targetFramework="net40" />
mine had:
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.7.0.0" targetFramework="net35" />
<package id="WindowsAzure.Storage" version="1.7.0.0" targetFramework="net35" />
i tried changing in this and uploading, didn't do anything
I am not using a worker role, i have only 1 running instance (same as default)
my application uses some authentication in global.asax where it tries to read from User.Identity.Name and compare with a user in the database (this user is inserted in the sql azure db). At first I thought this would maybe be the cause of the problem, but even if i comment out this code the application will not run on the cloud.
VM size is small, trust level = Full trust
I also saw some differences in the settings where i had remote access parameters. I tried removing all these just to exclude issues
i read something about settings references to "copy local is true", but im not sure if this will do any difference.
Any ideas because I don't really know what to do anymore
EDIT:
I modified all the references to "copy local is true" and i disabled to diagnostics just to be sure there's nothing wrong with it.
but now i get the error:
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>
Funny thing is, in my webconfig this is already set... And I can only find 1 webconfig.
I'm not quite sure what I'm doing wrong
"Keep recycling" almost always means that there are some exception occurred when your application was started. You might not be able to see any errors or exceptions in through the Diagnostics Montor since your exception might be occurred before you configured and started the diagnostics.
I recommend you enable the IntelliTrace option when deployment. It's very easy to do if you are using Visual Studio. Then you can retrieve the IntelliTrace result through Visual Studio and figure out what exception occurred. I strongly considered there are some references missed on azure that you need to set Copy Local = true. But you need IntelliTrace to find them.
The problem was that I had some referenced projects that had an app.config file with a string to a local database

VS2012 WebDeploy Publish Breaking Web.Config

I have a MVC3 Web Application project that I develop and publish from Visual Studio 2012. This was recently a VS2010 project that was migrated.
My web.config is setup using a <location inheritInChildApplications="false"> tag so that a child application running in a virtual directory does not take on the settings.
I have setup a WebDeploy publish profile, which worked flawlessly in VS2010, but breaks my application when published from VS2012. It adds a <connectionStrings> node after the closing aforementioned </location> tag, even though I already have a <connectionStrings> node inside my <location> node. This breaks the app due to an invalid configuration file.
I've tried re-creating the profile from scratch which didn't solve the problem.
Based on what I have read here, http://msdn.microsoft.com/en-us/library/dd465337.aspx, unchecking the "Use this connection string at runtime" checkbox should instruct the publish process to NOT add the connection string, but it does anyway.
I'm thinking that this would not be an issue if I wasn't using the <location inheritInChildApplications="false">, because the connection string would get added to the right spot.
Also, note that if I publish to the File System instead of using WebDeploy, the published Web.Config is created correctly and does NOT have the extra connection string node added.
Are there any known workarounds for this issue?
As I suspected, this issue is related to the inheritInChildApplications attribute. It is likely a bug in the Visual Studio 2012 Web Deploy whereby the deploy process always adds the connection string to the configuration file, even if you tell it not to. In my case, it was also adding in the wrong spot, which broke my application.
To fix the issue, I simply stopped using the attribute and turned off configuration inheritance using one of the options listed here.
I can now publish without errors, but the process still adds the connection string to the deployed configuration file. Annoying but not a show stopper.

When precompiling ASP.NET MVC 4 project in Visual Studio 2012, does it try to resolve the entire config chain locally?

Can someone please confirm or deny my assumption below and/or offer any alternatives?
My Goal
I'd like to be able to precompile and merge my ASP.NET MVC 4 application (as documented here and here) when one-click publishing to our production environment.
The Symptom
I've got an ASP.NET MVC 4 project in Visual Studio 2012. My Web.config contains various entries that are removed in the Web.Release.config transformation. One of the removed entries is the entire configSections element because we maintain those entries in the production server's Machine.config.
However, when I configure my project to precompile and merge for release publication, I get the following error:
Unrecognized configuration section [our custom section name]
My Assumption
What I assume is happening is that it is precompiling everything locally before publishing to the production server (which makes perfect sense) but that part of that precompilation process is to resolve and validate the entire .config chain, from the project's Web.config up to my local Machine.config (which doesn't make much sense, practically). And since my local Machine.config does not declare configSections (or any of the other settings we rely on the production server's Machine.config for), the resolved Web.config doesn't validate.
And since the Web.config doesn't validate, the site can't be precompiled and so nothing is ever published to production.
The Rub
If that is indeed what's happening, then we won't be able to precompile, because the only solution I can think of (other than some potential configuration option I haven't been able to find) would be for all of our developers to have local copies of our production server's Machine.config on their machines. And that simply isn't reasonable because it defeats the whole purpose of having those common settings declared in a single location.

Why does tomcat replace context.xml on redeploy?

Documentation says if you have a context file here:
$CATALINA_HOME/conf/Catalina/localhost/myapp.xml
it will NOT be replaced by a context file here:
mywebapp.war/META-INF/context.xml
It is written here: http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
Only if a context file does not exist for the application in the $CATALINA_BASE/conf/[enginename]/[hostname]/, in an individual file at /META-INF/context.xml inside the application files.
But everytime I re-deploy the war it replaces this myapp.xml with the /META-INF/context.xml!
Why does it do it and how can I avoid it?
Thanx
Undeploy part of redeploy deletes app and the associated context.xml.
If you use maven tomcat plugin you can avoid deleting context.xml if you deploy your app with command like this:
mvn tomcat:deploy-only -Dmaven.tomcat.update=true
More info here: https://tomcat.apache.org/maven-plugin-2.0-beta-1/tomcat7-maven-plugin/deploy-only-mojo.html
You can use deploy-only with parameter mode to deploy the context.xml too.
The short answer:
Just make the TOMCATHOME/conf/Catalina/localhost dir read-only, and keep reading for more details:
For quick deployment mode (Eclipse dynamic web project, direct Tomcat
connection, etc.) on a local/non-shared Tomcat server you can just define your JDBC datasource (or any
other 'web resource') using the META-INF/context.xml file inside the
WAR file. Easy and fast in your local environment, but not suitable for staging, QA, or
production.
For build deployment mode (usually for staging, QA, or prod), JDBC
datasources and other 'web resources' details are defined by the
QA/production team, not the development team anymore. Therefore, they
must be specified in the Tomcat server, not inside the WAR file
anymore. In this case, specify them in the file
TOMCATHOME/conf/Catalina/localhost/CONTEXT.xml (change Catalina
by the engine, and localhost by the host, and CONTEXT by your context accordingly). However,
Tomcat will delete this file on each deployment. To prevent this
deletion, just make this dir read-only; in Linux you can type:
chmod a-w TOMCATHOME/conf/Catalina/localhost
Voila! Your welcome.
The long answer
For historical reasons Tomcat allows you to define web resources (JDBC datasources, and others) in four
different places (read four different files) in a very specific order of precedence, if you happen to define the same resource multiple times. The ones named in the
short answer above are the more suitable nowadays for each purpose, though you could still
use the others (nah... you probably don't want to). I'm not going to
discuss the other ones here unless someone asks for it.
On tomcat7, also woth autoDeploy=false the file will be deleted on undeploy. This is documented and not a bug (althought it avoids good automated deployments with server-side fixed configuration).
I found a workaround which solved the problem for me:
create a META-INF/context.xml file in your webapp that contains
on the Server create a second context "/config-context" in server.xml and put all your server-side configuration parameters there
on the application use context.getContext("/config-context").getInitParameter(...) to access the configuration there.
This allows a per-host configuration that is independent of the deployed war.
It should also be possible to add per-context configurations by adding contexts like "/config-context-MYPATH". In your app you can use the context path oth the app to calculate the context path of the config app.
According to the documentation (http://tomcat.apache.org/tomcat-8.0-doc/config/automatic-deployment.html#Deleted_files) upon redeploy tomcat detects the deletion (undeploy) of your application. So it will start a cleanup process deleting the directory and xml also. This is independent of auto deployment - so it will happen upon redeployment through manager and modification of war also. There are 3 exceptions:
global resources are never deleted
external resources are never deleted
if the WAR or DIR has been modified then the XML file is only deleted
if copyXML is true and deployXML is true
I don't know why, but copyXML="false" deployXML="false" won't help.
Secondly: Making the directory read only just makes tomcat throwing an exception and won't start.
You can try merging your $CATALINA_BASE/conf/Catalina/localhost/myapp-1.xml, $CATALINA_BASE/conf/Catalina/localhost/myapp-2.xml, etc files into $CATALINA_BASE/conf/context.xml (that works only if you make sure your application won't deploy its own context configuration, like myapp-1.xml)
If someone could tell what is that "external resources" that would generally solve the problem.
The general issue as described by the title is covered by Re-deploy from war without deleting context which is still an open issue at this time.
There is an acknowledged distinction between re-deploy which does not delete the context, and deploy after un-deploy where the un-deploy deletes the context. The documentation was out of date, and the manager GUI still does not support re-deploy.
Redeployment means two parts: undeployment and deployment.
Undeployment removes the conf/Catalina/yourhost/yourapp.xml because the
<Host name="localhost" appBase="webapps" unpackWARs="true"
autoDeploy="true"> <!-- means autoUndeploy too!!! -->
</Host>
Change the autoDeploy="false" and Tomcat has no order anymore to remove the conf/Catalina/yourhost/yourapp.xml.
There is an feature that allowes us to make those steps (undeploy/deploy) as one single step (redeploy) that do not remove the context.xml. This feature is available via the manager-text-interface, but the option is not available using the manager-html-interface. You might have to wait until the bug in tomcat is fixed. You can use the method described in this answer as an workaround.