none
reading another applications' user.config file RRS feed

  • Question

  • Hi I am trying to read configuration information from another assemblies' config file.

     

    This is made slightly more difficult by the fact that the assemblies are Add-ins in Excel.

    Excel is the executable hosting the assemblies.

     

     

     'let's figure it out - this is setting i am after in the user.config of the other assembly
     My.Settings.AdminPath()
    
     Dim exePath As String = _
     System.IO.Path.Combine( _
      Environment.CurrentDirectory, "Excel.exe")
    
     'My current app.config - not useful
     Dim config As System.Configuration.Configuration = _
      ConfigurationManager.OpenExeConfiguration( _
      ConfigurationUserLevel.None)
    
     'This is the excel config file excel.exe.config
     Dim config As System.Configuration.Configuration = _
      ConfigurationManager.OpenExeConfiguration(exePath)
    
     'I need the current user.config for Excel.exe - DOESN'T WORK
     Dim config As System.Configuration.Configuration = _
      ConfigurationManager.OpenExeConfiguration(exePath, ConfigurationUserLevel.PerUserRoamingAndLocal)
    
    

     


    the first one returns the app.config from my executing assembly directory
    "C:\Users\Evaluation\Documents\Visual Studio 2010\Projects\MyFolder\MyProject\bin\Debug\app.config "

    the second one returns the excel.exe.config located next to my Excel.exe in:

    "C:\Program Files\Office\Office14\excel.exe.config

    but the third one fails, obviously because the method doesn't support passing path and setting the configuration user level.

    that example is the one that I would like to work :)

     

    i'm looking for this file

    "C:\Users\Evaluation\AppData\Local\Microsoft_Corporation\

    C__Users_Evaluation_Docum_Path_130ghvfpdy11qeun0r1a5nfcnn5po3o3\14.0.6024.1000\user.config"

     

    But I don't know where the file is located because it changes location with every Microsoft Update to Excel.

     

    Any idea how I can get it loaded into a Configuration object by simply asking the Configuration Manager for it?

     

    I'd rather not walk the XML.



    Thanks,

    Jordan 


    • Edited by Jordan B Wednesday, July 20, 2011 11:49 PM more info
    Wednesday, July 20, 2011 11:44 PM

