Using AppDomainSetup.ShadowCopyDirectories in IIS - c#

I've got a ton of DLLs used by my website. Most of them never change, but I frequently change 1 of them.
Every time I do the site is down for about 5 minutes while IIS restarts. I'd like to reduce this.
I've read about shadow copying being slow when you have a lot of DLL files so I'd like to disable it in most cases, but I do want to use it on my frequently modified DLL so I can change that without having to stop IIS.
The documentation on shadow copying seems to presume you are setting it up before the AppDomain is created, but IIS handles the creation of the AppDomain so I don't know how to use the AppDomainSetup.ShadowCopyDirectories property to tell it not to do any shadow copying in the main /bin folder and only shadow copy things in the /bin/changesFrequently folder. Can I set this in web.config somehow? Is there a way to run c# code in IIS before the shadowcopy process starts?

Related

Copy Files to the output directory on an Azure WebRole

We have an azure Webrole which we call as an API from other applications to convert webpages into a rendered byte array which we then attach as a pdf into emails. We do this using ABCpdf.
For our latest project we have to use a second engine from ABC (ABCGecko) in order to render our pages correctly. The ABCGecko engine requires manually copying to the output directory after build occurs, it doesn't happen automatically.
For a normal application this is no issue, I simply copy the required folder (XULRunner_38 for anyone who uses ABC) into the release after building but I can't figure out how to do this for an Azure WebRole and there doesn't seem to be anything much in the way of help from what I can see in google searches.
I'm assuming I either have to build the role and then adjust the package before I deploy, or deploy the role and then copy the folder across after. I can't figure out how to do this though.
If anyone has any ideas or has needed to manually copy files to an Azure Webrole in the past then I would greatly appreciate your help. Also I should mention that we use Visual Studio as our IDE and publish from within there in case that matters to anyone.
Azure web (and worker) roles allow you to define startup tasks, which allows you to call a script (e.g. powershell script, batch file) which can then perform actions such as copying files.
Oh, and if you don't want it to attempt copying in the event a role instance reboots, you'd need to do something like leaving yourself a "breadcrumb" somewhere to signal that you've already done your init work.
What you don't want to ever do is manual copying of content to your role instances. The moment those instances are updated (e.g. new Host OS update) or they're moved to another physical host, you'll lose any of the files you manually copied.
This is all independent of any IDE (aside from general support for the script language you're writing in), since your startup task is going to execute on each web role instance when it starts up.
More details about startup tasks are here.

Load asp.net dlls from external folder

I have 50 SAME asp.net websites hosted on IIS. Something like WordPress, where each website though same has different content.
C:\inetpub\vhosts\website1.com
C:\inetpub\vhosts\website2.com
C:\inetpub\vhosts\website3.com
.
.
.
C:\inetpub\vhosts\website50.com
Since these are exactly same copies of the ASP.NET website; I want to use a 'common' bin folder so that I don't load 50 copies of the same set of DLLs to update and load in memory each time.
The solutions here: Is there a way to change .net mvc bin dir location? DO NOT work as I want the DLLs to be placed outside the website folder, so that they can be shared.
One little detail you should know about IIS and ASP.NET; they do not actually run the files in the bin folder. Rather, they copy the files in the bin folder into a "shadow directory" (something like "C:\WINDOWS\Microsoft.NET\Framework\v4.5.XXXX\Temporary ASP.NET Files"). It is from there that they are actually executed. The bin folder is monitored for any changes, and the shadow directory is updated as needed. This allows you to deploy new DLLs even when the site is running-- otherwise, they'd be locked.
So... no matter what you do, the O/S is going to load multiple images of the same DLL, even if you get them to all use the same bin folder. As far as I know there is no way to turn this off.
That being said, if you want to save a bit of disk space and get your sites to use a common bin folder, consider using a symbolic link. This essentially allows you to create a directory that "points" at another directory (this sort of thing is more common in Unix). Thus you end up with one copy being accessed from several places. Just one word of caution: be very careful when deleting things, because you could delete folders from all 50 of your sites without meaning to.
But a better option (depending on why you are running 50 identical sites, which is very unusual) is to run just ONE site, with one IP address, but with several DNS entries pointed at that IP. This way it would look like you have 50 sites when you only have one. The trick here is (if you are using https) you'll have to use host headers to pick the SSL cert so that browsers don't show a phishing warning. Or, if your site is load balanced, you could terminate SSL at the load balancer (a strategy known as SSL offloading) so that a cert at the IIS level isn't even needed.

Rename a running executable (exe) file [duplicate]

This question already has answers here:
Why does rename a loaded .net assembly work?
(3 answers)
Closed 5 years ago.
We are trying to push updates to multiple servers at once and my manager has found that it is possible to rename running .exe file. Using that knowledge he wants to rename a running exe and copy over a new version of said exe such that anyone running their in memory copy of foo.exe are fine and anybody who opens a shortcut pointing to foo.exe will get a new copy with updates applied.
I guess I need to clarify, He doesn't expect the old copy to magically update, he just expects them to keep running the old copy until they open the exe again, in which case it will then open the new one that has the name of the old one.
It sometimes throws an exception that the file is in use on his program but if he tries renaming it in a loop it will eventually succeed. On my machine I have yet to be able to get it to work even in a loop.
My first and main question is this: Is it ever acceptable to do this. Should renaming a running executable ever be a valid scenario?
Secondly, if it is a valid scenario then how could one reliably do this? Our current thoughts are try a bunch of times using File.Move (C#) to do a rename and if it doesn't work then write out to an error log so it can be handled manually.
An airplane mechanic and a surgeon meet in a bar. The mechanic says "you know, we have basically the same job. We take broken stuff out and put new, better parts in." The surgeon says "yeah, but you don't have to keep the plane flying as you're making the repairs!"
Trying to update an application by moving files while the application is running seems about as dangerous as trying to fix an airplane in flight. Possible? Sure. Greatly increased risk of catestrophic crash? Yep.
If the application you are updating is a managed application, consider using ClickOnce Deployment. That way, the next time someone runs the application, if there is a new version available it will be copied down and installed automatically. That's much more safe and pleasant than trying to mess with an application while its still running.
No, this is not acceptable. Do not do this. This is not a valid deployment mechanism. This should have been yours or his first clue:
It sometimes throws an exception that the file is in use on his program but if he tries renaming it in a loop it will eventually succeed.
And it won't work, anyway. His theory is quite wrong:
Using that knowledge he wants to rename a running exe and copy over a new version of said exe such that anyone running their in memory copy of foo.exe are fine and anybody who opens a shortcut pointing to foo.exe will get a new copy with updates applied.
Specifically, the copy in memory will not be automatically replaced with the new executable just because it has the same name. The reason that you're allowed to rename the executable in the first place is because the operating system is not using the file name to find the application. The original executable will still be loaded, and it will remain loaded until you explicitly unload it and load the new, modified executable.
Notice how even modern web browsers like Chrome and Firefox with their super fancy automatic, in the background, no one ever notices that they exist, updaters still have to close and relaunch the application in order to apply the updates.
Don't worry about shooting the messenger here. It's more likely that your customers and your tech support department will shoot you first.
See number 1.
In our organization, we solved the problem of Updates by having two release folders say EXE_A and EXE_B. We also have a release folder called EXE which only has links ALL of which points to either to EXE_A or EXE_B from which the user runs the applications.
When we publish a new version of the program, we publish it to the folder that is not referenced in the links and then update the links (EXE). In this way, you do not get into exceptions that users are holding the application / assemblies. Also if a user wants to run the updated version, all he need to do is close / re-execute the link in EXE folder.
If you use Windows Vista/Server2k8 or newer you could use mklink to create a symbolic link to the folder containing your application and start the application out of the "symblic linked folder" and then at the update create a new folder, e.g. "AppV2" and change the SymLink to that folder, so the next time the user restarts the application he starts it out of the new folder without noticing.
Renaming open files is ALWAYS a bad choice!
But in general I would think of a better deployment strategy anyway, because if you need to use such "hacks" it is always a messy situation. I don't know your application, but maybee ClickOnce would be a point to start, because you can configure it to check for updates on every start...

How would I find an exe's path just by knowing its name?

How Would I find another exe's path by knowing its name in .net?
Would I add name to the OS environment variable?
Would the other application have to 'register' itself somewhere else?
I need App A to start-up App B and call some WCF services on it.
Thanks!
To answer your question: you cannot know the path simply by knowing the name. An exe can reside anywhere on the file system. There can be multiple instances of it that don't know about each other. Multiple exe files that are completely different can have the same name.
You could take one of several approaches to get round this, depending on the exe you are targetting:
get the user to browse for the exe using a normal file browse dialog
search the file system
see what traces the target exe leaves on the system (filesystem, registry, environmental variables, etc) and use those traces to locate the exe
For either of these options you save the result so you don't have to execute it again when your app is run the next time.
Searching the filesystem could take some time, you are not guaranteed to find the exe (depending upon the user level your app is running as) and you may get false positives, especially if the app is called something dumb like setup.exe.
Getting the user to locate the exe the first time you run is possibly the most reliable way of locating it, but then you have to decide what to do if your app runs but the target exe is no longer at the specified location, or the user has chosen the wrong exe.
If you have some control over App B (i.e. it is your product), then you could consider adding some info to a known spot in the registry when App B gets installed, so that App A can locate it easily. You still need to have a plan B though in case the info is missing.
Reference a path to a shortcut of the exe in the config setting, that way if the exe ever moves around the shortcut will still be up-to-date. Try it, make a shortcut to a exe, then cut and paste the exe somewhere else, then double click the shortcut and you'll see it points to the exe's new location thus will not require changes to app A if the location app B changes.
Really, just make the App B a windows service and start it up when needed.
UPDATE:
Another suggestion would be to create a hard link to the AppB's EXE:
mklink /H AppB-link.exe path_to_actual_exe
Or a symbolic link to whole directory where App B resides:
mklink /D virtual_directory path_to_actual_directory

Prevent ASP.Net AppDomain Unload

As described here, I'm writing a WinForms GUI that is run in an ASP.Net AppDomain.
However, whenever Web.config or the bin folder is modified, ASP.Net unloads the AppDomain, and the entire program dies.
Is there any way to prevent this?
2nd EDIT: In my EXE, I create the AppDomain by calling ApplicationHost.CreateApplicationHost and pass it a type in my EXE that launches the GUI.
EDIT: I'm already aware that this is a horrible design.
Does anyone have a sane alternatives?
The program tracks accounts for a non-profit organization in a typed dataset.
It needs to send bills by email, and I'm using ASPX files to generate the emails. (I'd rather not change that, unless there's a very nice alternative; the templates have already been written)
The email templates are ASPX files that are deployed in a subfolder; that subfolder becomes the ASP.Net application and has the executable in its bin directory for ASP.Net to load all of my code into its AppDomain.
The typed dataset must be accessed by both the UI and the ASPX files, and I don't want to download the data from SQL server twice
This is core to ASP.Net - if the web.config is changed, the AppDomain is recycled. If the machine.config is changed, all AppDomains are recycled.
However, you can disable this. Turn on "Disable Recycling on Configuration Changes" for the application pool you are interested in in the IIS control panel.
alt text http://img138.imageshack.us/img138/9938/iisdisablerecycle.png
See this question: How to prevent an ASP.NET application restarting when the web.config is modified?
I've noticed that your first question is dated Oct 29. I know it's far off on the development track...
But just out of curiosity: Why not use T4 templates?
It's simple, fast, you can edit pretty much like an ASPX page, and it runs in whatever AppDomain you are.

Categories