Referencing (config file) assembly location while debugging VSTO addin - c#

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).

Related

Programmatically get Folder location for assembly

Shadow copying is a feature in the .NET framework to allow assemblies used in an app domain to be updated without unloading the app domain. Very useful in web site binary updates update/release for example.
Is there a programmatic way to read the formal location assembly folder i.e. the website \bin folder instead of the shadow copy folder?
For example when GetExecutingAssembly like this:
System.Reflection.Assembly.GetExecutingAssembly().Location
It returns ShadowCopy location folder:
C:\Windows\system32\config\systemprofile\AppData\Local\assembly\dl3\4LPBW244.CR4\DZO34RQG.YAW\caa6207b
I want to obtain the the \bin folder as per my example...
4 years without a response!
And I needed a response to this exact question!
I finally found a possible answer. This is what I did when trying to obtain the Location of an assembly. The assembly file name was "IKVM.Runtime.DLL"
System.Reflection.Assembly.ReflectionOnlyLoad("IKVM.Runtime").Location
Note the the file extension had to be removed!

ClickOnce overwriting .exe.config with old version from 'obj' directory during publish

I'm working on an old ClickOnce app that's being updated for the first time in a couple of years.
As the title states, for some reason the ClickOnce publish is overwriting the generated ApplicationName.exe.config file with an out of date version located in the \obj\ subdirectory of the project.
This is causing a couple of issues:
Firstly, the hash fails on that file when trying to install the ClickOnce. My assumption is that Visual Studio is generating the .exe.config file as usual and generating a hash for the generated version, but then copying this other version over the top thus breaking the hash (there are no pre or post build events in the project).
Secondly, even if I disable hashing on that file, any changes I make to app.config don't make it to the published version as the config is overwritten by this old \obj\ version. If I delete the file from the \obj\ folder, when trying to run the ClickOnce setup it tells me it's missing the file and aborts.
I've done a text content search of the entire project directory and can't find any mention of this \obj\ file anywhere, but it has to be there because the bug is reproducible on a different PC that's pulled the project via source control.
I'm baffled because I thought that the \obj\ folder was just used for VS's local working files, and I can't understand why, how or where in the config files something like this could be set. Help!
Edit: Other stuff that's been tried:
Cleaning the project
Publishing to a fresh location in ClickOnce
Wiping the \obj\ directory (except this one config file)

C# DLL config file not present

Well, this question is a bit different from others with the slightly same title.
I add a config file to my DLL which will be used from a website and a console application.
I'm testing the DLL from my web application.
When I build the DLL I can see my MyApp.dll.config in the bin\debug folder.
Nevertheless, when I try to read the settings from the DLL this way:
var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
The file is not found.
I know it is something to do with the location where the application is being executed as Assembly.GetExecutingAssembly().Location return a path in Framework\v4.0.30319\Temporary ASP.NET Files\root\... while AppDomain.CurrentDomain.BaseDirectory return another completely different path.
So, what I'm doing wrong? There is some configuration missing to get the config file to be copied in the real location where the application is being ran?
Thank you in advance from your help!
Usually when you build a .dll and it has a config, that file lives with the dll in the same folder.
Alas, when you use your dll in another project, that project usually has it's own config, which takes precedence over the dll's one.
You could either add the dll's config to the parent's config, or try configuring what you need in code, instead of in the config.
In .NET DLLs can not have configuration files. They will simply not be used. They are created if you use the settings tab in the project properties, but they will not be read. What you need to do is merge the settings from that config file into the application's configuration (in your case, the web.config file).

How to get absolute path of another project in a solution C#

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.

system.io.filenotfoundexception when publishing

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.

Categories