I have multiple projects in a solution. Each project has its own app.config file. I want to have a single app.config or settings file which can be used across the solution. What I see is now, when i want to add some settings common to the application I will have to add an entry it in all the projects app.config file.
I want to have a single configurable file (XML) which can be used in whole application. At run time if the value of any key is changed, my application should be able to get that changed value from the XML.
It's a arquiteture problem. Why you can't have a unique webconfig file. Everytime that you need to update an application, will have to update all.
I think It's wrong.
You can to try a solution bellow:
The best and correct option. Uses one commom Redis Cache. Everybody can call it.
Save the configuration in one commom database table. So will have only one update in the solutions changes.
Use a noSql(mongodb, cosmosdb etc.) database. It's faster then sql.
Use one WebAPI. You can consult the configurations and to caching the information in each service.
obs: But if you whant a file. Can put in the solution and create a command to copy and replace the config when to build the solution. Like this:
Copying Visual Studio project file(s) to output directory during build
flw
You can use a linked file for using the same file in multiple projects in the same solution. This is good for using in multiple test projects that run either locally or from a build machine, however, for production code a centralized configuration would be a better approach.
For linking a file via the "Add Existing Item" select the arrow on the "Add" button and then choose "Add As Link".
Related
Now I have seen this question before on SO in a variant ways, but surprisingly not in this form:
I have a solution with multiple web services (projects) that need to talk to each other. After publishing each of these web services might end up on a different machine with a different database. To tell each web service where all other web services are, I want to maintain a single config file during development.
I would like to expect that after publishing the config to be present in each published project. And I would like to expect the config file to be editable after publishing, so I can swiftly migrate a certain web service and then just edit all config files of the other web services.
I don't want to do this in the database, for the config file its self should also hold connection settings to the database(s).
I came across the following ideas/thoughts/questions:
I have a dll project called 'common' that is referenced by other projects. Let's give that one a shared.config and build a class in that project that can be used to read out the shared.config by doing System.Configuration.ConfigurationManager.OpenExeConfiguration("shared.config"). Just need to make sure the shared.config will be published along with the DLL.
I would favor this solution, as it would also let me keep a web.config inside each project having just the project specific settings. And have the shared.config having the shared settings. But I read on SO that this should not be considered lightly and could have some unwanted side-effects, like file-access-issues; though I wonder if this would apply to my case. Also I would like to ask your help here on how to actually realize this as I don't think Visual Studio supports app.config for DLL projects out of the box.
I also thought about creating a shared.config file in the Solution Items. Then linking that file inside each project. And in the Web.config of each projects, add: <appSettings configSource="shared.config" /> pointing to the linked file in that project.
Though I cannot find any reason why not to do this, first implementation failed. It seems (at least during development), c# cannot find the linked shared.config file. I'm guessing linking files is not done instantly nor maintained after creating the linked file, but the file is only copied to the projects WHEN I do a publish. Thus leaving the file missing during development. Is this correct?
The config files are app specific. This mean that you can add a config file to a class library but the file will then by used by the app (windows service, webservice and so on) referencing the library.
Same thing for external configSource, this are app specific as well and need to be included withing the project using it.
So if your solution is composed by 2 projects you then need 2 config files. One for each project.
While for a windows based application(services, winforms) the expected folder for config files is the bin directory, for web based projects this will be the directory is the root folder of the virtual directory.
This said, using a shared config file looks the easier solution (and you don't have to copy the app.config from the class library for each project). Here are the steps :
Create a solution folder.
Add the config file to it.
Add the file as a reference for each project needing it. Right click the project and Add existing item - > Choose the file and Add as link
Ensure the file is always copied by setting the copy option (properties of the file) with Copy Always.
At this point you should have the config file deployed into your project directory everytime you compile the solution.
EDIT:
I'd avoid looking into the bin for config files within a web app, the
convention is that file should be in the root, so I would avoid the
first option.
Linked files end up in the bin after building the project. Try the same steps for importing the file but this time simply add it (not as link) and it will be deployed as content in the root of your site, so it can be always available.
If your hosting in IIS it is possible to have a single web.config file at the root site level but Giorgio is right in that app.config files are app specific. it is possible to use custom build steps to automate the copying of config files across multiple projects so personally I would go with that.
This actually drove me a bit crazy. In the end I fixed it like this:
Created a Shared.config file in the dll project 'common', having the contents look like any ordinary web.config/app.config.
Set the file to be Content and Copy Always, so it would surely be copied out to all projects that reference project common. (Though the config file will indeed end up in the bin folder.
Created the class SharedConfiguration inside the common project. The really tricky part was having to use OpenMappedExeConfiguration() , and getting the path to the executable directory (including bin, and without file:// in front of it).
Now when I want to access a setting from the shared settings, I do SharedConfiguration.instance.AppSettings.Settings["CubilisEntryPointUrl"].Value.
(I cannot use SharedConfiguration.instance.AppSettings["CubilisEntryPointUrl"] directly because of this issue)
.
public static class SharedConfiguration
{
public static readonly Configuration instance = GetConfiguration("Shared.config");
private static Configuration GetConfiguration(string configFileName)
{
ExeConfigurationFileMap exeConfigurationFileMap = new ExeConfigurationFileMap();
Uri uri = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
exeConfigurationFileMap.ExeConfigFilename = Path.Combine(uri.LocalPath, configFileName);
return ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None);
}
}
In several C# projects I have been using an app.config file to pass various settings to my program, settings like connectionstrings, power levels etc.
However sometimes I have come in situations where the settings aren't updated as expected and I have concluded that I am not that well informed with the proper use of app.config file.
Example:
Replacing the .exe file with a new version (where settings are different) to the output directory without changing the exe.config, results in the program seeing the hard-coded settings and not the settings of the existing .exe.config
So my Questions are:
What is the exact role of exe.manifest file
Every time I create a new .exe do I have to paste in the output folder anything else except the .exe file?
Whats the difference in obtaining the setting value by: ConfigurationManager.'settingName'... rather than:
Properties.Settings.Default.'settingName'?
What is the role of app.config build action?
Sorry If I am asking too much in a single Question.
The app.config file is a file that gets a special treatment when running the associated application. If you executable is named MyApp.exe the app.config file should be named MyApp.exe.config. The role of the app.config build task is to copy the file named app.config in your project to MyApp.exe.config in the output directory.
.NET provides ways to read the contents of the file (it is in XML format) and various parts of .NET will look for different sections in this XML to provide configuration.
A widely used section is the settings section you refer to as Properties.Settings.Default. This section plays together with Visual Studio that provides an editor for application settings. The settings are accessed in the code by using a generated class. Adding a setting will add a property to this class and this property is initialized from a value in the app.config file.
In the Visual Studio editor you can set a value for the setting and you can think of this as a default value for the setting. However, if you overwrite the value in the app.config file the later will take precedence. This allows you to modify the app.config file after installation and rerun the application with a modified setting.
You can also access application settings the app.config file using other methods, but in my oppinion using the Visual Studio editor and the code generated class is the best way to do that.
I am not sure I fully understand the problem that you experience. If you update MyApp.exe and leave MyApp.exe.config intact you should not see a change in the settings used by the application (unless of course you have renamed or changed some settings).
The manifest file provides information about side-by-side assemblies and can be used to request elevated privileges among other things. This is not related to the app.config file.
There quite a few resources about that.
See http://msdn.microsoft.com/en-us/library/ms229689%28v=vs.90%29.aspx
and the (better) overview: http://msdn.microsoft.com/en-us/library/k4s6c3a0%28v=vs.110%29.aspx
app.config is a very powerful tool. It addresses many issue like versioning, migration, upgrading etc. but this requires some in-depth reading from the links above.
Maybe one thing you could do, if you want to copy only .exe file every time you build your app, is make a settings.ini or settings.txt file, put your parameters in this file (that are not secret of course) and read all your settings from there when you start your app.
You can put all your connection string logic in your login form if you have one...
I have a console application that builds some default classes for me from a database. When the files are built, I want to be able to refresh my folders and see the new files in my class library.
However no matter what I do the files don't show up unless I go in and manually add existing files. Is there a way for VS2010 to look at the file folder and add in anything that is in that folder to the project? For example:
Folder > File1.cs, File2.cs, File3.cs, File4.cs
VS2010 sees
Folder > File1.cs
How can I make VS2010 show these new classes?
Your problem is that you will only see files that are included and referenced in your .csproj file. This is by and large a good thing because it gives you ultimate control over what is taken into account in the project or not. This is causing you a problem though, because the created files which are inserted into your project directory aren't being referenced. As you have mentioned you can include the files manually, but I understand that you wish this process to be automatic.
The best way to resovle this in my opinion is instead of having a project create the files, use design-time T4 templates. Design-time T4 templates are files which resemble pre-Razor ASP.NET views, which allow code generation within your project. You can access your database, format your classes and then output .cs files directly into your project without building it. This is extremely convenient becuase it lets you work on catching compile-time errors that may come up based on the output without having to do a complete build.
More information about using T4 can be found here.
And a good walkthrough can be found here.
Haven't tried this personally, but you should be able to do it using this..
First gain a reference to your project using your apps' solution, then with the Visual Studio automation framework (DTE):
ProjectItems p = Project.ProjectItems;
p.AddFromFile("File1.cs");
Taken from: http://msdn.microsoft.com/en-us/library/envdte.projectitems.addfromfile.aspx
I would read further into it.
Select the project where you can find your file
On top of your solution explorer you can select "show all files"
Select your files and include
Adding them automatically can be done from another app or script by modifying your projects .csproj/vbproj file
<Compile Include="My Project\MyClass.vb" />
This must be done in the correct itemgroup.
I think this is not directly possible. You may write a template file (t4) in order to create you cs files and they will be added to project when the transformation file is run.
In order to run the transformation file after / before build, you may write a pre/post build event.
That will require you to create a VS add-in.. you can find an example here...
Okay so I have a console application that is building some default classes for me from a database.
Can't you let this application write all classes in one file, say Proxy.cs or Entities.cs. Then every time you regenerate the file and rebuild the project, you can access the new classes.
I have a Visual Studio 2010 Solution that contains three projects:
A Windows Service which will read Data from a SQLite Database to perform actions
A Winforms App which will provide a method of configuring the behaviour of the Service (by updating the SQLite Database)
A Class Library Project to abstract all database access away from the service and the config app (making it easier in the future to update anything having to do with the database without having to hunt down queries in the other two projects)
All of these projects are in the same solution, and I have added references from the Winforms App and the Service to the class library. In both projects I am able to see the classes from the class library and interact with them, but I am having an issue. I have created the database in the /Resources/ directory of my class library project (because to me the "common" project is the only sensible place to store the common database), however whenever I attempt to access the database in the Winforms app, it is not returning data that I know is in there. Since System.Data.SQLite has the default behaviour of creating an empty database file if the file isn't found (an odd choice in my opinion), I can't even go back and tell if the database exists or not.
This leads me to suspect that I am not understanding properly how files from one project are referenced in another. Here is what my project looks like:
WorkModeCommon Contains the classes SQLiteDatabase and ScheduleManager, where ScheduleManager has a SQLiteDatabase() and SQLiteDatabase interacts with Resources/WorkModeSchedules.s3db
Both the WorkModeConfigApp and the WorkModeService have a WorkModeCommon.ScheduleManager(), which should in theory take care of all of the database interaction.
Do I have a major flaw in my design, or could someone point me to a resource which could help me solve the problem I'm having?
I think this is what's happening.
When you reference the common class library, it's simply using the .dll output as the reference, since it's the only output.
However, if you right-click on the .s3db file and go to its Properties, you can set its Copy to Output Directory setting to Copy if newer, that way the database file itself is in the output directory, so the .dll file can see it.
Now, when your form or service access the .dll file from the output directory of your common class library project, it'll reference the .s3db file, too, so then they'll all see the same data.
Whether this is a good design or not depends on your needs.
If the form and the service are both looking at the same data at the same time, then you have to make sure they're at least looking at the same file, not at their own copies of the .s3db file.
If it's just the form or the service accessing the database, I'd be ok with it, but since multiple processes (the form and the service) are accessing it, a common database server is a good choice.
Compiled classes are visible to outside assemblies that reference them as long as their visibility is Public (with some exceptions). Non-compiled files are a different story. You can specify the build action as "embedded resource", which will allow you to access the file from referencing assemblies, albeit in a read-only fashion. The other option, and likely what you want, is to specify "copy to output directory" as either "copy always" or "copy if newer." This will copy the file to the output directory at build time.
When you start debugging your WorkModeConfigApp, the app runs from its bin\debug directory and has no way to reach the resource directory of the class library. Simply referencing the class library doesn't means that VS copy the resource directory of the class library inside the bin/debug of the Config app. If you set the Copy Local = true for the class library VS will copy the compiled DLL inside the bin\debug of WorkModeConfigApp but doesnt' copy the content of the resource directory
On the other way, you could set the property copy to the output directory for the .s3db file, in this way the file and its directory will be copied in the bin\debug of the WorkModeConfigApp. But this will be the source of other problems because during debug your test database risk to be overwritten from the one coming from the class library.
I think that your best option is to save inside the configuration files of the service and of the config app where to locate this file and don't mess with the aforementioned property.
We are talking about a Database so probably in the config file for App and service you need to add a connection string. You could add the required nodes to your App.config, see the example below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="WindowsFormsApplication1.Properties.Settings.MyDatabaseConnection"
connectionString="Data Source=C:\ProgramData\MyAppName\/WorkModeSchedules.s3db;Version=3;Pooling=True;Max Pool Size=100;"/>
</connectionStrings>
</configuration>
You could then access this value using one these methods:
string cnnString1 = ConfigurationManager.ConnectionStrings["MyDatabaseConnection"];
string cnnString2 = Properties.Settings.Default.MyDatabaseConnection;
(The ConfigurationManager method requires the reference to System.Configuration assembly)
Ok folks, I've solved my problem. What I did is include a copy of the DB file in each project, and set the "Copy To Output Directory" property on all but one of those instances (the "Common" project) to "Do Not Copy". After that I changed the output directory for all three projects to the same directory (more specifically, I created centralized Debug and Release directories and pointed the proper build configurations to the proper directories). I am now able to test successfully using a single DB file and a centralized class library!
I have a project that reads in a file based on a value in a C# Setting class. This value however changes from machine to machine and Id rather not ask the user the first time the program is run as its a corporate environment, instead Id like it to be set in the installer, but where is the file located? Is there an easier method?
This is a visual studio addin not a standalone program
From your post it appears you have a windows application? , you can store an initial value in the application config, you can make an installer in Visual Studio and write custom actions that can write values to the file on first install in you install project.
The configure file is the easiest way to do what you are asking, however it is NOT the best. In fact it is recommended Not to use .config files for such cases.
whenever users install an 'update', there is a risk of overwriting their existing changes.
some businesses might have policy restrictions on the .config files.
the user cannot easily move his settings from one PC to another.
From my own experience, using XML, MS-Access, Registry or text files to store user settings has proven more useful than using the .config files.
I believe you are talking about designer-generated settings (the .settings file)?
The exact path usually contains some sort of a Hash (check this link). I usually have my own settings class which I serialize to and from xml using XmlSerializer, which gives me more freedom (I think C# settings files don't allow you to add custom enums, for example, or they make it a bit harder to do it than simply adding them to the .settings file).
However, maybe there is no need to set values during installation? For example, you could add a FirstStartup setting (set to true initially), which you can read when your App is started for the first time, and then set it to false. That way you can set your default settings when you detect a "first startup".
You will certainly need some sort of custom action at the end of your installer. You haven't mentioned what technology you're using to deploy your application so I will refrain from giving any specific guidance.
I recommend setting the value in your App.config. This is an xml file which will be named MyApplication.exe.config in the same directory as your application. Add it to your installer if it is not there already. In your installer, add a new setting:
<configuration>
<appSettings>
<add key="MySetting" value="My Value"/>
</appSettings>
</configuration>
In your code, retrieve the setting:
String setting = ConfigurationSettings.AppSettings["MySetting"];
If this is a machine-wide setting, this installer is the right place to set this. If you do it on the first execution you will run into a host of problems with permissions on the files and directories if the first person to run the app is a user with limited permissions.
Registry or an INI file or a XML file whatever suits you best.
Best option would be registry. Istalling the application will require Admin access so writing to the registry during installation will not be an issue.
More over if some one accidently deletes the ini or settings file then the program might stop working.
You said that this is for a corporate environment. You can create an administrative template for group policy to set the default in the registry. Then, your program can just query that one registry value if the default hasn't already been set.
I personally would never use web.config or app.config. Just read your own xml file, have a look at my post on this:
http://www.picnet.com.au/blogs/Guido/post/2009/09/10/XML-Settings-Files-No-more-webconfig.aspx
Thanks
Guido
To answer the "Where is the file located" bit of the original question for those interested (I'm assuming that the "settings file" in question is the "Settings File" item available from the "Add New Item" dialogue).
In Win7 (and probably all the other ones) the settings file will generate under the path:
C:\Users\[user]\AppData\Local
The folder structure from here on out depends on your AssemblyInfo and build information, the "AssemblyCompany" field (if populated) is used for the top-most folder, beneath this is a folder copying the application executable name, followed by the build and then finally the settings file (named "*.config").
In my case, the complete path is as follows:
C:\Users\[user]\AppData\Local\[company_name]\Application.exe_StrongName_zx0v1qxyoass4d0z3mtwe3vbrhaehkjg\0.0.5812.21662\user.config
My case is different, my project is a class library (dll) which have the app.config file. I decided to create 4 application settings variables (title, url, limit, rate). To create this, i right-click ont he project --> Properties --> Settings. this values you can retrieve in code using this command --> Settings.Default.title, ...etc
the problem is let say i instantiate 5 objects (same object for example MyProject.MyClass) from this library, i want the instance be able to have its own settings. i mean each of the instance may have their xml setting file. can this be done?