Answers

  • Hi Jordan,

    You can run below code in your Excel addin. Then you can get the file path of the user.config from the Configuration.FilePath property.

    Dim config As System.Configuration.Configuration = _
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal)

    Save the file path in a place where your own application can read it. Once you get the file path, you can call OpenMappedExeConfiguration to get the Congfiguration object in your application.

    public static Configuration OpenMappedExeConfiguration(
     ExeConfigurationFileMap fileMap,
     ConfigurationUserLevel userLevel
    ) http://msdn.microsoft.com/en-us/library/ms134269.aspx

    ----------------------------------------
    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Thanks,
    Carson Wang

    • Marked as answer by Jordan B Friday, July 29, 2011 9:41 PM
    Wednesday, July 27, 2011 6:51 AM
  • I have worked on this code for awhile using the approach Carson suggested. It was alot harder than I imagined, so I decided to post this here in the thought someone somewhere will be able to use it.

    Everything is working well, except for one problem where the Configuration.GetSectionGroup("userSettings") fails

    if the user.config has ever been upgraded to a new version of the Excel.exe executable

    (which is highly likely, given the number of Microsoft Office Updates)

    Using the My.Settings.Upgrade() strips critical section information off the user.config
     

    I have opened a separate thread on the forum to address that problem http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/28956781-8c39-4cbc-87c1-86b1bd23ca6f

     

    Imports Microsoft.VisualBasic
    Imports System.Collections.Specialized
    Imports System.Xml
    Imports System.IO
    Imports System.Configuration
    Imports System.Diagnostics
    
    Public Class MySample
    
    #Region "Code for the First Add-In or assembly"
     'THIS CODE GOES IN THE FIRST ADD-IN OR ASSEMBLY WHERE YOU ARE STORING USER SETTINGS OR INPUT FROM THE USER, IN THIS CASE MyCOMAddIn
     Public Function PutInMyCOMAddIN()
     Dim roamingPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
     Dim localPath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
     Dim userPath As String = Environment.GetEnvironmentVariable("UserProfile")
    
     Try
      System.Diagnostics.Debug.WriteLine("I'm in the COM Add-in startup complete.")
    
      'Set an intial value in a user setting called AdminPath
      'My.Settings.AdminPath = "User Scope Setting"
      'My.Settings.Save()
    
      Dim config As System.Configuration.Configuration = _
      ConfigurationManager.OpenExeConfiguration( _
      ConfigurationUserLevel.PerUserRoamingAndLocal)
    
      'I'm using a hardcoded string here but you can make your own.
      config.SaveAs("C:\Users\Evaluation\AppData\Local\Microsoft_Corporation\Shared\User.Config")
    
      'throws an exception because W7 knows it's not good to save it there.
      'config.SaveAs("C:\program files\Shared\Config\User.Config")
    
     Catch ex As Exception
      System.Diagnostics.Debug.WriteLine(ex.Message.ToString())
     End Try
    
     End Function
    
     'This also goes in the COMAddIn
     Public Function UpgradeUserSettings()
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     ' User's local settings stored in USER.CONFIG are replaced with a new set of 
     ' default values when the Excel version number changes, i.e. through a Microsoft
     ' Office update perhaps. This code will copy the user's current settings into the
     ' new USER.CONFIG file.
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     If My.Settings.UpdateUserSettings Then
      My.Settings.Upgrade()
      My.Settings.UpdateUserSettings = False
      System.Diagnostics.Debug.WriteLine("I updated the user.config to the latest version of Excel.exe")
     End If
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     End Function
    
    #End Region
    
    #Region "Code for the other add-in or assembly"
    
     'THE REST OF THIS CODE GOES IN THE ADD-IN OR ASSEMBLY THAT WHERE YOU WOULD LIKE TO GET INFORMATION FROM MyCOMAddIN's user.config
     Public Function GetUserConfigInformation()
    
     'see if I can get the user.config
     Dim localPath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
     Dim roamingPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    
     'This is the path to the excel.exe.config
     Dim exePath As String = _
     System.IO.Path.Combine( _
      Environment.CurrentDirectory, "Excel.exe")
    
     'This is the path to the Roaming user.config
     Dim configRoamingPath As String = System.IO.Path.Combine(roamingPath, "Microsoft_Corporation\Shared\user.config")
    
     'This is the path to the Local user.config
     Dim configLocalPath As String = System.IO.Path.Combine(localPath, "Microsoft_Corporation\Shared\user.config")
    
     'Opens the excel.exe.config
     Dim execonfig As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(exePath)
    
     Dim fileMap As System.Configuration.ExeConfigurationFileMap = New ExeConfigurationFileMap()
    
     fileMap.ExeConfigFilename = exePath & ".config"
    
     fileMap.LocalUserConfigFilename = configLocalPath
    
     fileMap.RoamingUserConfigFilename = configRoamingPath
    
     Try
      Dim config As Configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.PerUserRoamingAndLocal)
    
      Dim sectionGroups As ConfigurationSectionGroupCollection = config.SectionGroups
    
      'For debugging
      ShowSectionGroupCollectionInfo(sectionGroups)
    
      'THIS LINE FAILS IF THE USER.CONFIG WAS UPGRADED BY My.Settings.Upgrade() - THIS IS A PROBLEM
      Dim cUSG As System.Configuration.UserSettingsGroup = config.GetSectionGroup("userSettings")
    
      Dim cCSC As System.Configuration.ConfigurationSectionCollection = cUSG.Sections
    
      Dim result As String
      Dim myconfigSection As System.Configuration.ConfigurationSection
      Dim key As String
    
      'Supposedly, I should be using a NameValueConfigurationCollection here, but I could never get it to work.
      Dim nvc As NameValueCollection
    
      For Each key In cCSC.Keys
      System.Diagnostics.Debug.Print("Key value: {0}", key)
    
      If key.ToString = "MyCOMAddin.My.MySettings" Then
       myconfigSection = cCSC.Item(key)
       result = myconfigSection.SectionInformation.GetRawXml()
    
       nvc = SharedModule.GetNameValueCollectionFromXml(result)
    
       For Each ValueKey In nvc.AllKeys
       System.Diagnostics.Debug.Print(" {0,-10} {1}", ValueKey, nvc(ValueKey))
       Next
      End If
    
      Next (key)
     Catch ex As Exception
      System.Diagnostics.Debug.WriteLine(ex.Message.ToString())
     End Try
     End Function
    
     Public Function GetNameValueCollectionFromXml(xml As String) As NameValueCollection
    
     Dim nvc As New NameValueCollection()
     Dim foundName As Boolean = False
     Dim foundValue As Boolean = False
     Dim name As String = ""
     Dim value As String = ""
    
     Using reader As XmlReader = XmlReader.Create(New StringReader(xml))
    
      While reader.Read()
    
      If reader.LocalName.ToLower() = "setting" Then
    
       If reader.HasAttributes Then
    
       name = reader.GetAttribute("name")
       foundName = True
    
       End If
      End If
      If reader.LocalName.ToLower() = "value" Then
    
       value = reader.ReadInnerXml.ToString()
       foundValue = True
    
      End If
      If foundName And foundValue Then
       nvc.Add(name, value)
       foundName = False
       foundValue = False
      End If
    
      End While
    
    
      reader.Close()
     End Using
    
     If nvc.Count = 0 Then
      nvc = Nothing
     End If
    
     Return nvc
    
     End Function
    
    #Region "Walking the configuration files"
     Private indentLevel As Integer = 0
    
     Sub ShowSectionGroupCollectionInfo( _
     ByVal sectionGroups _
     As ConfigurationSectionGroupCollection)
    
     Dim group As ConfigurationSectionGroup
     For Each group In sectionGroups
      ShowSectionGroupInfo(group)
     Next group
     End Sub 'ShowSectionGroupCollectionInfo
    
     Sub ShowSectionGroupInfo( _
     ByVal sectionGroup As ConfigurationSectionGroup)
     ' Get the section group name.
     indent("Section Group Name: " + sectionGroup.Name)
    
     ' Get the fully qualified section group name.
     indent("Section Group Name: " + sectionGroup.SectionGroupName)
    
     indentLevel += 1
    
     indent("Type: " + sectionGroup.Type)
     indent("Is Group Required?: " + _
      sectionGroup.IsDeclarationRequired.ToString())
     indent("Is Group Declared?: " + _
      sectionGroup.IsDeclared.ToString())
     indent("Contained Sections:")
    
     indentLevel += 1
     Dim section As ConfigurationSection
     For Each section In sectionGroup.Sections
      indent("Section Name:" + section.SectionInformation.Name)
     Next section
     indentLevel -= 1
    
     If (sectionGroup.SectionGroups.Count > 0) Then
      indent("Contained Section Groups:")
    
      indentLevel += 1
      Dim sectionGroups As ConfigurationSectionGroupCollection = _
      sectionGroup.SectionGroups
      ShowSectionGroupCollectionInfo(sectionGroups)
      indentLevel -= 1
     End If
    
     indent("")
     indentLevel -= 1
    
     End Sub 'ShowSectionGroupInfo
    
     Sub indent(ByVal text As String)
     Dim i As Integer
     For i = 0 To indentLevel - 1
      System.Diagnostics.Debug.Print(" ")
     Next i
     System.Diagnostics.Debug.Print(Left(text, 79 - indentLevel * 2))
     End Sub 'getSpacer
    
    #End Region
    #End Region
    End Class
    
    


     



    • Edited by Jordan B Wednesday, August 10, 2011 2:59 PM spacing
    • Marked as answer by Jordan B Wednesday, August 10, 2011 4:23 PM
    Wednesday, August 10, 2011 2:57 PM

