tags:

views:

541

answers:

4

Hi,

As I'm polishing my little pet project, I'm trying to store all the constant strings in my app.config file (Keys, XpathExpressions etc). When I run the compiled exe this works great. In the Interactive Shell this isn't the case.

I tried to copy the .config file from my bin/Release directory to the obj/Debug & obj/Release dirs, but the Call to ConfigurationManager.AppSettings.Item("key") always returns null.

Any suggestions how to fix this?

With best regards

A: 

The problem is that FSI is a different exe running behind the scenes and does some crazy tricks with on-the-fly compilation and generation of binaries. Check to see which assembly FSI thinks is running. You might be surprised what you find :)

It will throw an error:

System.NotSupportedException: The invoked member is not supported in a dynamic assembly. at System.Reflection.Emit.AssemblyBuilder.get_Location()

You need to look into how to get app.config settings into dynamic assemblies. This could be a pain, and might not be worth it. If it works as a compiled binary, I'd test those things that rely on config settings outside of FSI.

Good luck.

OJ
+1  A: 

Maybe you could point FSI to the app.config file manually by using the OpenMappedExeConfiguration method on ConfigurationManager.

Also you could try loading your assembly in a separate AppDomain - you can give any file as config file to an AppDomain you create yourself using the AppDomainSetup class.

Th fact remains that FSI isn't well suited to this kind of scenario...

Kurt Schelfthout
+4  A: 

While FSI dynamically generates code for your input, using the fsi.exe.config will work just fine.

I created this file:

<configuration>
    <appSettings>
        <add key="test" value="bar"/>
    </appSettings>
</configuration>

As fsi.exe.config (program files\fsharp-version\bin). Started FSI:

> #r "System.configuration";;
--> Referenced 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.configuration.dll'

> System.Configuration.ConfigurationManager.AppSettings.["test"];;
val it : string = "bar"

It also worked from Visual Studio. (But note that you'll need to reset the session to pickup changes.)

MichaelGG
+2  A: 

F# Interactive can work with executables that rely on app.config files.

The way to do this is to have an .fs file in your project that loads your .config conditional on the COMPILED define so:

let GetMyConfig() =
  let config  = 
    #if COMPILED 
      ConfigurationManager.GetSection("MyConfig") :?> MyConfig
    #else                        
      let path = __SOURCE_DIRECTORY__ + "/app.config"
      let fileMap = ConfigurationFileMap(path) 
      let config = ConfigurationManager.OpenMappedMachineConfiguration(fileMap) 
      config.GetSection("MyConfig") :?> MyConfig
    #endif

then in your script file reference the executable and #load the .fs file so:

#I "../Build/Path

#r "ConfiguredApp.exe"

#load "MyConfig.fs"

On executing these three lines you will see a message similar to the following in the FSI window:

[Loading C:\Svn\trunk\Source\ConfiguredApp\MyConfig.fs]

Binding session to 'C:\Svn\Qar\trunk\Build\Path\ConfiguredApp.exe'...

Notice that you're actually referencing the app.config when in FSI (rather than the generated .exe.config.)

Best of luck...

DannyAsher