tags:

views:

40

answers:

4

I would like to have an offline ClickOnce application (they can run it from Start menu) but I would like my application to function similar to an online one (make sure the web page / server is there to run). This way I can take off (uninstall) a ClickOnce application and it will stop working for end users without having to go to 1000's of desktops. This is for an internal corporate environment, so we have total control over the servers, end clients, etc.

There are a lot of clients out there world wide essentially I would like to give them a message like "This applications functionality has been moved to XXX application, please use it instead." Or "This application has been retired." If I could get the install folder url from code, I could have a message.xml file sitting in that directory that would have some logical tags in it for accomplishing this. If that message isn't there (server offline) I could have the application fail gracefully and instruct the user to contact their local IT for assistance.

If you have another idea for accomplishing this same thing, would be appreciated as well.

A: 

You could create a new version of your application which only contains a messagebox saying "This application is retired" and deploy it.

The next time a user starts the application the new version will be downloaded showing your messagebox.

Carra
The one thing this wouldn't catch is if the web server we have the deployment on has been retired which is another catch I want. I know we can move deployments, but it would only work for people that run the application daily. Sometimes people might not run this app for weeks or months, and I want to catch people that might run this after the web server is offline.
John
A: 

I've used the following code to solve part of your problem:

            try
            {
                // The next four lines probe for the update server.
                // If the update server cannot be reached, an exception will be thrown by the GetResponse method.
                string testURL = ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString();
                HttpWebRequest webRequest = WebRequest.Create(testURL) as HttpWebRequest;
                webRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
                HttpWebResponse webResponse = webRequest.GetResponse() as HttpWebResponse;

                // I discard the webResponse and go on to do a programmatic update here - YMMV
            }
            catch (WebException ex)
            {
                // handle the exception
            }

There may be some other useful exceptions to catch as well -- I've got a handful more in the code I use, but I think the rest all had to do with exceptions that the ClickOnce update can throw.

That handles the missing server case -- though it does require you to have been proactive in putting this in place well before the server is retired.

Richard Dunlap
Thanks, this is exactly what is needed. I had found some source code that glimpsed at this, and posted it as a follow up on my post, but it's good to have the source code here in Stackoverflow itself!I will have to ask a few more questions, and answer some cause I can't up your answer because my rep isn't high enough, but thanks for the post.
John
A: 

What I did was to combine the comments on this question, and some sprinkling of my own to come out with this answer below.

XML Document saved as an HTML (our web servers don't allow XML transfers):

<?xml version="1.0" encoding="utf-8"?>
<appstatus>
    <online status="true" message="online"/>
</appstatus>

Then I have the following code read from the above, and use it to see if the application should close or not:

            string testURL = "";
            try
            {
                // Probe for the update server. 
                // If the update server cannot be reached, an exception will be thrown by the GetResponse method. 
#if !DEBUG
                testURL = ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString() + "online.html"; 
#else
                testURL = "http://testserver/appname/online.html";
#endif
                HttpWebRequest webRequest = WebRequest.Create(testURL) as HttpWebRequest;
                webRequest.Credentials = CredentialCache.DefaultCredentials;
                HttpWebResponse webResponse = webRequest.GetResponse() as HttpWebResponse;
                StreamReader reader = new StreamReader(webResponse.GetResponseStream());
                XmlDocument xmlDom = new XmlDocument();
                xmlDom.Load(reader);
                if (xmlDom["usdwatcherstatus"]["online"].Attributes["status"].Value.ToString() != "true")
                {
                    MessageBox.Show(xmlDom["usdwatcherstatus"]["online"].Attributes["message"].Value.ToString());
                    this.Close();
                    return;
                }
            }
            catch (WebException ex)
            {
                // handle the exception 
                MessageBox.Show("I either count not get to the website " + testURL + ", or this application has been taken offline.  Please try again later, or contact the help desk."); 
            }
John
A: 

You can only get the deployment provider URL if the application is online-only. Otherwise it's not available.

Aside from moving a deployment, you can programmatically uninstall and reinstall the application.

You deploy the new version (or whatever you want to install instead) to another URL. Then you add uninstall/reinstall code to the old version and deploy it. When the user runs it, he will get an update, and then it will uninstall itself and call the new deployment to be installed.

The code for uninstalling and reinstalling a ClickOnce application can be found in the article on certificate expiration on MSDN which is here

RobinDotNet