views:

697

answers:

1

I know that I can load an app.config file from a different location using the following line of code:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", ConfigFile);

where ConfigFile is a full path location. What I'd like to do though is be able to load a file that has been encrypted for the app.config. Ideally, I'd like to be able to load the file, decrypt it, and load it into a string or memory stream and pass it to the app as if it were the app.config. I know I could just load all of the values from it and access them manually, but I'd like to be able to access them using the built in functionality of .NET. Is there a way to tell the app to use the config file from something other than a file?

The other option is to open the file, decrypt it, write it out to a temp file, and then use the above code to reference it that way, but if there was an easier way, ideally, I'd like to find it, to have to avoid dealing with additional files.

A: 

While I was never able to get an answer for this so far, I had to come up with a work-around. This may not be the best solution, but it does work. Basically what we've done is encypted our app.config file, and given it a new name. When the app starts up, it will take the encypted file, decyrpt it, and write it to a Windows temp file. This ensures that the file is some unique random name that no one is likely to find, and we don't have to manage the files, as Windows will delete it for us automatically. This way each re-launch we are able to re-write out a new file and use it. Here's the basic code snippets for anyone who is interested.

This first method, LoadFileAppConfig, will load up the file. In this case, since they are services, we need to load the executing path, and pass it to the appropriate method. We get back the path of the decrypted app.config, and then use the SetData method to set it to be the app.config path.

    /// <summary>
    /// Loads the Local App.Config file, and sets it to be the local app.config file
    /// </summary>
    /// <param name="p_ConfigFilePath">The path of the config file to load, i.e. \Logs\</param>
    public void LoadFileAppConfig(string p_ConfigFilePath)
    {
        try
        {
            // The app.config path is the passed in path + Application Name + .config
            m_LocalAppConfigFile = ProcessLocalAppConfig(p_ConfigFilePath + this.ApplicationName + ".config");

            // This sets the service's app.config property
            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", m_LocalAppConfigFile);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

In this method we are getting the path of the file, passing that file off to be decrypted and returned as a string, and then writing that file to our Windows temp file.

    /// <summary>
    /// 
    /// </summary>
    /// <param name="p_ConfigFilePath"></param>
    /// <returns></returns>
    public string ProcessLocalAppConfig(string p_ConfigFilePath)
    {
        try
        {
            string fileName = Path.GetTempFileName();
            string unencryptedConfig = DecryptConfigData(p_ConfigFilePath);

            FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            StreamWriter streamWriter = new StreamWriter(fileStream);

            if (!string.IsNullOrEmpty(unencryptedConfig))
            {
                try
                {
                    streamWriter.BaseStream.Seek(0, SeekOrigin.End);
                    streamWriter.WriteLine(unencryptedConfig);
                }

                catch (IOException ex)
                {
                    Debug.Assert(false, ex.ToString());
                }
                finally
                {
                    streamWriter.Close();
                }
                return fileName;
            }
            return null;
        }
        catch (Exception)
        {
            throw;
        }
    }

This final method takes in the path of the encrypted app.config, uses our Decryption tool to decrypt the file (ensuring that we can decrypt it, and that it is the right file type) and then returning the decrypted contents as a string to the method above.

    /// <summary>
    /// 
    /// </summary>
    /// <param name="p_AppConfigFile"></param>
    /// <returns></returns>
    private string DecryptConfigData(string p_AppConfigFile)
    {
        string decryptedData = null;
        TMS.Pearl.SystemFramework.CryptographyManager.CryptographyManager cryptManager = new TMS.Pearl.SystemFramework.CryptographyManager.CryptographyManager();
        try
        {
            //Attempt to load the file.
            if (File.Exists(p_AppConfigFile))
            {
                //Load the file's contents and decrypt them if they are encrypted.
                string rawData = File.ReadAllText(p_AppConfigFile);

                if (!string.IsNullOrEmpty(rawData))
                {
                    if (!rawData.Contains("<?xml"))  //assuming that all unencrypted config files will start with an xml tag...
                    {
                        decryptedData = cryptManager.Decrypt(rawData);
                    }
                    else
                    {
                        decryptedData = rawData;
                    }
                }
            }
        }
        catch (Exception)
        {
            throw;
        }

        return decryptedData;
    }
Noah