All replies

  • Hi

    I guess you are looking for this

    http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/8241e079-2514-4945-a9d5-47a4e9f2793d


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".
    Thursday, July 21, 2011 12:32 PM
  • Hi

    Thanks for the reply, but doesn't solve my issue. 

     Dim config As System.Configuration.Configuration = _
     ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal)
    
    

    This is the code suggested by the thread you posted - it only returns the user.config of the current assembly.

    The code works, but I am trying to get the user.config of a different application/assembly than the one currently executing.

    I would like to pass in the location of the executable (exepath) and the PerUserRoamingAndLocal option at the same time. In my examples in my original post, I can do both of these things separately but not at the same time.

    So in theory, I would pass into OpenExeConfiguration exepath of

    C:\Program Files\Office\Office14\Excel.exe

    and the option PerUserRoamingAndLocal

    and then it would return the configuration file located here:

    C:\Users\Evaluation\AppData\Local\Microsoft_Corporation\

    C__Users_Evaluation_Docum_Path_130ghvfpdy11qeun0r1a5nfcnn5po3o3\14.0.6024.1000\user.config

     

    I see alot of people walking the XML but my problem is that even if I wanted to or could walk the XML, I still need to know where the user.config is located first, and there is no way to compute the location, so the .NET framework needs to tell me where it is first.

    For example, if I was to somehow determine the location of this user.config file

    The variables involved are:

    1.Drive where the user profiles are stored, in this case C

    2.Operating system, dictating the folder name for users (in this casw it's w7, so "Users"), and where to look in step 4 for the Application Data

    3. Username, in this case "Evaluation"

    4. locality of the profile, (Roaming,Local or LocalLow), in this case "Local" and for w7, "AppData" for Local profile data, so "AppData\Local"

    5. The convention of "Microsoft_Corporation", used for storing user.config data for microsoft products.

    6. Then we get to the really fun one. This is where I am lost, and I need the .NET framework to tell me how decipher this. This folder is some kind of hash with the folder where the user decided to install the add-in for Excel, so I have no idea how to compute this. "C__Users_Evaluation_Docum_Path_130ghvfpdy11qeun0r1a5nfcnn5po3o3\"

    7. Then, finally, the current version of the exe in question, in this case, Excel.exe current application version "14.0.6024.1000"

     

    Number 6 is deal breaker for me on walking the user.config in XML, otherwise it would be possible althought not preferable. I hope this make sense.

    Just to restate,

    I'm looking for a way to retrieve the user.config for an assembly excuting inside of the application excel.exe. My code does not know the location of the user.config because it is not the executing assembly, I simply want to read the user.config as a way to share some setting information between two pieces of code that have no cross-appdomain marshaling available.

     

    Thanks, Jordan

    Saturday, July 23, 2011 5:52 PM
  • Hi,

     

    Thank you for your question, we're doing research on this case, it might take some time before we get back to you.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, July 26, 2011 1:23 AM
  • Hi Eric, Thank you for your reply. I appreciate you looking into this issue for me.

    I did find a relevant post from an old MSDN blogger:

    http://blogs.msdn.com/b/rprabhu/archive/2005/06/29/433979.aspx


    I think the information below suggests writing my own SettingsProvider if I want to store the file in a less obscure location. I'm not sure this would be an option for me since my assembly is an Excel add-in.

    However, This article did help me understand the user.config file storage logic in better detail, but did not assist me in finding a solution.

     

    Q: You said user.config files go in the user data path. How can I locate the file? Are there multiple files for an application or just one?

     

    A: As mentioned before, the default SettingsProvider for client applications (called the LocalFileSettingsProvider) stores settings in the application configuration files. In .NET v1 and v1.1, there were two levels of config files - machine.config and app.exe.config (where 'app.exe' is the name of the application). In v2.0, we have added two more levels of configuration to store user specific data - one that goes in the roaming user profile path and another in the local user profile path. On XP, the profile directories would be something like 'c:\Documents and Settings\<username>\Application Data' and 'c:\Documents and Settings\<username>\Local Settings\Application Data' respectively. These directories are the recommended location (per Windows Logo requirements) for storing user specific information and most applications (like Outlook and Visual Studio) put user data somewhere under here.

     

    The exact path of the user.config files looks something like this:

     

    <Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config

     

    where

     

    <Profile Directory> - is either the roaming profile directory or the local one. Settings are stored by default in the local user.config file. To store a setting in the roaming user.config file, you need to mark the setting with the SettingsManageabilityAttribute with SettingsManageability set to Roaming.

     

    <Company Name> - is typically the string specified by the AssemblyCompanyAttribute (with the caveat that the string is escaped and truncated as necessary, and if not specified on the assembly, we have a fallback procedure).

     

    <App Name> - is typically the string specified by the AssemblyProductAttribute (same caveats as for company name).

     

    <Evidence Type> and <Evidence Hash> - information derived from the app domain evidence to provide proper app domain and assembly isolation.

     

    <Version> - typically the version specified in the AssemblyVersionAttribute. This is required to isolate different versions of the app deployed side by side.

     

    The file name is always simply 'user.config'.

     

    If you want to get to the path programmatically, you can do it using the Configuration Management API (you need to add a reference to System.Configuration.dll). For example, here is how you can get the local user.config file path:

     

       Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);

       Console.WriteLine("Local user config path: {0}", config.FilePath);

     

    Q: Why is the path so obscure? Is there any way to change/customize it?

     

    A: The path construction algorithm has to meet certain rigorous requirements in terms of security, isolation and robustness. While we tried to make the path as easily discoverable as possible by making use of friendly, application supplied strings, it is not possible to keep the path totally simple without running into issues like collisions with other apps, spoofing etc. 

     

    The LocalFileSettingsProvider does not provide a way to change the files in which settings are stored. Note that the provider itself doesn't determine the config file locations in the first place - it is the configuration system. If you need to store the settings in a different location for some reason, the recommended way is to write your own SettingsProvider. This is fairly simple to implement and you can find samples in the .NET 2.0 SDK that show how to do this. Keep in mind however that you may run into the same isolation issues mentioned above .

    Tuesday, July 26, 2011 3:49 PM
  • Hi Jordan,

    You can run below code in your Excel addin. Then you can get the file path of the user.config from the Configuration.FilePath property.

    Dim config As System.Configuration.Configuration = _
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal)

    Save the file path in a place where your own application can read it. Once you get the file path, you can call OpenMappedExeConfiguration to get the Congfiguration object in your application.

    public static Configuration OpenMappedExeConfiguration(
     ExeConfigurationFileMap fileMap,
     ConfigurationUserLevel userLevel
    ) http://msdn.microsoft.com/en-us/library/ms134269.aspx

    ----------------------------------------
    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Thanks,
    Carson Wang

    • Marked as answer by Jordan B Friday, July 29, 2011 9:41 PM
    Wednesday, July 27, 2011 6:51 AM
  • Hi Carson,

     

    Thank you for your reply. I do believe that will work, although not ideal. Some days you just have to go with what works. Thanks for suggesting this. Of course, this assumes that you have the source to the first add-in to be able to save the original application's user.config to a new location (or a less obscure location). Each time the add-in's user settings are updated, the copy must be updated too. Then, my other assembly can read the user.config settings from the user.config stored in the known or "less obscure" folder location. I think that's brilliant. Sometimes you just get tunnel vision on these things and want it to work exactly as it is in your head. 

     

    Thanks,

    Jordan

    Friday, July 29, 2011 9:41 PM
  • I have worked on this code for awhile using the approach Carson suggested. It was alot harder than I imagined, so I decided to post this here in the thought someone somewhere will be able to use it.

    Everything is working well, except for one problem where the Configuration.GetSectionGroup("userSettings") fails

    if the user.config has ever been upgraded to a new version of the Excel.exe executable

    (which is highly likely, given the number of Microsoft Office Updates)

    Using the My.Settings.Upgrade() strips critical section information off the user.config
     

    I have opened a separate thread on the forum to address that problem http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/28956781-8c39-4cbc-87c1-86b1bd23ca6f

     

    Imports Microsoft.VisualBasic
    Imports System.Collections.Specialized
    Imports System.Xml
    Imports System.IO
    Imports System.Configuration
    Imports System.Diagnostics
    
    Public Class MySample
    
    #Region "Code for the First Add-In or assembly"
     'THIS CODE GOES IN THE FIRST ADD-IN OR ASSEMBLY WHERE YOU ARE STORING USER SETTINGS OR INPUT FROM THE USER, IN THIS CASE MyCOMAddIn
     Public Function PutInMyCOMAddIN()
     Dim roamingPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
     Dim localPath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
     Dim userPath As String = Environment.GetEnvironmentVariable("UserProfile")
    
     Try
      System.Diagnostics.Debug.WriteLine("I'm in the COM Add-in startup complete.")
    
      'Set an intial value in a user setting called AdminPath
      'My.Settings.AdminPath = "User Scope Setting"
      'My.Settings.Save()
    
      Dim config As System.Configuration.Configuration = _
      ConfigurationManager.OpenExeConfiguration( _
      ConfigurationUserLevel.PerUserRoamingAndLocal)
    
      'I'm using a hardcoded string here but you can make your own.
      config.SaveAs("C:\Users\Evaluation\AppData\Local\Microsoft_Corporation\Shared\User.Config")
    
      'throws an exception because W7 knows it's not good to save it there.
      'config.SaveAs("C:\program files\Shared\Config\User.Config")
    
     Catch ex As Exception
      System.Diagnostics.Debug.WriteLine(ex.Message.ToString())
     End Try
    
     End Function
    
     'This also goes in the COMAddIn
     Public Function UpgradeUserSettings()
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     ' User's local settings stored in USER.CONFIG are replaced with a new set of 
     ' default values when the Excel version number changes, i.e. through a Microsoft
     ' Office update perhaps. This code will copy the user's current settings into the
     ' new USER.CONFIG file.
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     If My.Settings.UpdateUserSettings Then
      My.Settings.Upgrade()
      My.Settings.UpdateUserSettings = False
      System.Diagnostics.Debug.WriteLine("I updated the user.config to the latest version of Excel.exe")
     End If
     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     End Function
    
    #End Region
    
    #Region "Code for the other add-in or assembly"
    
     'THE REST OF THIS CODE GOES IN THE ADD-IN OR ASSEMBLY THAT WHERE YOU WOULD LIKE TO GET INFORMATION FROM MyCOMAddIN's user.config
     Public Function GetUserConfigInformation()
    
     'see if I can get the user.config
     Dim localPath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
     Dim roamingPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    
     'This is the path to the excel.exe.config
     Dim exePath As String = _
     System.IO.Path.Combine( _
      Environment.CurrentDirectory, "Excel.exe")
    
     'This is the path to the Roaming user.config
     Dim configRoamingPath As String = System.IO.Path.Combine(roamingPath, "Microsoft_Corporation\Shared\user.config")
    
     'This is the path to the Local user.config
     Dim configLocalPath As String = System.IO.Path.Combine(localPath, "Microsoft_Corporation\Shared\user.config")
    
     'Opens the excel.exe.config
     Dim execonfig As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(exePath)
    
     Dim fileMap As System.Configuration.ExeConfigurationFileMap = New ExeConfigurationFileMap()
    
     fileMap.ExeConfigFilename = exePath & ".config"
    
     fileMap.LocalUserConfigFilename = configLocalPath
    
     fileMap.RoamingUserConfigFilename = configRoamingPath
    
     Try
      Dim config As Configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.PerUserRoamingAndLocal)
    
      Dim sectionGroups As ConfigurationSectionGroupCollection = config.SectionGroups
    
      'For debugging
      ShowSectionGroupCollectionInfo(sectionGroups)
    
      'THIS LINE FAILS IF THE USER.CONFIG WAS UPGRADED BY My.Settings.Upgrade() - THIS IS A PROBLEM
      Dim cUSG As System.Configuration.UserSettingsGroup = config.GetSectionGroup("userSettings")
    
      Dim cCSC As System.Configuration.ConfigurationSectionCollection = cUSG.Sections
    
      Dim result As String
      Dim myconfigSection As System.Configuration.ConfigurationSection
      Dim key As String
    
      'Supposedly, I should be using a NameValueConfigurationCollection here, but I could never get it to work.
      Dim nvc As NameValueCollection
    
      For Each key In cCSC.Keys
      System.Diagnostics.Debug.Print("Key value: {0}", key)
    
      If key.ToString = "MyCOMAddin.My.MySettings" Then
       myconfigSection = cCSC.Item(key)
       result = myconfigSection.SectionInformation.GetRawXml()
    
       nvc = SharedModule.GetNameValueCollectionFromXml(result)
    
       For Each ValueKey In nvc.AllKeys
       System.Diagnostics.Debug.Print(" {0,-10} {1}", ValueKey, nvc(ValueKey))
       Next
      End If
    
      Next (key)
     Catch ex As Exception
      System.Diagnostics.Debug.WriteLine(ex.Message.ToString())
     End Try
     End Function
    
     Public Function GetNameValueCollectionFromXml(xml As String) As NameValueCollection
    
     Dim nvc As New NameValueCollection()
     Dim foundName As Boolean = False
     Dim foundValue As Boolean = False
     Dim name As String = ""
     Dim value As String = ""
    
     Using reader As XmlReader = XmlReader.Create(New StringReader(xml))
    
      While reader.Read()
    
      If reader.LocalName.ToLower() = "setting" Then
    
       If reader.HasAttributes Then
    
       name = reader.GetAttribute("name")
       foundName = True
    
       End If
      End If
      If reader.LocalName.ToLower() = "value" Then
    
       value = reader.ReadInnerXml.ToString()
       foundValue = True
    
      End If
      If foundName And foundValue Then
       nvc.Add(name, value)
       foundName = False
       foundValue = False
      End If
    
      End While
    
    
      reader.Close()
     End Using
    
     If nvc.Count = 0 Then
      nvc = Nothing
     End If
    
     Return nvc
    
     End Function
    
    #Region "Walking the configuration files"
     Private indentLevel As Integer = 0
    
     Sub ShowSectionGroupCollectionInfo( _
     ByVal sectionGroups _
     As ConfigurationSectionGroupCollection)
    
     Dim group As ConfigurationSectionGroup
     For Each group In sectionGroups
      ShowSectionGroupInfo(group)
     Next group
     End Sub 'ShowSectionGroupCollectionInfo
    
     Sub ShowSectionGroupInfo( _
     ByVal sectionGroup As ConfigurationSectionGroup)
     ' Get the section group name.
     indent("Section Group Name: " + sectionGroup.Name)
    
     ' Get the fully qualified section group name.
     indent("Section Group Name: " + sectionGroup.SectionGroupName)
    
     indentLevel += 1
    
     indent("Type: " + sectionGroup.Type)
     indent("Is Group Required?: " + _
      sectionGroup.IsDeclarationRequired.ToString())
     indent("Is Group Declared?: " + _
      sectionGroup.IsDeclared.ToString())
     indent("Contained Sections:")
    
     indentLevel += 1
     Dim section As ConfigurationSection
     For Each section In sectionGroup.Sections
      indent("Section Name:" + section.SectionInformation.Name)
     Next section
     indentLevel -= 1
    
     If (sectionGroup.SectionGroups.Count > 0) Then
      indent("Contained Section Groups:")
    
      indentLevel += 1
      Dim sectionGroups As ConfigurationSectionGroupCollection = _
      sectionGroup.SectionGroups
      ShowSectionGroupCollectionInfo(sectionGroups)
      indentLevel -= 1
     End If
    
     indent("")
     indentLevel -= 1
    
     End Sub 'ShowSectionGroupInfo
    
     Sub indent(ByVal text As String)
     Dim i As Integer
     For i = 0 To indentLevel - 1
      System.Diagnostics.Debug.Print(" ")
     Next i
     System.Diagnostics.Debug.Print(Left(text, 79 - indentLevel * 2))
     End Sub 'getSpacer
    
    #End Region
    #End Region
    End Class
    
    


     



    • Edited by Jordan B Wednesday, August 10, 2011 2:59 PM spacing
    • Marked as answer by Jordan B Wednesday, August 10, 2011 4:23 PM
    Wednesday, August 10, 2011 2:57 PM