none
Here is a method for updating App.Config after ClickOnce Deployment RRS feed

  • Question

  • Simple Scenario: You built a program, deployed it with click once, and now you need to updated a global setting (eg: a connection string) for all the clients but don't wan't to re-publish the program.

     

     

    Initial Steps:

     

    Create a new project with a form and place a Listbox on it. Also add an App.config file and create a setting called "MessageString", APP LEVEL, "This is the Opening Message". Add this code and Publish the ClickOnce application.

     

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    'On the first time through, don't change anything and you should see the original message.

    'Then copy the app.exe.config.deploy file to the root of the publish folder, change the message setting

    'inside, and re-launch the program. It should change

     

    ListBox1.Items.Add("Initial Setting is: " & My.Settings.MessageString)

    ListBox1.Items.Add("")

    CheckForUpdatedConfigFile()

    ListBox1.Items.Add("")

    ListBox1.Items.Add("Current Setting is: " & My.Settings.MessageString)

     

    End Sub

     

    Private Function CheckForUpdatedConfigFile() As Boolean

    'Update our Config File if needed.

     

    Dim strCurrentConfigFile As String = ""

    Dim strNewConfigFile As String = ""

    Dim blnUpdated As Boolean

    Dim objCurrentFile As System.IO.FileInfo

    Dim objNewFile As System.IO.FileInfo

     

    'Grab the app.config filepath of the one currently being used.

    strCurrentConfigFile = Application.ExecutablePath & ".config"

     

    'Grab the app.config filepath from the one in the ClickOnce deployment source

    If System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed = True Then

    strNewConfigFile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString

    strNewConfigFile = strNewConfigFile.ToLower 'Convert it all to lower so it matches our search text

    strNewConfigFile = strNewConfigFile.Replace("/", "\") 'Replace any // with \\

    strNewConfigFile = strNewConfigFile.Substring(strNewConfigFile.IndexOf("\\")) 'Chop off anything in front of the \\ like 'file:'

    strNewConfigFile = strNewConfigFile.Substring(0, strNewConfigFile.IndexOf(".application")) 'Truncate off the trailing .application

    strNewConfigFile &= ".exe.config.deploy" 'Finally tack on the correct extension

    Else

    'For devolopment\debuging you can hard code in a path here

    strNewConfigFile = "x:\PublishedLocation\" & My.Application.Info.AssemblyName & ".exe.config.deploy"

    End If

     

    'Now Grab an instance of each of the Files so we can compare

    ListBox1.Items.Add("Current Config File is: " & strCurrentConfigFile)

    If System.IO.File.Exists(strCurrentConfigFile) Then

    objCurrentFile = New System.IO.FileInfo(strCurrentConfigFile)

    ListBox1.Items.Add("CurrFile Date of: " & objCurrentFile.LastWriteTime.ToString)

    Else

    objCurrentFile = Nothing

    ListBox1.Items.Add("CurrFile Date of: MISSING")

    End If

    ListBox1.Items.Add("Updated Config File is: " & strNewConfigFile)

     

    If System.IO.File.Exists(strNewConfigFile) Then

    objNewFile = New System.IO.FileInfo(strNewConfigFile)

    ListBox1.Items.Add("SrcFile Date of: " & objNewFile.LastWriteTime.ToString)

    Else

    objNewFile = Nothing

    ListBox1.Items.Add("CurrFile Date of: MISSING")

    End If

     

    'And compare their dates (you can of course compare anything you want)

    If (objCurrentFile Is Nothing = False) And (objNewFile Is Nothing = False) Then

    ListBox1.Items.Add("Comparing Files")

    If objCurrentFile.LastWriteTime < objNewFile.LastWriteTime Then

    objCurrentFile = Nothing

    objNewFile.CopyTo(strCurrentConfigFile, True)

    blnUpdated = True

    ListBox1.Items.Add("*** Config File was UPDATED *** ")

    Else

    ListBox1.Items.Add("File doesn't need to be updated")

    End If

    Else

    ListBox1.Items.Add("Missing Current or Source File to compare")

    End If

    objCurrentFile = Nothing

    objNewFile = Nothing

    If blnUpdated = True Then

    My.Settings.Reload()  'This triggers the program to reload so all NEW calls get new values

    End If

     

    Return blnUpdated

     

    End Function

    Thursday, June 5, 2008 8:55 PM

Answers

  •  

    Hi da_jokker,

    Since ClickOnce application is installed per-user, I recommend you set the settings as User-Scoped Setting in the Application Settings. It is much easier to handle as this type of settings allows user changed the value during run time. This also benefits you when you upgrade the application. Simply call ApplicationSettingsBase.Upgrade() and it will retrieve settings from the previous version that match the current version of the class and store them out in the current version's user.config file.

    I don’t think it is good idea to let the user change the Application-Scoped Application Settings. You will need to changed the xml file directly and reload the application to load these settings.

    Hope this helps.
    Best regards.
    Rong-Chun Zhang

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Wednesday, June 11, 2008 8:53 AM

All replies

  •  

    Hi da_jokker,

    Since ClickOnce application is installed per-user, I recommend you set the settings as User-Scoped Setting in the Application Settings. It is much easier to handle as this type of settings allows user changed the value during run time. This also benefits you when you upgrade the application. Simply call ApplicationSettingsBase.Upgrade() and it will retrieve settings from the previous version that match the current version of the class and store them out in the current version's user.config file.

    I don’t think it is good idea to let the user change the Application-Scoped Application Settings. You will need to changed the xml file directly and reload the application to load these settings.

    Hope this helps.
    Best regards.
    Rong-Chun Zhang

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Wednesday, June 11, 2008 8:53 AM
  •  

     

    I agree however in my particular case, the user does not change any settings. While researching my particular issue, what I found what people were looking for ways to update an entire locations settings and not individual users. For example, you have a program that is being used in multiple locations, and you want the system administrator to be able to set the location of your SQL server. However they obviously can't have the source code or the ability to re-compile and re-publish just because they want to change the ConnectionString.

     

    By all means, if your program has settings that the user must update, you will have to put a twist on this. But my proposed method show how you can create the product, and then allow each "site" to make the needed changes and have it updated throughout without having to open up the source and re-publish the entire project.

     

    Thanks for the feedback.

     

    Friday, June 13, 2008 3:25 PM
  •  

    Hi da_jokker,

    One possible approach would be that you can read the connection string from a shared file and let the administrator to edit the file.

    Hope this helps.
    Best regards.
    Rong-Chun Zhang

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Monday, June 16, 2008 11:06 AM
  • I have a similar issue.  The app.config file contains the references for my WCF services that the click once client uses.  These are set by the customer when they install the product and I am looking for a way to update the app.config files for each of the client applications after the install.  The clients are deployed with clickonce inside the customer network.

     

    Any ideas?

     

    Tuesday, July 8, 2008 6:40 PM
  •  

    You could, however you would be in a similar boat... the location of the file would have to be set and then you would have to re-publish the application.

     

    This method allows you to publish the location once, and from that point on, never have to do it again just to change a setting in the App.config file.

     

     

     

     Rong-Chun Zhang - MSFT wrote:

     

    Hi da_jokker,

    One possible approach would be that you can read the connection string from a shared file and let the administrator to edit the file.

    Hope this helps.
    Best regards.
    Rong-Chun Zhang

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Tuesday, July 8, 2008 7:51 PM
  • Generically I would think this would work... that is what it's designed to do. From the Customer side, they would place your "installation" package on their network and then also copy the App.config file to the root of that folder and make any changes they needed and save it (It MUST have a newer datetime stamp than the one in the installation package).

     

    The client would then run the install, and the first time it runs, it would replace the App.config file included in the setup, with the modified copy placed in the root folder...

     

    The key section you are looking at is this:

     

    'Grab the app.config filepath from the one in the ClickOnce deployment source

    strNewConfigFile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString

    strNewConfigFile = strNewConfigFile.ToLower 'Convert it all to lower so it matches our search text

    strNewConfigFile = strNewConfigFile.Replace("/", "\") 'Replace any // with \\

    strNewConfigFile = strNewConfigFile.Substring(strNewConfigFile.IndexOf("\\")) 'Chop off anything in front of the \\ like 'file:'

    strNewConfigFile = strNewConfigFile.Substring(0, strNewConfigFile.IndexOf(".application")) 'Truncate off the trailing .application

    strNewConfigFile &= ".exe.config.deploy" 'Finally tack on the correct extension

     

    What this code is doing is grabbing the applications Deployment location. It then modifies it so that by the time you are done, strNewConfigFile should look something like: :"\\MyAppServer\ProgInstall\ProgramName.exe.config.deploy"

     

    So as long as you have the modified App.Config file where it is expecting to find it, you will be fine.

     

     

     

     

     CTDevelopment wrote:

    I have a similar issue.  The app.config file contains the references for my WCF services that the click once client uses.  These are set by the customer when they install the product and I am looking for a way to update the app.config files for each of the client applications after the install.  The clients are deployed with clickonce inside the customer network.

     

    Any ideas?

     

    Tuesday, July 8, 2008 8:02 PM
  • Mister,

     

    Which class I created this code

     

    'Grab the app.config filepath from the one in the ClickOnce deployment source

    strNewConfigFile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString

    strNewConfigFile = strNewConfigFile.ToLower 'Convert it all to lower so it matches our search text

    strNewConfigFile = strNewConfigFile.Replace("/", "\") 'Replace any // with \\

    strNewConfigFile = strNewConfigFile.Substring(strNewConfigFile.IndexOf("\\")) 'Chop off anything in front of the \\ like 'file:'

    strNewConfigFile = strNewConfigFile.Substring(0, strNewConfigFile.IndexOf(".application")) 'Truncate off the trailing .application

    strNewConfigFile &= ".exe.config.deploy" 'Finally tack on the correct extension

     

    and how I can execute this code using Click Once ?? any tutorial about it.

     

    I generate Publish in UNC, and like you say, modified app.config in root folder, but how can I execute this code ???

     

    The user connect to publish.htm and launch setup.exe.

     

    Any help, please ??

     

    Thanks.

    Friday, September 5, 2008 7:35 PM
  •  

    You would put the code in the very beginning of your program. In my example, it's in the Form Load event of my first form. YOu want the program to update it's settings as soon as it begins to run.

     

    Hope that make sense.

     

     

    Saturday, September 6, 2008 2:56 AM
  • Hi how are you ?
    I have 2 questions for your code:
    Create a new project with a form and place a Listbox on it. Also add an App.config file and create a setting called "MessageString", APP LEVEL, "This is the Opening Message". Add this code and Publish the ClickOnce application
    A
    1-How to creat a setting?
    2-Where to find the APP Level(I double click on MyProject i have Application,Settings and more)
     
    B
     
    I create a database app with VB2005.I build,test and publish it on my network shared folder.
    I copy the deployment output on my second pc to test it.I open .config.deploy file with an
    xml editor and chage the connection string that math with the sql express connection string
    on my second pc.
    I install the app but my program could not connect with the sql server.
    Any help!
     
    Thanks
     
    Talley123
     
     
    Saturday, September 6, 2008 7:58 PM
  • Help with creating the app.config

    Text fo the app.config file Thanks

    Sunday, April 5, 2009 1:58 PM
  • This is the ONLY post that actually solved my problem. Thanks!

    Here's the code in C# as I implemented it... Thanks again!

     

    NOTE: I didn't find a C# equivalent of "My .Application.Info.AssemblyName" so I just hard-coded my dev path

    ----------------------------------------------

       static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                CheckForUpdatedConfigFile();

                Application.Run(new Login());
            }

     

            private static bool CheckForUpdatedConfigFile ()

            {
                // Update our Config File if needed.
                string strCurrentConfigFile = "";
                string strNewConfigFile = "";
                bool blnUpdated = false;
                System.IO.FileInfo objCurrentFile;
                System.IO.FileInfo objNewFile;

                // Grab the app.config filepath of the one currently being used.
                strCurrentConfigFile = Application.ExecutablePath + ".config";

                // Grab the app.config filepath from the one in the ClickOnce deployment source
                if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                {
                    strNewConfigFile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString();
                    strNewConfigFile = strNewConfigFile.ToLower(); // Convert it all to lower so it matches our search text
                    strNewConfigFile = strNewConfigFile.Replace("/", @"\"); // Replace any // with \\
                    strNewConfigFile = strNewConfigFile.Substring(strNewConfigFile.IndexOf(@"\\")); //Chop off anything in front of the \\ like 'file:'
                    strNewConfigFile = strNewConfigFile.Substring(0, strNewConfigFile.IndexOf(".application")); // Truncate off the trailing .application
                    strNewConfigFile += ".exe.config.deploy"; // Finally tack on the correct extension
                }
                else
                {
                    // For devolopment\debuging you can hard code in a path here
                    strNewConfigFile = @"C:\Users\Me\Documents\Visual Studio 2010\Projects\MyProject\ClickOnceWinApp\Custom\App.Custom.config";
                }

                // Now Grab an instance of each of the Files so we can compare
                if (System.IO.File.Exists(strCurrentConfigFile))
                {
                    objCurrentFile = new System.IO.FileInfo(strCurrentConfigFile);
                }
                else
                {
                    objCurrentFile = null;
                }

                if (System.IO.File.Exists(strNewConfigFile))
                {
                    objNewFile = new System.IO.FileInfo(strNewConfigFile);
                }
                else
                {
                    objNewFile = null;
                }

                // And compare their dates (you can of course compare anything you want)
                if (objCurrentFile != null && objNewFile != null)
                {
                    if (objCurrentFile.LastWriteTime < objNewFile.LastWriteTime)
                    {
                        objCurrentFile = null;
                        objNewFile.CopyTo(strCurrentConfigFile, true);
                        blnUpdated = true;
                    }
                }
                objCurrentFile = null;
                objNewFile = null;
                if (blnUpdated)
                {
                    Properties.Settings.Default.Reload(); // This triggers the program to reload so all NEW calls get new values
                }
                MessageBox.Show(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString(), "Connection string from App.Config");

                return blnUpdated;
            }

     

    Friday, May 7, 2010 7:20 PM