I wrote a form application in c# using Visual Studio 2008, third party dlls, an xml file and images. The images have been added to the project as resources.
A System.IO.FileNotFoundException is thrown when I attempt to run the published version of the executable on another machine.
If I copy the .exe file to the desktop on the pc, and also copy the dlls and the xml file to the desktop, double clicking on the exe works fine.
In my project, I have the copyLocal set to true for the required dll references. The xml is added to the project and set to copy if newer to output directory. I also checked the publish application files and everything is there.
The line I use to load the xml file is this
config = new XmlDocument();
config.Load("fileName.xml");
I'm assuming the FileNotFound exception is being thrown when you try to load the XML file, right?
Simply looking for "filename.xml" doesn't seem like a fantastic idea to me, especially if this is a key configuration file for your application.
I typically try to move these things into my App.config file then load them either using a fully qualified path or a short path. For example:
App.config
<add key="ExternalConfig" value="D:\\config.xml"/>
.cs file
config = new XmlDocument();
config.Load(ConfigurationManager.AppSettings["ExternalConfig"]);
You could also use a relative path, but keep in mind that you're always relative to the current working directory.
Alternatively, based on the type of data in your configuration, you could try to store this information to you App.config file and do away with a config.xml altogether.
Related
the problem that i have with my application is about how to reference some files, when i load and image, etc, i use Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\")); and this works fine for debugging and for some files, but doesn't work for some essential files, credentials.txt, config.ini, this files are searched in appdata when i run the published file and i don't know how i should reference them.
I try to generate some initial files so i am sure where they are and that they exists, but for folders that works great with
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
with that i can make the folders where the app is run but you can't generate a file without load the content of the original file, and i don't know how to reference them.
Example:
Project.
Root of the project.
utils/key/credentials.txt
When the published file is executed i want to generate and store credentials.txt like this:
Executable (app.exe stored for example in "my documents")
"my documents"/utils/key/credentials.txt
how i do that? when i run the published application you just have the .exe, the dlls, and the resources are embebbed, so the uri doesn't works.
Assuming you have sufficient permissions, you could create a folder in the output folder of your compiled .exe at runtime using the Directory.CreateDirectory method.
If the utils/key/credentials.txt file is part of your deployment, you should set its Build Action to Content and the Copy to Output Directory property to Copy if newer in Visual Studio. This will add the utils and key folders to the output directory of the .exe, which is typically c:<project-folder\bin\Debug or \Release when you build from Visual Studio.
You can get the absolute path of the output directory like this:
string path = System.IO.Path.GetDirectoryName(
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
Depending on your requirements, you may then append the relative path of the file within your app to the absolute path.
I use xsltc.exe in developer console (ms visual studio). I try to generate a DLL that could be used in a .NET project.
xsltc /settings:dtd /settings:document /settings:script /c:Bk24.Specs specs.xsl /out:Bk24Specs.dll
I have successfully generated many of such DLLs before, but now I have a big problem. The current XSL contains a reference to an XML
<xsl:variable name="spcodes" select="document('specialCodes.xml')/list/data" />
I successfully generated the DLL for this template. I added a reference to this DLL in the .NET project. But then, the application throws an exception
File not found (c:\projects\bk24\specialCodes.xml)
in the real production environment. Of course, on the client's workstation there is no such directory C:\projects\bk24\. It's my directory on my dev machine, but when I ran xsltc.exe, I put specialCodes.xml into the same directory where the XSL is placed. I hoped that xsltc.exe would look at the directory, found that XSLs and XMLs are in the same directory, so, the generator will embed the XMLs into this DLL, but, it seems, it's not...
How can I resolve this issue?
If it is only a read only file, then open the file in a text editor and copy it. Then embed it as a string in any cs class and read with XElement.Parse(that_string)
Due to problem with referencing application config in excel addins (Excel Add-In not loading app.config with service reference config information) I have referenced the assembly location for the config file.
The problem I am now encountering is that each time I launch a debug instance, the assembly is put in a different path (GUID folders under local AppData directory). So I cannot put a copy of the config file in there.
Any suggestions to get around this?
Best solution turned out to be discard above solution and use solution from post:
Change default app.config at runtime
Because while the original link would then allow you to access the config file, you would have to manually extract the information to bind the webservice.
However originally I did persist with the original and found:
To enable the solution in original link to work I had to change the way of accessing directory (which I have now submitted this change to the original linked solution):
AppDomain.CurrentDomain.BaseDirectory
rather than
new FileInfo(Assembly.GetCallingAssembly().Location).DirectoryName
AppDomain.CurrentDomain.BaseDirectory would reference a stable location while debugging (the source directory where the original app.config is located), and the correct install directory for the installed version of the Addin (the addin directory rather than Microsoft Excel directory).
I have a solution containing two projects. One project is just for doing all data stuff and the other one, the startup project, do all the web stuff.
Now I want to get the TasksDataBase.xml from the TaskManagerHelpers class by first getting the projects root directory. But all I get is the TaskManager.Web root directory. (I call the method inside TaskManagerHelpers.cs from a controller inside TaskManager.Web)
How do I get the TaskManager.Data root directory when I'm in a class in the same project?
I've tried with theese methodes and similar ones.
HttpContext.Current.Request.PhysicalApplicationPath;
System.IO.Path.GetFullPath();
AppDomain.CurrentDomain.BaseDirectory;
Thanks in advance!
One possibility is to embed the XML file into the assembly of the class library and then read it as resource in your web application. Remember that when you publish your web application to a web server all that will get into the package will be the files of this web application. There's no physical relation to some projects that might have lived into the Visual Studio solution that this web application was part of.
You may take a look at the GetManifestResourceStream method which will allow you to read the embedded XML from the referenced assembly.
Here's an example:
// you could use any type from the assembly here
var assembly = typeof(TaskManagerHelper).Assembly;
using (var stream = assembly.GetManifestResourceStream("TaskManager.Data.DataBase.TasksDataBase.xml"))
using (var xmlReader = XmlReader.Create(stream))
{
// ... do something with the XML here
}
Bear in mind though that since the file is embedded into the assembly you will not be able to modify it. It is readonly. If you need to modify it then an alternative approach would consist into copying this file to your web application. For example a good place is the App_Data special folder. You could even setup a post compilation step that will copy the XML file in this location.
And then you can reference it easily:
string xmlFile = HostingEnvironment.MapPath("~/App_Data/TasksDataBase.xml");
using (var xmlReader = XmlReader.Create(xmlFile))
{
// ... do something with the XML here
}
In this case since the XML file is now physically part of the web application and lives on the hard drive you could also modify it.
Just because the two projects are located in the same folder tree during development, says nothing about where they'll be located at run time. It's entirely possible that that could be on different machines.
"No," you say. They'll will definitely be on the same machine in the same c:\inetpub tree. That may be true, but that's your policy, not a requirement.
If you are going to establish a hard policy about where they are located, then you can hard-code that into you code.
Right-click the XML file and select properties, then change the Copy to Output Director to one of the other settings than "Do Not Copy". That will place the file into your \bin\ folder alongside the other project output. You can then use AppDomain.CurrentDomain.BaseDirectory as your base path
IF you are running a web project, all the referenced dll files are copied to the bin directory (unless they are in the GAC) and used from there, no matter if you add a reference to another project, Visual Studio first compile it and then copies it to the bin folder of the web project. You can mark your xml file as Content (Compilation Action) and with the copy always option so it always copy it to the bin directory .... the problem is that it sometime look for this files outside of the bin folder but I think that you can handle this.
Here is the task I have been given at work. We have a Web Application for which I created a Console Application that can be executed by the Scheduled Tasks on a daily basis. The task I have be presented with is to discover if we can place the ConApp.exe and the ConApp.exe.config in two different directories (folders) in our application. We would like to place the .exe file in the bin folder with all the .dll's and place the .exe.config file in a central configurations folder. I have been looking around in the properties and such with in Visual Studio and I do not see any options that will allow me to specify to the ConApp.exe the location of the ConApp.exe.config.
Is there a way to place these two files in separate folders or do they need to be in the same folder and have the .exe.confing reference a central .config file?
Thanks, :)
You should be able to use ConfigurationManager.OpenExeConfiguration to do that. You can add a setting in the console application's config file that points out the path and filename to the config file, and pass that value to OpenExeConfiguration (granted that the console runs as an account that has read access to the location where the config file is stored).
Note that if your console app contains statements like ConfigurationManager.AppSettings["somekey"], these will need some rewriting so that they use the Configuration object returned by the OpenExeConfiguration method.
The automatic discovery of the .exe.config works only if the files are in the same folder. But you gave the answer yourself IMHO: have the .exe.config reference another .config file in the desired central location.
No, you cannot tell your app to look in another directory for its main app.config.
What you can do is externalize certain configuration sections to external files in another directory:
<configuration>
<appSettings configSource="config\appSettings.config" />
<connectionStrings configSource="config\connections.config" />
</configuration>
This works - even though in the Visual Studio designer there will be complaints about this - on any .NET configuration section (but not on section groups, e.g. you cannot externalize the entire <system.web> or <system.serviceModel> at once - you need to do it by their sub-elements.
So with help from Fredrik Mork I was able to figure out this solution. First of all when you create your Console Applications, DO NOT, create any setting in the projects properties window. This will create an app.config file in your project which I believe the executable will try to look for and crash if it doesn't find it. When you first create the Console Application and then Build it before writing any code. Visual Studio create the Debug folder with just the executable file and a few supporting files. I then placed this code in the "main" function:
Dim fileMap As ExeConfigurationFileMap = New ExeConfigurationFileMap()
fileMap.ExeConfigFilename = "....../AppName.config"
Dim externalConfig As Configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None)
Dim appS As AppSettingsSection = externalConfig.Sections("appSettings")
Dim reportURL As String = appS.Settings("URL").Value
Console.Writeline(reportURL)
In the 2nd line "fileMap.ExeConfigFilename = "....../AppName.exe.config" then "......" represent the full pathname to the config file and AppName is the name of your file. Now I also tried to copy the code from my original Console Application and run it but it still crashed. I think it is due to the .dlls that I am using which make calls to Stored Procedures on the database. I believe these dlls are looking for the .config file to be in the same folder since that is the way they were built. However, if you are careful when you begin writing your application you can utilize Web.config information like I did above.