3

I'm creating an application in .NET 4 which needs to update the configuration for the application during the runtime of the application. The code that does this is as follows:

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["MySetting"].Value = "my value";
config.Save();

My App.Config looks like this...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="MySetting" value="my old value"/>
  </appSettings>
</configuration>

When I run this application on a local drive (and therefore the configuration file is also going to be on the local drive when the program is run) then this code works. If, however, the application is run with the configuration file on a network share (actually Z:) then the code fails with the following exception on the config.Save(); line...

System.InvalidOperationException was unhandled
  Message=Method failed with unexpected error code 1.
  Source=mscorlib
  StackTrace:
       at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
       at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean isContainer, String name, AccessControlSections includeSections, Boolean isDirectory)
       at System.Security.AccessControl.FileSecurity..ctor(String fileName, AccessControlSections includeSections)
       at System.Configuration.Internal.WriteFileContext.DuplicateTemplateAttributes(String source, String destination)
       at System.Configuration.Internal.WriteFileContext.DuplicateFileAttributes(String source, String destination)
       at System.Configuration.Internal.WriteFileContext.Complete(String filename, Boolean success)
       at System.Configuration.Internal.InternalConfigHost.StaticWriteCompleted(String streamName, Boolean success, Object writeContext, Boolean assertPermissions)
       at System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext, Boolean assertPermissions)
       at System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext)
       at System.Configuration.Internal.DelegatingConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext)
       at System.Configuration.UpdateConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext)
       at System.Configuration.MgmtConfigurationRecord.SaveAs(String filename, ConfigurationSaveMode saveMode, Boolean forceUpdateAll)
       at System.Configuration.Configuration.SaveAsImpl(String filename, ConfigurationSaveMode saveMode, Boolean forceSaveAll)
       at System.Configuration.Configuration.Save()
       at MyProj.Program.Main() in Z:\repos\project\MyProj\Program.cs:line 61
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
       at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
       at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
       at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
       at System.Activator.CreateInstance(ActivationContext activationContext)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

I'm thinking that this is some sort of security issue with .NET, but I'm not sure how I would disable that security.

The network share that the configuration file is stored on is actually a VirtualBox shared drive. The host system is linux, and the shared drive is mapped to an Ext4 filesystem.

I don't believe this is simply a filesystem write issue, as I can successfully write to a text file in the same directory as my App.config file (at least I think it's the same directory, unless .NET is doing something funky behind the scenes like using a temp directory).

File.WriteAllText("Text.txt", "Testing");
Mark Hildreth
  • 42,023
  • 11
  • 120
  • 109
  • 1
    Looks like filesystem permission issues. Does the user that runs the program have write permissions on the share? – MarioDS Oct 29 '12 at 18:03
  • @MarioDeSchaepmeester: I don't believe this is a problem. I was able to successfully write to a text file with the same program without any problems. – Mark Hildreth Oct 29 '12 at 18:08
  • What's the file system on the VirtualBox drive? – Richard Deeming Oct 29 '12 at 18:23
  • @Richard: The Virtualbox host is running Linux, the mapped directory is on an Ext4 filesystem. I'm not sure how the Virtualbox client (Windows) system sees that in terms of a file system. – Mark Hildreth Oct 29 '12 at 18:26
  • Is the executable also on the network share? – Joachim Isaksson Oct 29 '12 at 18:32
  • This looks like a framework bug. It's assuming that, because it's running on NT, the file-system will be NTFS. When it tries to read the ACL from the file, the function is failing because it's not an NTFS volume. – Richard Deeming Oct 29 '12 at 18:33
  • @JoachimIsaksson: Yes. I have two versions of the code, one is on my C:, the other is entirely on the network share. The program begins to execute fine on each one, and I can even modify the program to write to the same directory as the .exe in either case. It's just the save call that is throwing an error. – Mark Hildreth Oct 29 '12 at 18:35
  • Error code one means "Incorrect Function". It is the standard error you get when a drive in windows in inaccessible. Can you append/overwrite to a file too? – AbdElRaheim Oct 31 '12 at 03:52
  • It might be the same issue as I just described here: http://stackoverflow.com/questions/20946627/how-to-work-around-localfilesettingsprovider-requiring-full-control-ownerrights Were you ever able to solve the problem? – realMarkusSchmidt Jan 06 '14 at 09:20

2 Answers2

0

This looks like a Code Access Security issue, there is a good post here: http://www.sellsbrothers.com/Posts/Details/1519

Basically when you run an application from a network drive, by default it is given a trust level of "Intranet" which I don't think will allow you to modify the config file.

So basically you would need to elevate the trust level for that drive by doing something like this:

caspol -q -machine -addgroup 1 -url file://z:/* FullTrust -name "Z Drive"

Hope that helps, I don't have access to a network drive so can't confirm.

Jamil Geor
  • 337
  • 2
  • 5
  • 1
    That doesn't apply to .NET 4.0 - everything loaded from a network drive gets full trust. This was changed in 3.5 SP1: http://blogs.msdn.com/b/brada/archive/2008/08/13/net-framework-3-5-sp1-allows-managed-code-to-be-launched-from-a-network-share.aspx – Richard Deeming Oct 30 '12 at 13:05
  • As Richard said, the problem that you mention does not apply to .NET 4.0. – Mark Hildreth Nov 06 '12 at 16:48
0

I tried the caspol and using .Net 4 but with no success. This may be silly, but I only managed it to work doing this:

  • Getting the APP_CONFIG_FILE and storing it in a local variable
  • Replacing the actual APP_CONFIG_FILE with a file in a local file system
  • Modify the settings as you wish
  • Copy and overwrite the APP_CONFIG_FILE on the network drive with the local one
  • Set the APP_CONFIG_FILE to the original file on the network
  • Delete the local file

For instance:

string APP_CONFIG_FILE = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
string TEMP_FILE = System.IO.Path.GetTempPath() + Guid.NewGuid();
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", TEMP_FILE);

Configuration config = 
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["MySetting"].Value = "my value";
config.Save();

File.Copy(TEMP_FILE, APP_CONFIG_FILE, true);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", APP_CONFIG_FILE);
File.Delete(TEMP_FILE);

The funny thing is that when I run the program in a machine with Visual Studio installed, it worked well (without caspol) without the need of using the steps above.

Daniel Bonetti
  • 2,306
  • 2
  • 24
  • 33