FileNotFoundException on resource when executing from outside path - c#

The problem we are experiencing was noticed in msbuild. We have an executable in a task that is throwing a FileNotFoundException. This LoadData.exe uses NHibernate to initialize data, so there is an NHibernate.config file in the root of the project.
The properties on the config are set to Content/Copy Always. I can confirm that, on build, this config file is copied to the output directory.
In a console window, you can launch this executable from within the bin/debug directory, and it will work without an error. From outside of this directory, you get a FileNotFoundException on the config file.
The error indicates that the NHibernate.config is being loaded relative to where we are executing MSBUILD in the BUILD directory, and not the LoadData.exe directory. Why is that? Can't we make it absolute to the exe?
Is there a BuildAction setting for this?

Change your code to load the file from the location of your assembly.

Related

How to deploy a C# (ClickOnce?) project that is a wrapper on a command line .exe

I have a C# project which is basically a GUI used to call other executable(s) with command line arguments. (The command line exe was actually built with cygwin and uses the cugwin DLL).
So the directory structure that needs to exist once the app is deployed (via setup.exe or whatever) is this:
install dir ---> MyApp.exe
MyApp.config
(dir) bin ---> cmd1.exe
cmd2.exe
cygwin.dll
Now this ought to be simple, but whatever I try, I cannot get the bin directory and its contents to be copied when I install on a second machine with setup.exe. I tried:
- adding them as resources
- setting "Build Action" to Content
- setting "Copy To Output Directory" to Always
But the bin directory was never copied across when I did this. I have tried searching here and elsewhere but I am still at a loss.
Should this be a "ClickOnce" project? (what does this even mean - are there also ClickTwice and ClickUntilYouCanClickNoMore projects - ok, excuse me ...)
Also do I get setup.exe to put this app somewhere sane like C://Program Files/MyOrg/Myapp - instead of being buried somewhere in the user's profile?
(Using VS 2019.)
Since I cannot add an image in a comment, I am adding them here. Here is how my folder structure looks like.
I have a .p12 file and have marked it as "Copy to Output Directory" to "Copy always"
When the project is built, the file gets copied inside bin folder with the file's folder structure which includes "keystore" folder as well.
As a curiosity, I just tried out renaming my folder "keystore" to "bin" (I had to delete existing bin folder), and then added the .p12 file to it. The project compiled, generated new exe file and also copied .p12 file with appropriate folder structure. I am not sure what means to building and generating a Setup.exe though. You can try and let us know if it worked for you.
To package the specified file into ClickOnce, you just need to add it to Application Files....
The following is the folder structure.
And then confirm it has been added into Application Files....
Last step, publish it. And you can access the image like this.
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + #"/img/a.jpg");
}
As to put this app somewhere sane, I am afraid the answer is no.
ClickOnce's installation path cannot be changed. You can find it at C:\Users\username\AppData\Local\Apps\2.0.

Finding a specific file path when two files have the same name in different locations in C#

I'm trying to load and save an xml file called Modules.xml in my code. I have currently got the file path hardcoded as shown below. I am trying to get the file path within my code without it being hardcoded.
I have tried using Path.GetDirectoryName and new FileInfo("Modules.xml").Directory.FullName. However, both of these target the file in my debug folder, when the file I need is in the main solution folder.
Is there a way to target the file in my main solution folder instead of my debug folder? (both files are called Modules.xml)
doc.Save("C:\\Users\\Matthew\\Desktop\\Year4\\Object Oriented\\Project1\\Project1\\Modules.xml");
Both file locations are shown below:
C:\Users\Matthew\Desktop\Year4\Object Oriented\Project1\Project1\Modules.xml
^^^this is the file path I need for my code^^^
C:\Users\Matthew\Desktop\Year4\Object Oriented\Project1\Project1\bin\Debug\Modules.xml
The best approach here would be to use a configuration file, e.g. app.config, for storing such a string. Then you can change file path without recompiling the code, and your file can be stored in any location accessible by application.
If you really want to access your file the way you explained, AppDomain.CurrentDomain.BaseDirectory will provide you with the bin/Debug location in runtime. Then you can find a relative path from there like:
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"..\..\", fileName);
where fileName is "Modules.xml" for example.
I have tried using Path.GetDirectoryName and new
FileInfo("Modules.xml").Directory.FullName. However, both of these
target the file in my debug folder, when the file I need is in the
main solution folder.
That's because bin\Debug is your working directory when you start and run the project. To change that, you can set the working directory environment variable to point to your solution directory (instead of bin\debug|release) which I wouldn't recommend that. Because when you finally endup with development, and release the application, there wouldn't be any solution directory that holds your XML file. What I can suggest is to copy your XML file to the output folder. Either you are in development (debug) or production (release) mode, the XML always going to be copied to final directory. And you can access the working directory with something like AppDomain.CurrentDomain.BaseDirectory. To enabling copy XML to output directory, right-click on it, choose Properties, set Build Action to None, and set Copy to Output Directory to Copy Always or Copy if newer. You're good to go now.

ReadAllLines() local directory not working

For some reason the ReadAllLines() looks in the wrong folder.
string[] LoadLines = File.ReadAllLines(#"Assets\\UserFile.txt");
The "Assets\UserFile.txt" is located where the exe file is.
The Debugger throws a System.IO.DirectoryNotFoundException with a comment:
"Could not find a part of the path C:\WINDOWS\SysWOW64\Assets\UserFile.txt"
Why is it checking in the wrong folder?
Try this...
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), #"Assets\UserFile.txt");
string[] lines= File.ReadAllLines(path);
Note: This will look in the folder you are executing from so make sure the folder/file exists in there.
If the executing folder is your bin folder, ensure that the file property is set to "Content" and "Always copy" or "Copy when newer" within Visual Studio.
Relative path names are resolved relative to the working directory of the process, not relative to the executable. So presumably your process has a working directory of c:\Windows\SysWOW64.
If your code needs to load assets that are effectively bundled with the application, I'd use embedded resources as a way of not having to worry about physical file paths.

Where to place external DLL in C#?

If I reference an external unmanaged DLL in C# by the following:
[DLLImport("MyDLL.dll", ...
Where should the DLL be placed when I want to run the code from my IDE? Should it be in the bin\Debug folder?
Which compiling configuration you are using?
If you want to run the application from Visual Studio Debug/Run it would be in your project folder
If you want to run by double click, it should be near your exe which is in
bin\Debug
or
bin\Release
folder.
Anywhere locatable by the LoadLibrary function. See Dynamic-Link Library Search Order for more information:
If SafeDllSearchMode is enabled, the search order is as follows:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
bin\Debug satisfies the first point, assuming that you're only ever running the application in its Debug configuration.
Yes, alongside the .exe file produced by the compiler (which ends up in bin\Debug\ as you said) should be perfect.

c#: config file in bin\debug folder

I kept getting errors in my log file that messageconfig file not found. It turned out that my application was expecting it in the bin\debug folder. What causes the application to expect so? It seems that when project is built it should copy the config file in bin\debug folder. Am i missing a certain project setting?
App/web.Config files are expected to be in the same directory as the application/web root.
Other, referenced config files may be in other directories, as specified in the main configuration file.
If you right click on the .config file, then on properties there is a Copy to Ouput Directory entry.
This should be set to either Copy if Newer or Copy always, if this is set to Do not copy, the .config will not by copied to the debug/release folder where it is expected.
Config files are expected to be in the same location as the executing assembly.
Check out this SO question:
.NET 2.0 Application Settings (user.config) file location
You could set the files build action to "Copy always"..
usually you only need the .exe. Try to clean and rebuild your project..
Hope it helps

Categories

Resources