How to get path of a specific folder inside solution - c#

I want to get the path of a specific folder inside the solution.
Ive tried to find answers on stack overflow, but i guess my concentration is already near the end and i cant find a real usefull answer.
Here is the folder i want (KeePassFiles):
I had those 2 files on the desktop before and reading them worked. But now i have to add those files into one of the solution folder and i only want to get the path for that.
It should work for different users who download that project.
My code right now for the desktop solution is:
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var dbpath = #$"{desktopPath}\KeePassDatabase\Database.kdbx";
var keypath = #$"{desktopPath}\KeePassDatabase\Database.key";
Now it should be something like:
string solutionKPPath = Environment.GetFolderPath(path for solution);
var dbpath = #$"{solutionKPPath}\KeePassFiles\Database.kdbx";
var keypath = #$"{solutionKPPath}\KeePassFiles\Database.key";

Environment.CurrentDirectory will return the Debug directory or the Release directory depending on your run configuration. As far as I know, there is no easy way to get a specific folder or file in your solution. The best solution I could think of is using something like the following to get the solution directory:
public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = null)
{
var directory = new DirectoryInfo(
currentPath ?? Directory.GetCurrentDirectory());
while (directory != null && !directory.GetFiles("*.sln").Any())
{
directory = directory.Parent;
}
return directory;
}
And then use that path to dig into your folders and find the specific file you're looking for using something like Path.Combine(...).
In your case, don't pass any parameters to this method if you want it to retrieve the Debug/Release directory and search up from there
Edit: Note that this will actually not work for production since there will be no .sln file to find. As suggested by the comments on your question, you should configure your project to copy the necessary files into the output folder and therefore Environment.CurrentDirectory will do the trick

