How can I find in code path of my current project? - c#

How can I programmatically get the path of the current project in my C# code?
Do I have any preprocessor directives for this? Or any macros?
Note: I don't need the path of the current executing assembly, but rather a path of the project, from which this assembly was compiled.
Note (2) - What I'm trying to achieve: I have several files that are compiled as embedded resources. I load and use them in the runtime. I would like to create a "debug" mode, in which the files are loaded from their original location on disk and not from the resource stream. This would enable me to fast-edit the files for test purposes without the need to recompile the assembly.
Since the assembly is copied to a different location, outside the project from which it was compiled, in the "debug" mode I can't load the files using relative path.

You might be able to make use of the CallerFilePathAttribute.
https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callerfilepathattribute(v=vs.110).aspx

string fileName = "SampleFile.txt";
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LocalConstants.EMAIL_PATH, fileName);
C:\****\****\Documents\Visual Studio 2010\Projects\WindowsApplication1\WindowsFormsApplication1\bin\Debug\Emails\SampleFile.txt

Related

What's the preferred way to find the folder my executable is in?

I've inherited a .Net desktop app that has a folder called Data that's in the same folder as the executable. Currently, the app just opens "Data" but that breaks if the current directory is not the directory that contains the executable. I've found two ways of getting the executable's folder: Assembly.GetExecutingAssembly().Location and AppDomain.CurrentDomain.BaseDirectory. The latter is easier to use since I can just append "Data" to the string. Will AppDomain.CurrentDomain.BaseDirectory always return the executable's directory or are there situations where it might not?
Short answer
Both should be perfectly fine in 99% of cases.
Explanation
The currently executing assembly's directory is a reliable way to get the location of the current executable. Using System.IO, you could simply remove the file name from the path:
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
If the Data folder is shipped as part of a dll file that you compile, you might want to use typeof(SomeClassInMyDll).Assembly.Location instead of the executing assembly. This is to allow for a user of your DLL to have uncommon logic such as loading your assembly based on its path, which might be a different location than the currently executing assembly.
The AppDomain.BaseDirectory property is the location where the currently running code looks for DLL files when it needs to load a dependency. This is generally the same location as the currently executing assembly's path, however, if whoever is calling your code is loading your DLL in a separate AppDomain, again loading it from a file name explicitly, the BaseDirectory might be different from the folder that contains your DLL or executable.
To give an example of that uncommon scenario, let's say there is an executable C:\foo\bar.exe, which dynamically loads a DLL from a different path. This would be done by calling the method Assembly.LoadFrom("C:\MyFolder\MyDll.dll"). In that case, the following would be returned:
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) = C:\foo\
AppDomain.BaseDirectory = C:\foo\
Path.GetDirectoryName(typeof(SomeClassInMyDll).Assembly.Location) = C:\MyFolder\
Maybe this?
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
There isn't any preferred way, but the most widely used way is this.
System.Reflection.Assembly.GetEntryAssembly().Location;

Relative Paths of File.Open() in a DLL

I'm working on a SolidWorks plugin (DLL). It depends on a couple of files (sqlite DB, sketches etc). To install the plugin, you only have to open the DLL with SolidWorks.
In the DLL are some routines that call File.Open() on a number of resource files that I'll refer to by relative paths. The dir. hierarchy would look like:
Plugin/
plugin.dll
Sketches/
various.sldprt
otherfile.db
otherdeps.txt
...
Where the root dir. of the plugin can be anywhere on the system. The plugin can be easily loaded by SolidWorks with Open File Dialog. The problem is that once I load the DLL, any calls to File.Open() (eg File.Open("Sketches/various.sldprt")) with relative paths won't work because it'll be relative to the dir. where SLDWORKS.exe (SW install dir.) resides instead of the dir. of the DLL. This would mean I'll have to put all my resource files in the SolidWorks install dir., which I would like to avoid. Is that possible?
What you can do is add your addin folder as a prefix to any local path before calling File.Open().
Addin folder can be obtained as :
string path = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );

How do I load a file in a Visual Studio solution/assembly programmatically?

