How to update XBAP to latest version on client computer? - c#

I developed a XAML browser application (XBAP) that is embedded within an ASP.NET web page. I am having a problem getting the latest version of the XBAP to update on the client computer. During development, I have had to use the Mage.exe tool to clear out the application cache so that my changes will be seen when running on my local computer. Besides executing Mage.exe -cc in the command line, I have also found rundll32 dfshim CleanOnlineAppCache to work just as well.
However, I do not want to ask customers to run any commands in the command line. What will I have to do to make the XBAP automatically update on the client computer? Instead of the updated XBAP refreshing on the client computer, the previous version of the XBAP continues to run.
Update
I created a bounty on this question because I have the same issue. From what I read online, XBAPs are supposed to compare the cached version # with the version # of the one on the webserver, and download the new version if it's different. I've verified that my version numbers are different, but the cached copy is still the one that is running when I launch the XBAP.
The cached copy also comes if I launch the XBAP outside of the asp.net page, although I do get the new version if I change the url parameters.
Update #2
I've discovered that the XBAP does automatically update on XP 32-bit machines, but not on my Windows 7 64-bit machine.

You could try something like this, although I use it in XAPs not XBAPs it might work for you too:
(snippet follows)
public partial class App : Application
{
/// <summary>
/// Creates a new <see cref="App"/> instance.
/// </summary>
public App()
{
Application.Current.CheckAndDownloadUpdateAsync();
// rest of code
EDIT
Was gonna suggest incrementing version number between publishes but it seems that's already been taken care of. Does this behavior happen on all browsers ? Might be some IE-specific bug/oddity (i've seen plenty of IE-only misbehaviors... wouldn't surprise me)

Years ago, we had this problem with an ordinary website. It kept haunting us, and in the end, we ended up changing the url prefix for each new version. The very first page was never cached, and forwarded to the updated url.
Its a workaround, I know, but a very reliable one.

You can use ClickOnce to deploy your application. If you want to force user to update just set minimum required version for the application (it's in Application Updates dialog box).

without the correct cache headers your browser may be preventing downloading the xbap.
clear cache to see if this fixes it.
alternatively use:
<%string versionInfo = typeof (AVSTX.POS.WebMvc.Controllers.HomeController).Assembly.GetName().Version.ToString(); %>
<param name="source" value="<%=ResolveUrl("~/ClientBin/AVSTX.POS.WebRia.xap?version=" + versionInfo) %>"/>
to create a new url which the browser cannot cache at this point.
It is based on inspecting the host assembly version so make sure to increment
[assembly: AssemblyVersion("3.4.9.0")]
[assembly: AssemblyFileVersion("3.4.9.0")]
this solution won't solve the dynamic modules you may download in the future. you will need to fix the actual cache headers if this is your problem.
edit 1: code to disable browser caching
//http://stackoverflow.com/questions/1160105/asp-net-mvc-disable-browser-cache
//http://developer.yahoo.com/performance/rules.html#expires
//http://ray.jez.net/prevent-client-side-caching-with-httpmodules/
//http://stackoverflow.com/questions/2281919/expiry-silverlight-xap-file-from-browser-cache-programmatically
public class XapFileHttpModule : IHttpModule
{
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
public void Dispose()
{
}
private void context_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if(context.Request.FilePath.Contains(".xap"))
{
context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
context.Response.Cache.SetValidUntilExpires(false);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
}
}
#endregion
}

Application caching is done via manifest files caching, when manifests signatures changes, runtime will upgrade the local files (moreover it just upgrade the changed files). Just sure that you has the right headers sent on HTTP responses. Sometimes dynamic pages cache settings or hosting providers global settings interfere. For me, it always works out of the box.

ClickOnce worked for me like a charm. Also make sure that you're versioning your XBAP properly.

I deploy my Xbap by simply copying filest to ClientBin directory in my web project.
I display it in iframe.
To make application "refresh" version I have to change "Publish Version" in Xbap project before build.
Project Properties -> Publish -> Publish Version.
This changes version in xbap and manifest file forcing clients to download newest version.

Related

How do i update live content on Nancy Hosting Framework

Iam using Nancy Framework with C# and my views are rendered from HTML files. If i need to udate the code in my HTML,CSS or JS (which is part of the content), I have to go through the long annoying process of
Stopping the running C# project
Editing my HTML,CSS or JS File
Saving the changes
Running the C# project
Refreshing the browser
Waiting for the connection to localhost:8080 to be established (This usually takes a bit longer on the first run and that is even more annoying)
7.Finally i get to see if that CSS styling has been applied...if it has not be applied, i have to start the whole process from 1.
Please help me if u have a better way of doing this if not maybe just explain to me why i always have to wait a few more seconds for the first run of the C# project to start allowing connections on the browser.
Nancy does not cache CSS or JS files, they are pass-through files when they exist under Content folder, or if you explicitly set them up in the static conventions.
To disable View Caching, simply disable caches in your bootstrapper:
StaticConfiguration.DisableCaches = true
Edit:
Based on your comment:
https://github.com/richorama/Jukebox/blob/master/Jukebox/Controllers/Home.cs#L11
namespace Jukebox.Controllers
{
public class Home : NancyModule
{
public Home()
{
Get["/"] = x =>
{
return Response.AsFile("default.htm");
};
}
}
}
This will load the htm file off the disk every request. So I'm not entirely sure what issues you're running into. None-the-less try disabling the caches.
Also caching is only enabled when you're running the code in Release mode...
Edit 2:
Since you're using a console app and files are copied to the bin.
https://github.com/NancyFx/Nancy/wiki/The-root-path#changing-the-root-path
Create a implementation of the rootpath provider pointing to your dev directory. Configure it to only run during development.
Do you get 304 - Not Modified HTTP status code for the HTML, JS and CSS files? If so, then the files are cached by browser. Disable the caching either on the server side as Phill suggested or disable the browser caching (which might be counter-productive).

VS2013 publish Web deployment task failed The file is in use

I am using VS2013 Premium to publish a site to Windows Server 2012.
All files publish ok except these:
SqlServerTypes\x64\msvcr100.dll
SqlServerTypes\x64\SqlServerSpatial110.dll
SqlServerTypes\x86\msvcr100.dll
SqlServerTypes\x86\SqlServerSpatial110.dll
I get this kind of errors for each of the above files I tried to publish:
Web deployment task failed. (The file 'msvcr100.dll' is in use. Learn more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_FILE_IN_USE.)
Interrestingly, these files were published the first time (when they were not on the server), then they are no longer overwritten. Tried with 2 different web servers.
I have followed the guide here:
http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
...But it only managed to put the site offline (VS is placing the app_offline.htm) but publish still fails with the same error.
All other files publish perfectly.
Any ideas?
You can take you app offline during publishing which hopefully should free up the lock on the file and allow you to update it.
I blogged about this a while back. The support outlined was shipped inside of the Azure SDK and Visual Studio Update. I don't remember the exact releases but I can find out if needed. Any update dating around/after that blog post should be fine.
Prerequisites:
VS 2012 + VS update / VS 2013 + VS Update / VS2015
MSDeploy v3
Note: if you are publishing from a CI server the CI server will need the updates above as well
Edit the publish profile
In VS when create a Web Publish profile the settings from the dialog are stored in Properties\PublishProfiles\ as files that end with .pubxml. Note: there is also a .pubxml.user file, that file should not be modified
To take your app offline in the .pubxml file add the following property.
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
Notes
ASP.NET Required
The way that this has been implemented on the MSDeploy side is that an app_offline.htm file is dropped in the root of the website/app. From there the asp.net runtime will detect that and take your app offline. Because of this if your website/app doesn't have asp.net enabled this function will not work.
Cases where it may not work
The implementation of this makes it such that the app may not strictly be offline before publish starts. First the app_offline.htm file is dropped, then MSDeploy will start publishing the files. It doesn't wait for ASP.NET to detect the file and actually take it offline. Because of this you may run into cases where you still run into the file lock. By default VS enables retrys so usually the app will go offline during one of the retrys and all is good. In some cases it may take longer for ASP.NET to respond. That is a bit more tricky.
In the case that you add <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline> and your app is not getting taken offline soon enough then I suggest that you take the app offline before the publish begins. There are several ways to do this remotely, but that depends on your setup. If you only have MSDeploy access you can try the following sequence:
Use msdeploy.exe to take your site offline by dropping app_offline.htm
Use msdeploy.exe to publish your app (_make sure the sync doesn't delete the app_offline.htm file_)
Wait some amount of time
Publish the site
Use msdeploy.exe to bring the app online by deleting app_offline.htm
I have blogged how you can do this at http://sedodream.com/2012/01/08/howtotakeyourwebappofflineduringpublishing.aspx. The only thing that is missing from that blog post is the delay to wait for the site to actually be taken offline. You can also create a script that just calls msdeploy.exe directly instead of integrating it into the project build/publish process.
I have found the reason why the solution at
http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
did not work for the original poster, and I have a workaround.
The issue with the EnableMSDeployAppOffline approach is that it only recycles the app domain hosting the application. It does not recycle the app pool worker process (w3wp.exe) which the app domain lives in.
Tearing down and recreating the app domain will not affect the Sql Server Spatial dlls in question. Those dlls are unmanaged code which are manually loaded via interop LoadLibray calls. Therefore the dlls live outside the purview of the app domain.
In order to release the files locks, which the app pool process puts on them, you need to either recycle the app pool, or unload the dlls from memory manually.
The Microsoft.SqlServer.Types nuget package ships a class which is used to load the Spatial dlls called SqlServerTypes.Utilities. You can modify the LoadNativeAssemblies method to unload the unmanaged dlls when the app domain is unloaded. With this modification when msdeploy copys the app_offline.htm the app domain will unload and then unload the managed dlls as well.
[DllImport("kernel32.dll", SetLastError = true)]
internal extern static bool FreeLibrary(IntPtr hModule);
private static IntPtr _msvcrPtr = IntPtr.Zero;
private static IntPtr _spatialPtr = IntPtr.Zero;
public static void LoadNativeAssemblies(string rootApplicationPath)
{
if (_msvcrPtr != IntPtr.Zero || _spatialPtr != IntPtr.Zero)
throw new Exception("LoadNativeAssemblies already called.");
var nativeBinaryPath = IntPtr.Size > 4
? Path.Combine(rootApplicationPath, #"SqlServerTypes\x64\")
: Path.Combine(rootApplicationPath, #"SqlServerTypes\x86\");
_msvcrPtr = LoadNativeAssembly(nativeBinaryPath, "msvcr100.dll");
_spatialPtr = LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial110.dll");
AppDomain.CurrentDomain.DomainUnload += (sender, e) =>
{
if (_msvcrPtr != IntPtr.Zero)
{
FreeLibrary(_msvcrPtr);
_msvcrPtr = IntPtr.Zero;
}
if (_spatialPtr != IntPtr.Zero)
{
FreeLibrary(_spatialPtr);
_spatialPtr = IntPtr.Zero;
}
};
}
There is one caveat with this approach. It assumes your application is the only one running in the worker process that is using the Spatial dlls. Since app pools can host multiple applications the file locks will not be released if another application has also loaded them. This will prevent your deploy from working with the same file locked error.
There are known issues with IIS and file-locks (why they aren't solved yet i dont know).
The question i want to ask however is if you even need to re-deploy these files?
I recognize the file-names and recall them to be system-files which should either already be present on the server or simply not need to be re-deployed.
I am not very experienced when it comes to IIS but i have ran into this problem before and several of my more experienced co-workers have told me that this is as i said a known IIS-issue and i believe the answer to your question is:
Avoid deploying unnecessary files.
try again
Reset website
try again
iisreset
I think what would be the easiest thing to do is to make these dll's as CopyLocal as true. I am assuming these dll's are pulled out from program files folder. Try marking them as copylocal true and do a deployment.Try to stop any IIS local process running in your local machine.
Watch out you don't have one of those new-fangled cloud backup services running that is taking file locks - and also you don't have things open in explorer or a DLL inspection tool.
I think it's kind of ridiculous that MS doesn't make better provisions for this problem. I find that 9 times out of 10 my deployment works just fine, but then as our traffic increases that can become 1 in 10 times.
I am going to solve the problem with :
two applications MySite.A and MySite.B, where only one is running at a time.
I always then deploy to the dormant site.
If there's a problem during the deployment it will never cause the whole site to go down.
If there's a major problem after deployment you can revert back very easily.
Not quite sure how I'm implementing it, but I think this is what I need to do.

Application_start not working

I have written some code in the application_start() method in my global.asax file. It does not get called when I deploy my application on IIS server. The code is accessible when I run it in the .NET framework.
I've tried to restart the application many times, but it's still not working.
I've also tried the suggestion from the following link.
Application_Start not firing?
There are few things you need to know before you are trying to debug Appplication_Start. There are -
One : When the code executes and why it is almost impossible to debug by attaching to it.
The application start method is executed when the application pool starts and your website is being started up for the first time. If you deploy new deliverables to IIS, then IIS might restart it itself, but there is no guarantee that it will. So, deploying new codes does not guarantee that it will restart the pool and he execution of application start. You should restart your application pool to guarantee execution of application start.
While debugging IIS applications, Visual Studio attaches itself to a process something named w3wp.exe or similart (I forgot the actual executable name), which is the worker process and only available after, remember after, your application pool is up and your site is up. So, in other words, if you are seeing this in service list, then the application start has already been executed and attaching to it will not give you a chance to debug it. It is kind of a tug of war with time.
So, in other words, it is kind of impossible to debug application start unless you are very very quick.
Two, the solution 1 - With Dev Server
Launch your application in visual studio with Asp.net development server or IIS express, then you will be able to debug. But if you really want to debug on IIS, then check the next section
Two, the solution 2 - With IIS
There is a library in the name System.Diagnostics, Debuggerand it has a nice way to call debugger in code. You can read it here - http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break(v=vs.110).aspx
Modify you application start with this -
public void Application_Start(){
....... //other codes
Debugger.Break() or Debugger.Launch()
}
When this line executes, IIS will halt execution, and will show you a debugger selector window (similar to the one attached), keep your solution open in vs and select that vs from the list, will be able to debug as usual... :)
In case you are using windows 8 and the debugger does not launch, read this article to enable it -
http://blogs.msdn.com/b/mapo/archive/2013/11/07/debugger-launch-not-displaying-jit-debugger-selection-popup-on-windows-8-8-1.aspx
Three: A very important thing
I noticed that you said, you are adding db entries in Application_Start. You should keep in mind that, Application_Start does not have a HttpContext, ViewContext, So your db access code may fail for so many others reasons.
Make sure that the Global.asax file is actually deployed to the destination folder in the root. If the file is not present then the code behind you have written for Application_Start will never be called.
Also make sure the signature is correct
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {/*do something here like logging so you know it was called*/}
}
If you are running Server 2008R2 (or earlier) and/or IIS 7.5, you might want to look into the Application Initialization module. This can be downloaded here:
www.iis.net/downloads/microsoft/application-initialization
With IIS versions prior to 8.0, the application start is not called until the first web request arrives. I'm reading your question as you want your application start to be fired before the first web request, yes?
Here is a fantastic guide to configuring this module (if it applies to you):
https://blogs.msdn.microsoft.com/benjaminperkins/2014/01/07/configure-the-iis-application-initialization-module/
The key takeaways is that you need to set your app pool to 'AlwaysRunning' instead of 'OnDemand'. You also need to set a preloadEnabled flag for your website. Once both of these are done, fire off an iisreset and you should see the results of your application start (look in the database since it's writing there).
Other answers are relevant as well, in that this is tough to debug and you're missing all the niceties you're used to such as a httpcontext in app start.
If you are running IIS 8.0 - you should still read the above link to configure preloading.
This did work for me:
Menu -> Build -> Clean Solution
Menu -> Build -> Rebuild Solution
Then, Application_Start() was fired only for the first time.
In my case in production environment App_global.asax.compiled was missing and all content of global.asax not fired.

How to update your exe from remote host - c# 4.0 - wpf application

I want to update my exe from remote server. So when the button clicked on my wpf application it will download the remote and also a remote txt file and replace the current ones in the same folder that exe running. So it will overwrite the current txt and and exe file while my exe is running. How can i achive this ?
Remote host is url like www.mydomain.com/MyAPP.exe
wpf application , c# 4.0
The way that we resolved this issue was to create a shell exe that as the one that was installed and deployed initially to the client machines.
The "real" executable program is stored in a subdirectory of this initial app. When the shell app is launched, after it has downloaded and installed any updates for the real app, it launches the real app's executable in a separate AppDomain.
Here is the core of the "real" app launching from within the shell app:
System.AppDomainSetup oSetup = new System.AppDomainSetup();
string sApplicationFile = null;
// Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
oSetup.ShadowCopyFiles = "true";
oSetup.ApplicationName = sAppName;
// Generate the name of the DLL we are going to launch
sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");
oSetup.ApplicationBase = sApplicationDirectory;
oSetup.ConfigurationFile = sApplicationFile + ".config";
oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;
// Launch the application
System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
oAppDomain.SetData("App", sAppName);
oAppDomain.SetData("User", sUserName);
oAppDomain.SetData("Pwd", sUserPassword);
oAppDomain.ExecuteAssembly(sApplicationFile);
// When the launched application closes, close this application as well
Application.Exit();
Note that in our version, the shell app collects the user name and password from the user in order to access the update web site correctly. This data is then passed to the "real" app through the SetData method on the AppDomain.
The solution depends on your particular case. But there's no straight solution, because you can't update assemblies while they are loaded into memory and being used. I can propose 2 solutions: using shadow copying and using some sort of helper executable. I've used both of them.
Shadow copying.
The obvious way is to make your main executable to be shadow copied, replace it while your app is running and then restart the app. But you can't make your default app domain to be shadow copied, only secondary app domains can be. But you still can move all your code into another assembly (say, MainAppLib.dll) and rewrite your main app executable (MainApp.exe) so that it contains only "loader code". This loader code has to create another app domain, set it to be shadow copied and then run your program logic in the secondary app domain. Beware not to have any direct references from your main app domain into MainAppLib.dll because then this assembly will be loaded into your main app domain which is not shadow copied and the assembly file will get locked. In most cases you can go with AppDomain.ExecuteAssembly() methods.
Helper executable
The idea is to use some sort of update finisher. Your main app remains unchanged, you only add a little amount of code into it, so that your app will download update, put it into temporary folder, and then your main app starts update finisher (in separate process) and exits. Update finisher waits till your app closes and then copies new files from temporary folder into your app folder replacing all files. Update finisher can't replace it's own executable but it can be done by main application before it starts the update finisher. After copying files update finisher runs your application.
p.s. Personally I prefer the former solution because it involves some sort of voodoo magic using app domains, reflection, assemblies e.t.c. And it can be evolved into using plugins if you need (e.g. via MEF framework). But the latter is easier to understand especially if you have never worked with app domains and manual assemblies loading, it's quite straightforward.
You could probably use ClickOnce (based on your comment above that you would be prepared to have another assembly get the exe....as the other poster mentioned you can't replace a running assembly). You can configure it to check at various times (e.g. on startup) for new versions and it automatically downloads them. Its a very robust solution and you can do a lot with the deployment assemblies.

Sharepoint cannot see newly deployed features and will not activate them

I've been updating a SP2010 solution which integrates an external content source into search via BCS. This solution deploys a feature (featureA) to the farm scope. I split it into two features, one (FeatureA) deploying to the farm scope, and one (featureB) to the site scope.
My update script does this:
Deactivate FeatureA on the farm
Update-SPSolution with the new wsp file (same name)
Activate FeatureA on the farm
Activate FeatureB on the two sites (on two different web apps)
The script bombs on the last two steps, saying
Enable-SPFeature : The Feature is either not found or not a Farm Level Feature. Use Url parameter to specify the scope of the Feature.
for the first one (farm), and
Enable-SPFeature : The Feature is not a Farm Level Feature and is not found in a Site level defined by the Url http://url-site
on the second one (sites)
This is a test run on the CI server, which means it will also crash on the production server.
However, deploying the package on my machine, and activating the features, works fine.
I've checked, the features are actually present in the SharePoint folder, so the deployment seems to have gone ok. I can't work out why SharePoint can't see them though. If I run Get-SPFeature, they are not in the list.
I've tried iisreset, to no avail.
EDIT:
I've managed to get SharePojnt to notice the two features, by using Install-SPFeature.
However, it still won't enable FeatureB, but errors out with:
Enable-SPFeature : Attempted to perform an unauthorized operation.
I'm at a bit of a loss once again.
You cannot use Update-SPSolution when new files have been added to the solution package.
From Update-SPSolution:
The Update-SPSolution cmdlet upgrades a deployed SharePoint solution in the farm. Use this cmdlet only if a new solution contains the same set of files and features as the deployed solution. If files and features are different, the solution must be retracted and redeployed by using the Uninstall-SPSolution and Install-SPSolution cmdlets, respectively.
For more information, see Adding Features during Solution Update

Categories

Resources