I think you should not get the files from the project source, you should copy them to the output during build and then get them from output location.
I would recommend to use "Copy to Output directory= Copy Allways" and than identify the "Execution Path" by use of AppDomain.CurrentDomain.BaseDirectory or Assembly.GetEntryAssembly().Location
If you using Unit Test, especially MS UnitTests it may be necessary to use `[DeploymentItem(#"\Shared\Keepassfiles\Database.kdbx")]

Related

How to retrieve the repository directory name I am in using C#?

So I am currently working using a Unity project in a specific repository. How can I get the name of this repository I am working in? That is, the name of the folder directly above the .git folder.
The way I have done it is like so:
Directory.GetCurrentDirectory().GetParentDirectory().GetParentDirectory().GetParentDirectory().GetFilename();
However, this feels like not the best way to do it since it's almost like as if I am hard coding?
What other ways can I do this?
You could probably start with a known folder like e.g. Application.dataPath which is the Assets folder and from there bubble up until you find the root
var directory = new DirectoryInfo(Application.dataPath);
while(directory.GetDirectories(".git").Length == 0)
{
directory = directory.Parent;
if(directory == null)
{
throw new DirectoryNotFoundException("We went all the way up to the system root directory and didn't find any \".git\" directory!");
}
}
var repositoryPath = directory.FullName;
var repositoryName = directory.Name;
You could pobably also start at
var directory = new DirectoryInfo(System.Environment.CurrentDirectory);
which usually should be the root path of your project, so basically already one directory higher than the Assets.
Assuming you mean the folder of your code when you run your game:
You can use AppDomain.CurrentDomain.BaseDirectory as stated in this question

How to access a file in runtime from output directory from a different project folder

We have set of Test projects under one solution in Visual Studio. I want to read a Json file which is copied to the output directory from a different project folder in runtime. It's a test project. I can get the current project directory. But not sure how to get the other assembly's directory.
Solution looks as below
Project1 -> Sample.json (this file is set to copy to output directory)
Project2
While running my test in Project2 I want to access the file in Project1 from the output directory.
I used to access files in the same project folder with code as mentioned. But not sure how to get for a different project file. Now with replace I am able to achieve it. But sure this is not the right way
var filePath = Path.Combine("Sample.json");
var fullPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filePath).Replace("Project1", "Project2");
Not sure how to get from other project. I am sure I can't use GetExecutingAssembly(), but what is the alternative. Somehow I can access it using the above dirty way of replacing the assembly name.
To get the location of another assembly, you get use a type from that assembly to get to the right Assembly instance, and thus its location:
typeof(FromOtherAssembly).Assembly.Location
First, I suggest that you could find the dll path in the solution.
Second, you can filter the json file from the path.
The next is my working code.
Please install Microsoft.Build and Microsoft.Build.Framework nugetpackages first.
string path= string.Empty;
var solutionFile =SolutionFile.Parse(#"D:\test.sln");// Your solution place.
var projectsInSolution = solutionFile.ProjectsInOrder;
foreach (var project in projectsInSolution)
{
if(project.ProjectName=="TestDLL") //your dll name
{
path = project.AbsolutePath;
DirectoryInfo di = new DirectoryInfo(string.Format(#"{0}..\..\", path));
path = di.FullName;
foreach (var item in Directory.GetFiles(path,"*.json")) // filter the josn file in the correct path
{
if(item.StartsWith("Sample"))
{
Console.WriteLine(item);// you will get the correct json file path
}
}
}
}
You can use the below code to do it in a better way
//solutionpath will take you to the root directory which has the .sln file
string solutionpath = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName);
string secondprojectname = #"SecondProjectName\bin";
string finalPath = Path.Combine(solutionpath, secondprojectname);
you can use CopyToOutputDirectory in MSBuild

Using relative paths and globbing patterns (all files in folder/subfolders) in bundleconfig.json with BundlerMinifier

I have an ASP.NET Core web project. I am trying to bundle a bunch of static .js files using the BundlerMinifier package on the bundleconfig.json file at the root of my project. The issue I have is that the .js files I want to bundle are in another project in the solution (which I'll call MainProject), so I have to use relative paths to specify them, like so:
"outputFileName": "../MainProject/bundles/libraryscripts.js",
"inputFiles": [
"../MainProject/Scripts/Libraries/Angular/**/*.js",
// more input files
],
"minify": {
"enabled": true
}
When I build my project, the bundler does not give any errors and the file libraryscripts.js is created at the specified folder. The problem is the file is empty, which I believe is due to the globbing pattern (**/*.js). When I enumerate all the files instead of using this pattern, it works fine. What makes this more complicated is that when I don't use relative paths (no ../ at the start), it seems to work fine when using the globbing pattern.
This leads me to believe it's a problem with using relative paths in conjunction with globbing patterns. Can anyone confirm this and does anyone know a way around this? I do not want to enumerate hundreds of .js files (neither elegant nor sustainable).
Note: the following is a hacky workaround that I implemented -- it is not an official solution to this problem, though it may still be helpful.
I cloned the BundlerMinifier project so I could debug how it was bundling the files specified in bundleconfig.json and see what the problem was. The issue was in Bundle.cs, in particular in the GetAbsoluteInputFiles method. This line gets the path of the folder in which bundleconfig.json is stored:
string folder = new DirectoryInfo(Path.GetDirectoryName(FileName)).FullName;
The issue is that this same folder variable is used later when trimming the start of the paths of the files that are found:
var allFiles = Directory.EnumerateFiles(searchDir, "*" + ext, SearchOption.AllDirectories).Select(f => f.Replace(folder + FileHelpers.PathSeparatorChar, ""));
Since the files were in another directory, the .Select(f => f.Replace()); part didn't remove the start of the paths of the files, which meant the comparisons later failed when being matched. Thus, no files with both ../ and a globbing pattern were found.
I came up with a hacky solution for myself, but I don't think it's robust and I will therefore not contribute to the Git project. Nonetheless, I'll put it here in case anyone else has the same issue. I created a copy of folder:
string folder = new DirectoryInfo(Path.GetDirectoryName(FileName)).FullName;
string alternateFolder = folder;
bool folderModified = false;
Then I created a copy of inputFile and checked if it starts with ../. If so, remove it and at the same time remove the last folder name from alternateFolder:
string searchDir = new FileInfo(Path.Combine(folder, relative).NormalizePath()).FullName;
string newInput = inputFile;
while (newInput.StartsWith("../"))
{
// I'm sure there's a better way to do this using some class/library.
newInput = newInput.Substring(3);
if (!folderModified)
{
int lastSlash = alternateFolder.LastIndexOf('\\');
alternateFolder = alternateFolder.Substring(0, lastSlash);
folderModified = true;
}
}
Then I use alternateFolder and newInput only in the following lines:
var allFiles = Directory.EnumerateFiles(searchDir, "*" + ext, SearchOption.AllDirectories).Select(f => f.Replace(alternateFolder + FileHelpers.PathSeparatorChar, ""));
var matches = Minimatcher.Filter(allFiles, newInput, options).Select(f => Path.Combine(alternateFolder, f));
Everywhere else still uses folder and inputFile. Also note the use of the folderModified boolean. It is important to only remove the last folder on alternateFolder once since it is in a foreach loop.

How get file from a directory using relative path?

I am pretty new in C# and I am finding some difficulties trying to retrieve a jpg file that is into a directory of my project.
I have the following situation:
I have a Solution that is named MySolution, inside this solution there are some projects including a project named PdfReport. Inside this project there is a folder named Shared and inside this folder there is an header.jpg file.
Now if I want to obtain the list of all files that are inside the Shared directory (that as explained is a directory inside my project) I can do something like this:
string[] filePaths = Directory.GetFiles(#"C:\Develop\EarlyWarning\public\Implementazione\Ver2\PdfReport\Shared\");
and this work fine but I don't want use absolute path but I'd rather use a relative path relative to the PdfReport project.
I am searching a solution to do that but, untill now, I can't found it. Can you help me to do that?
Provided your application's Executable Path is "C:\Develop\EarlyWarning\public\Implementazione\Ver2", you can access the PdfReport\Shared folder as
string exePath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
string sharedPath = Path.Combine(exePath, "PdfReport\\Shared\\");
string[] filePaths = Directory.GetFiles(sharedPath);
Try to get the current folder by using this
Server.MapPath(".");
In a non ASP.NET application but WinForms or Console or WPF application you should use
AppDomain.CurrentDomain.BaseDirectory
If you want root relative, you can do this (assuming C:\Develop\EarlyWarning is site root)
string[] filePaths = Directory.GetFiles(Server.MapPath("~/public/Implementazione/Ver2/PdfReport/Shared"));
Or if you want plain relative,
//assuming you're in the public folder
string[] filePathes = Directory.GetFiles(Server.MapPath("/Implementazione/Ver2/PdfReport/Shared"));
Root relative is usually best in my experience, in case you move the code around.
You can right click on your file header.jpg, choose Properties, and select for example the option Copy always on the property "Copy to Output Directory".
Then a method like this, in any class that belongs to project PdfReport:
public string[] ReadFiles()
{
return Directory.GetFiles("Shared");
}
will work well.
Alternatively, if you have files that never change at runtime and you want to have access to them inside the assembly you also can embed: http://support.microsoft.com/kb/319292/en-us

Open a text file with WPF

There is a text file that I have created in my project root folder. Now, I am trying to use Process.Start() method to externally launch that text file.
The problem I have got here is that the file path is incorrect and Process.Start() can't find this text file. My code is as follows:
Process.Start("Textfile.txt");
So how should I correctly reference to that text file? Can I use the relative path instead of the absolute path? Thanks.
Edit:
If I change above code to this, would it work?
string path = Assembly.GetExecutingAssembly().Location;
Process.Start(path + "/ReadMe.txt");
Windows needs to know where to find the file, so you need somehow specify that:
Either using absolute path:
Process.Start("C:\\1.txt");
Or set current directory:
Environment.CurrentDirectory = "C:\\";
Process.Start("1.txt");
Normally CurrentDirectory is set to the location of the executable.
[Edit]
If the file is in the same directory where executable is you can use the code like this:
var directory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var file = Path.Combine(directory, "1.txt");
Process.Start(file);
The way you are doing this is fine. This will find the text file that is in the same directory as your exe and it will open it with the default application (probably notepad.exe). Here are more examples of how to do this:
http://www.dotnetperls.com/process-start
However, if you want to put a path in, you have to use the full path. You can build the full path while only caring about the relative path using the method listed in this post:
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/e763ae8c-1284-43fe-9e55-4b36f8780f1c
It would look something like this:
string pathPrefix;
if(System.Diagnostics.Debugger.IsAttached())
{
pathPrefix = System.IO.Path.GetFullPath(Application.StartupPath + "\..\..\resources\");
}
else
{
pathPrefix = Application.StartupPath + "\resources\";
}
Process.Start(pathPrefix + "Textfile.txt");
This is for opening a file in a folder you add to your project called resources. If you want it in your project root, just drop off the resources folder in the above two strings and you will be good to go.
You'll need to know the current directory if you want to use a relative path.
System.Envrionment.CurrentDirectory
You could append that to your path with Path
System.IO.Path.Combine(System.Envrionment.CurrentDirectory, "Textfile.txt")
Try using Application.StartupPath path as default path may point to current directory.
This scenario has been explained on following links..
Environment.CurrentDirectory in C#.NET
http://start-coding.blogspot.com/2008/12/applicationstartuppath.html
On a windows box:
Start notepad with the file's location immediately following it. WIN
process.start("notepad C:\Full\Directory\To\File\FileName.txt");

Categories