I have a console app that should, when given a particular command-line argument, write a skeleton configuration file for my app to a specified directory. Currently, that skeleton config file now lives in my assembly (under a t4 template that I use to generate it at compile time).
When my app is run with the relevant argument, I want to be able to load the results of my t4-processed config file into memory at run time and then write it to an arbitrary location on disk.
I can't figure out how to reference and load the file in my solution in my C# code. Is it even possible to embed a file resource like this into an assembly and reference it from code? Or do I need to put the file on the filesystem as part of an install process? I'd rather not have to do the latter if possible.
Any help or advice would be most appreciated. :)
Oops. Figured it out, after making some inferences based on this stackoverflow question: "How to embed a text file in a .NET assembly?"
The trick is to set the file's Build Action property to "Embedded resource." (Note that you're setting this for the result of the t4 template generation, not the the template itself.)
Then it will be embedded in your assembly and you can reference it in code.
var assembly = Assembly.GetExecutingAssembly();
string configFileContents;
using(StreamReader reader = new StreamReader(assembly.GetManifestResourceStream("MySolutionNamespace.ContainingFolder.SiteConfiguration.json"), Encoding.Unicode))
{
configFileContents = reader.ReadToEnd();
}
Console.WriteLine(configFileContents);
Console.ReadKey();

open file from folder in visual studio 2012

I had a folder on my desktop with files in it. I copied that into the folder of my solution and in the solution explorer I referenced that folder into the solution. However, Im not able to open files in that folder with a relative path.
The relative path from the cs-file would be "../FolderIAdded/blabla" as seen in the solution explorer. But in the windows explorer, the path is differen of course:
Solutionfolder
- SolutionFolder.sln
- Solutionfolder.v11.suo
- SolutionFolder
-- bin
-- obj
-- Properties
-- TheFolderIAdded
-- App.config
-- Form1.cs
-- etc.
Here, it would be "FolderIAdded/blabla"
Where do I have to put that folder?
My goal: I want to be able to open files from that folder in my c#-code with a relative path.
You're assuming that your program runs in the directory where your source code is located. That's not the case. Depending on your configuration, your program will execute from a directory inside Solutionfolder\bin.
One possible solution is to copy the file(s) to the output directory when you build your project.
Another alternative is to embed the files into your application's assembly at compile time, although this precludes editing of them after deployment. To do that, set Build Action to 'Embedded Resource', then you can access them using the GetManifestResourceStream method of the Assembly class. The filename you need to give it will be derived from the path within the project structure, so in your example it would be "TheFolderIAdded.Filename.ext".
Yes, that's a dot, not a backslash.
Assuming the files are embedded in the same assembly the code that wants to read them is in, the code will look something like
var assembly = Assembly.GetExecutingAssembly();
using (var stream =
assembly.GetManifestResourceStream("TheFolderIAdded.Filename.ext"))
using (var reader = new StreamReader(stream)) {
string fileContents = reader.ReadToEnd();
}
I don't think it's a good idea to write relative path from .cs file. Better build the path base on where the application is executed:
One example, there are plenty other on the web: How can I get the application's path in a .NET console application?
(Your application is not running in the solution's root folder but where the .exe file is locatated. For example when you debug a desktop application, it runs typically from [solution folder]/bin/debug/ )
Then make sure the file you want to open property Copy to Output Directory is set to Copy Always or Copy if newer. (Right click on the file in your Solution Explorer and click on "Properties" to be sure to access it.)

CSE.exe assembly search while compiling

I am using a batch file with the following commands to successfully compile a C# code on the fly, run the resulting exe and destry the exe.
start /wait C:\WINDOWS\Microsoft.NET\Framework\v3.5\csc.exe /out:PostillionOutgoing.exe PostillionOutgoing.cs /reference:AlexPilotti.FTPS.Client.dll
call SetupCI.bat
start /wait PostillionOutgoing.exe
del PostillionOutgoing.exe
It works exactly the way I wanted. File AlexPilotti.FTPS.Client.dll is present in the same folder as the .cs files are.
The assembly AlexPilotti.FTPS.Client.dll is also needed by a lot of other similar applications. My question is that is there any centralised place where I can keep this DLL so that all the above batch scripts will find it ? By this way I wont have to keep a copy of this DLL in all the separate folders.
I dont want to place the DLL in GAC. I tried in system32 folder also but it didnt work.
You can use the /lib command line to specify search folders for references
see msdn docs here http://msdn.microsoft.com/en-us/library/vstudio/s5bac5fx.aspx
As per the documentation, there is no fixed location that the runtime uses when probing for assemblies (i.e. when it looks into directories because it hasn't been able to locate the assembly already).
However, if your assembly is strongly named then you can use a <codeBase> configuration element in your app.config to direct the runtime to any path of your choosing.
If your assembly isn't strongly named and you don't want to use app.config then unfortunately you are out of options.

Categories

Resources