So I'm trying to create an application that requires the reading of scripts in a sub-folder called "scripts". My code I'm having issues with:
string script = Console.ReadLine();
string path = Directory.GetCurrentDirectory();
string sciptpath = path + "/scripts/" + script;
This works fine on Windows. But on Linux (running using Mono Runtime) it goes to the current users home Directory...not the directory of the executable. Is this a bug? And can someone suggest a workaround?
It's not that it needs "fixing" it's that the current directory is not what you think it is. The current directory is the directory that "has focus" for relative paths. Regardless where your EXE is, your current directory can be anywhere else, or may even change during execution.
What you want is:
string path = Path.GetDirectoryName(Application.ExecutablePath);
Related
They all give the same result, the location of folder that contains the exe that is being executed. I am sure there are no good or bad methods in the .net BCL. They are all appropriate in particular circumstances. Which one is appropriate for which scenario?
var appBaseDir = AppDomain.CurrentDomain.BaseDirectory;
var currentDir = Environment.CurrentDirectory;
var dir = Directory.GetCurrentDirectory();
var path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
They all give the same result
They certainly don’t. currentDir and dir both give you the current working directory – i.e. by default the directory your executable was run from (but it can be changed during the execution).
By contrast, appBaseDir and path get the directory which contains the executing assembly’s file.
To illustrate how they differ, consider that you have an executable which sits in C:\bar\baz.exe. Now I can execute the application by entering the following chain of commands in a terminal:
$ md C:\foo
$ cd C:\foo
$ ..\bar\baz.exe
Now the current working directory is C:\foo but the application’s base directory is C:\bar. There exist analogous means of setting the working directory for other methods of launching an application (e.g. via a shortcut icon or programmatically, such as via Process.Start).
Still, the framework provides different ways of accessing this information:
Environment.CurrentDirectory quite directly conveys the meaning that the execution environment (an environment variable) is queried. Directory.GetCurrentDirectory() may actually do the same internally (I have no idea) but it encapsulates this, and rather focuses on providing the user with a logical API for querying information about directories.
AppDomain.CurrentDomain has information about the current AppDomain (roughly, the executable). Part of that information is, logically, the AppDomain’s path. By contrast, System.Reflection.Assembly gives you general information about assembles – these represent any kind of binary objects in .NET, including DLLs and EXEs. GetExecutingAssembly in particular returns the currently executed assembly. And you can get its path again by querying its Location property, which gives the physical path of an assembly file.
Consider the example above
The myTest.exe file contains the entry point and is at located at D:\myTest.exe. This exe calls via reflection a method in an assembly in F:\. This assembly contains all the find directory code.
In the command prompt I have my current directory set to C:\
Here are the results
AppDomain.CurrentDomain.BaseDirectory
D:\
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
F:\
Environment.CurrentDirectory and Directory.GetCurrentDirectory()
C:\
AppDomain.CurrentDomain.BaseDirectory will give you the directory the application is running in.
Environment.CurrentDirectory & Directory.GetCurrentDirectory can change during the execution of an application. You can see the behavior if you get the value at the start of execution, then use something like OpenFileDialog, then then get the value again. You will notice that the value will have changed to where the OpenFileDialog was pointing.
I found with .net 5 that if the application is published as a self-contained single-file EXE, all of these well-known methods to get the EXE location return an empty string:
System.Reflection.Assembly.GetExecutingAssembly().Location
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase
typeof(Program).Assembly.ManifestModule.FullyQualifiedName
However this does work to get the containing folder path:
AppDomain.CurrentDomain.BaseDirectory
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I find out what directory my console app is running in with C#?
How to get current working directory of a console that runs a program so I could resolve relative paths passed as program args?
Lets say I've put my program here: c:\tools\program.exe
But I'm invoking it from various places. Lets say I'm here: C:\Users\Me\Documents\ and I run this command program.exe --src=somefile.txt --dest=subdir\otherfile.txt
Environment.CurrentDirectory and System.Reflection.Assembly.GetExecutingAssembly().Location will return c:\tools but I would like to be able to resolve somefile.txt and subdir\oterfile.txt paths that are relative to C:\Users\Me\Documents\.
====== UPDATE ======
Thank you for your help. It seems that Environment.CurrentDirectory works as expected. It turned out that in my case the problem was caused by Xenocode's Postbuild tool (now called Spoon Virtual Application Studio) that I occasionally use to "pack" all program's files (including dlls, config, etc.) into one executable. It's very handy, but in this case the "virtualization" feature messed up my program's Environment variables. I've managed to solve that issue.
Environment.CurrentDirectory gives you the Current Working Directory
Let me show a simple example:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Startup: " + Environment.CurrentDirectory);
Environment.CurrentDirectory = #"D:\temp";
Console.WriteLine("After:" + Environment.CurrentDirectory);
}
}
Now I create two folders named D:\temp and D:\temp2
I put the executable in D:\temp
Open a command prompt and set the current working directory with cd D:\temp2
From that directory I run ..\temp\mytestapp.exe
the output is
Startup: D:\temp2
After: D:\temp
As a curiosity:
this was the documentation for Environment.CurrentDirectory in Net 1.1
Gets and sets the fully qualified path of the current directory; that
is, the directory from which this process starts.
and this is the documentation in NET 4.0
Gets or sets the fully qualified path of the current working
directory.
Use the Environment and Path classes. http://msdn.microsoft.com/en-us/library/fyy7a5kt.aspx
var fqn = Path.Combine(Environment.CurrentDirectory, "somefile.txt")
But to play with your documents you need:
var fqn = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Person),
"somefile.txt");
`fqn' is TLA for fully qualified name
Prologue - If i append PATH environment variable in windows with Installation Directory path of my application, i don't need to CD to installation directory to execute it.
Question - Would relative file path(s) in my application interpreted according to current execution path in console or according to installation directory. Strangely, in my application, the paths are being interpreted relative to current execution path, thus causing exceptions (File not found, etc).
Please help me out.
Relative paths will be interpreted relative to Environment.CurrentDirectory.
It will default to the directory where the process started in, but can be changed.
The behaviour you are encountering (relative pathes being evaluate in the context of the current working directory) is by design.
If you want to always place a file next to the currently executing assembly, this piece of code might come in handy:
public static string GetPathRelativeToExecutingAssemblyLocation(string aRelativePath)
{
return Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
aRelativePath);
}
I have done an application in c# windows application. In this i created a project with name ACHWINAPP. I have written some code to get the path that i required as follows
strFilePath = Directory.GetCurrentDirectory();
strFilePath = Directory.GetParent(strFilePath).ToString();
strFilePath = Directory.GetParent(strFilePath).ToString();
strFilePath = strFilePath + "\\ACH\\";
But when i create a setup for the project and installed in a direcotry namely some F:\ i am getting the error ACH as not found .
What i need is when user clicks on save i would like to save the file in the directory where he installed my setup file with the folder name ACH
Any Idea please..
Do you mean:
Application.StartupPath
Might not be what you want... but its the folder from which your executable is located
Link: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.startuppath.aspx
This is a relatively simple bit of code:
string currentPath = Directory.GetCurrentDirectory();
if (!Directory.Exists(Path.Combine(currentPath, "ACH")))
Directory.CreateDirectory(Path.Combine(currentPath, "ACH"));
//at this point your folder should exist
of course there can be a bunch of reasons why you can fail to create the folder, including insufficient privileges to do so. So you should also practice safe coding and catch exceptions when dealing with the file system.
It's hard to understand exactly what you want. Maybe use the answers to this question to load files next to the currently running application?
Otherwise, either trace out using Console.WriteLine() (or if you're using Visual Studio, add a Breakpoint) to find out the initial value of strFilePath. It's probably not what you expect.
Rather than 'adding' strings together, use Path.Combine(path1, path2) to create your path:
strFilePath = Path.Combine(strFilePath, "ACH");
I have an app launching an executable which is in the same folder as that app, by doing:
Process procStarter = new Process();
procStarter.StartInfo.FileName = "OtherApp.exe";
procStart.Start();
which works fine, until I used a file open or file save dialog in my app. Then it can't find OtherApp.exe.
Does that seem normal? Can I just fix it by adding the current folder to StartInfo.Filename (and how do I obtain the current folder)?
Using the file dialog probably changes the current directory of your process. To access a file in the same folder as your current executable you can use the following code:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
path = Path.Combine(path, "OtherApp.exe");
Or you could add to your code:
saveFileDialog1.RestoreDirectory = true ;
when prompting for filenames.
The issue is that you can possibly change the current working directory when doing other file operations.
You want to remember the path as the other posters have showed you, but it may be that you want to create your own ProcessStartInfo instance and use the ProcessStartInfo.WorkingDirectory property so that you can remember the correct path.
Try explicitly specifying the path to OtherApp.exe.
Your open file dialog may be changing the current directory.
If you don't specify the folder explicitly, the system will look in the "current working directory" for the process.
The current working directory (usually) starts off as the application exe directory, but can be changed by browsing to with an Open or Save dialog.
Using an explicit filepath is the right answer. Best way is to not rely on the working directory at all, but to use the filepath of the current executable as a base.
Here are some ways to do this: Application.StartupPath, Application.ExecutablePath
Code might look something like this ...
var exeName = "sample.exe";
var exePath
= Path.Combine(
Path.GetDirectoryName( Application.ExecutablePath ),
exeName);
Try System.IO.Path.Combine( System.Windows.Forms.Application.StartupPath, "myfile.exe" );
If it's not a winforms project divo's answer is best (imo, at the time of this answer)