I want to run a program with different configuration file, the program write with C# 2.0, I make some different file name {program_name}.exe.config, I mean one exe with different config file, for example I have 3 config file, then I will run 3 exe with the different config file, bu the exe file is the same one.
Can I do not modify the program for read the different config file (I don`t want to put the config file path in the exe command parameters) to do that(like use the batch file or other method.) ?
Thanks.
You can change the configuration file for the application domain in which the exe is loaded. This is done using the SetData method of the AppDomain class. Ensure that this line of code is executed as the first line of your application.
I have used following code to share 1 exe.config file between 3 different executables.
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE","yourSharedConfig.exe.config");
You can look at the following blog entry
Binding to custom app.config
If you want to run the same exe with 3 different configs, I believe the same approach will work with bit of customization. You can pass the name of the config file while invoking the exe as a command line parameter and using the SetData method you can dynamically set the config.
I make it with LINQ and passing the parameter as config=path2file
public partial class App : Application {
private void startup(object sender, StartupEventArgs e) {
if (null != e) {
if (null != e.Args && 0 < e.Args.Length) {
string config = e.Args.Where(a => a.StartsWith("config=")).FirstOrDefault();
if (null != config) {
config = config.Substring("config=".Length);
if (File.Exists(config)) {
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", config);
}
}
}
}
}
The main issue you have with three configs and one executable is that you need to specify to the executable which config to use.
One option is to make 3 copies of your executable, exe1.exe, exe2.exe and exe3.exe and have a similarly named config for each - exe1.exe.config, exe2.exe.config and exe3.exe.config.
When running each executable, it will use the correct config.
Another option is to have several batch files that will rename the different config files according to which one you want to use. Then you have a single exe and three configs.
You create a second executable, and always run that one first. In it, all you do is rename one configfile to the correct name and fire the main application.
string currentConfig = "application.exe.config";
string someOtherName = "firstconfig.config";
string configFileYouWant = "secondconfig.config";
string application = "application.exe";
File.Move(currentConfig, someOtherName);
File.Move(configFileYouWant, currentConfig);
Process.Start(application);
Related
I have two projects in my solution, ChatProject and ChatProjectTest.
ChatProjectTest has a single class file that has many methods that test methods in ChatProject.
My problem is that ChatProject uses some files, like data.bin and log.txt, that are stored in the .exe folder (that is ChatProject\bin\Debug\ChatProject.exe). I want ChatProjectTest to use the same files, and not go ahead and create or load new files in its own .exe folder (ChatProjectTest\bin\Debug\ChatProject.exe), like it does currently.
To be clear, the file paths are stored in constant variables in ChatProject like this:
private static string DATABASE_NAME = "data.bin";
I didn't hardcode their paths.
One solution can be configuring your projects to put all the output files into the same the same bin/ directory under your solution root (instead of two separate bin/ folders).
To do this, go to the "Build" tab under project settings and set "Output path" to
$(SolutionDir)Bin\$(Configuration)\
Repeat this for both of your projects.
If you don't specify a path to a file it looks in the current directory for them.
To use the same ones, you either have to specify some sort of relative path from the Test Output, or build the tests into the same folder as the Project.
You may allow the target file path to be injected e. g. via an optional constructor parameter:
public class SampleClass
{
private readonly string OutputDirectory;
public SampleClass(string outputDirectory = ".")
{
OutputDirectory = outputDirectory;
}
public void WriteData(string data)
{
File.AppendAllText($"{OutputDirectory}\\data.bin", data);
}
}
[TestClass]
public class SampleClassTest
{
[TestMethod]
public void WriteDataTest()
{
var sut = new SampleClass("..\\..\\..\\ChatProject\\bin\\Debug");
sut.WriteData("data");
}
}
I'm have this code pulling views embedded as resource in my referenced assembly:
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new EmbeddedFileProvider(typeof(SomeTypeInMyAssembly).GetTypeInfo().Assembly));
});
It successfully finds views in the embedded location (Views\Shared\Components\ViewComponentName\Default.cshtml). I need it to FIRST search for the files in the current project BEFORE looking at any assemblies, this way I can create defaults in an assembly, and allow "overrides" in the main project (same path). Anyone have any ideas how this can be done? I'm still trying to look through the source to figure this out.
And no, ViewLocationExpander is not the answer. I need to use the exact same path and file names, thanks.
Turns out there are TWO options:
Add
options.FileProviders.Add(HostingEnvironment.ContentRootFileProvider);
just before EmbeddedFileProvider. (HostingEnvironment was simply taken
from the Startup() constructor and stored locally in the Startup class. The physical file on disk (could also be in the cache) will be found before the assembly version.
Wrap EmbeddedFileProvider in your own type (implement IFileProvider) and pass in IHostingEnvironment. The GetFileInfo() method is
called while trying to locate files. The
IHostingEnvironment instance is used to detect physical
files from the root content path, and returns NotFoundFileInfo if a local file exists:
public virtual IFileInfo GetFileInfo(string subpath)
{
if (_HostingEnvironment != null)
{
var filepath = Path.Combine(_HostingEnvironment.ContentRootPath, subpath.TrimStart('/'));
if (File.Exists(filepath))
return new NotFoundFileInfo(filepath);
}
return _EmbeddedFileProvider.GetFileInfo(subpath)
}
and add it to Startup.ConfigureServices():
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new MyEmbeddedFileProvider(typeof(SomeTypeInTheTargetAssembly).GetTypeInfo().Assembly, HostingEnvironment));
});
}
I wrote a custom build task that reads values form the appsettings in it's App.config file. When I compile my task as an executable and run it, the task works perfectly. The correct values are read from the config file. However when I compile it as an assembly and run it from a target in my build script I get a System.NullReferenceException. The exception occurs in the foreach loop because the configuration manager returns null.
IEnumerable<string> tables = ConfigurationManager.AppSettings.GetValues(key);
foreach (string txt in tables)
{
Logic.....
}
I'm calling the custom task correctly because I commented out the issue and it builds successfully.
Does anyone know why this might be happening? or if I'm even able to use a App.config file with custom build tasks?
Thanks in advance
If you compile a project as a library, then it reads from the app.config of the calling executable. If you compile a project as an executable, then it reads from it's own app.config.
If anyone is interested I used the following code to access the custom config
private static string[] GetConfigFile()
{
var map = new ExeConfigurationFileMap();
map.ExeConfigFilename = #"C:\ConfigFile.config";
config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
return config.AppSettings.Settings.AllKeys;
}
The above code gets the list of keys from the specified config file.
The return value is stored in a string array which I run through using a foreach loop as seen below
string[] keyNames = GetConfigFile();
foreach (string keys in keyNames )
{
KeyValueConfigurationElement keyval = config.AppSettings.Settings[keys];
Console.WriteLine(keyval.Value);
}
I am using an app.config file to store the dynamic parameters of my application. The problem is, when I change a value in app.config file, and start the application, it doesn't load the new value from config file. Seems like the values in app.config file are being read and embedded in exe file only at compile time!
This is how I read the config file:
public class Helper
{
static Helper()
{
Foo = ConfigurationManager.AppSettings["Foo"];
}
public static string Foo { get; set; }
}
Am I missing something?
Are you sure you are changing the correct file? You don't want to change the app.config file, but the <exename>.exe.config file, in the same directory as the .exe
The app.config file is what you edit in the ide, but when you compile your app this file is renamed to <exename>.exe.config and copied to the output directory when you compile. The .exe looks for a file with the same name as itself with the .config extension when looking for the default configuration.
The static nature of your class and method may be causing you the issue. Maybe refactor it to the following...
public static class Helper
{
public static string Foo
{
get
{
return ConfigurationManager.AppSettings["Foo"];
}
}
}
Actually, thinking about it, it doesn't help you a great deal since ConfigurationManager.AppSettings["Foo"] is already (effectively) a static call - you're just adding another layer of abstraction that may well not be required.
This is very frustrating... I can set the Configuration File for a Windows Forms Application just fine. Consider this:
public static void Main(){
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", #"SharedAppConfig.config");
//do other things
}
However, in a WPF application, this doesn't seem to work! If I set this value, the value of the AppDomain.CurrentDomain.SetupInformation.ConfigurationFile property is correct, but any calls to that configuration file while debugging yield no results. There are WCF configuration settings in an App.config that I need to share between application, so this is my proposed solution. Is it possible to dynamically set the location of my config file in WPF?
Help! Thanks!
You should be able to do something along the lines of:
using System.Configuration;
public class TryThis
{
Configuration config = ConfigurationManager.OpenExeConfiguration("C:\PathTo\app.exe");
public static void Main()
{
// Get something from the config to test.
string test = config.AppSettings.Settings["TestSetting"].Value;
// Set a value in the config file.
config.AppSettings.Settings["TestSetting"].Value = test;
// Save the changes to disk.
config.Save(ConfigurationSaveMode.Modified);
}
}
NOTE: This will attempt to open a file named app.exe.config at C:\PathTo. This also REQUIRES that a file exists at the same path with the name "app.exe". The "app.exe" file can just be an empty file though. For your case I'd almost make a shared "Config.dll" library that would handle the config file.
~md5sum~
Is this on the service side or the client side? If on the service side, it is often the case that the service is running in its own AppDomain, so that if you set AppDomain.CurrentDomain.SetData(...) it won't apply to the service configuration.
I'm not entirely sure how to get around this, but you should be able to control the service's configuration by implementing your own ServiceHost.