Relative path in .NET - c#

I am running my C# application from "D:\App\program.cs". My application needs to execute a file placed in "C:\Program Files\software\abc.exe".
How can I set the relative path in my program to execute the "abc.exe"?

To answer the question how to get a path that shows the relative location of pathB from pathA. You can use the Uri class to get the relative path.
string pathA = #"C:\App\program.cs";
string pathB = #"C:\program files\software\abc.exe";
System.Uri uriA = new Uri(pathA);
System.Uri uriB = new Uri(pathB);
Uri relativeUri = uriA.MakeRelativeUri(uriB);
string relativeToA = relativeUri.ToString();
Console.WriteLine(relativeToA);
This yields "../program%20files/software/abc.exe" for the relative path.
I have changed your example from D to C though because you can't have a relative path for two locations on different drive letters, although the above code still works, just yields the absolute.
OR if the c# bit is a red herring, and as I now understand you want to run a batch file:
in batch file put:
cd c:\program files\software\
abc.exe
abc.exe will then execute from software folder and not folder of the batch file.

You shouldn't be using relative path for referring something from Program Files. I would recommend to use Environment.GetFolderPath (and Environment.SpecialFolder) to get path to Program Files and then use some config setting to get reminder path to the program.

It's not clear what you mean by "set relative path", but if you're using Process and ProcessStartInfo to run the executable, I would suggest that you use an absolute path to specify the executable, and ProcessStartInfo.WorkingDirectory to tell the process where to run (so that relative paths will be evaluated appropriately within the new process).
EDIT: If you want the batch file to run c:\Program Files\Software\abc.exe then the contents of the batch file should be just:
"c:\Program Files\Software\abc.exe"
(Note the quotes to allow for space.)
I don't see what this has got to do with relative pathnames though.

If the application is in Program Files then you can create a batch file like
"%ProgramFiles%\software\abc.exe"

Related

Console App Get Full Path for Filename in Args

So, I have a simple console app which takes one parameter: filename.
Now, when I run it like this:
program.exe "C:\Temp\list.json"
It works since I have passed a full file path.
What I want to achieve is next:
I want to CD into C:\Temp and from there I want to call a file like:
"C:\Program Files\WS\program.exe" list.json
Basically, I want to pass in only the file name and from that construct the full file path.
How is this achievable?
I tried finding out if I can get the current directory from Terminal where I am, in my case, it would be C:Temp, but I did not find any answers for that.
You can do that.
When you execute the below commands:
CD c:\TEMP
"C:\Program Files\WS\program.exe" list.json
The current directory for your program.exe would be C:\TEMP.
You can construct full path using below c# code.
//// assuming fileName contains the input file name
var fullPath = Path.Combine(Environment.CurrentDirectory, fileName);
Hope this works.
Reference: Stackoverflow Question.

How to create a folder and file inside of the folder where the app is installed? c#

I want to be able to set default folder and file creating inside of the folder where the app is installed? Because this app will be used on multiple machines so I cannot specify path like C://Users/PcName/etc.. Is there any very simple way of doing it?
What you are trying to do is not advisable; if your application is installed using recommended default methods (following Microsoft guidelines) the app will be in a directory under C:\Program Files (or where the program files folder may be redirected) and the user that runs the app will not have write access to that directory, so the directory creation will fail.
That said, you cannot use the Environment.CurrentDirectory, because it may or may not be the directory where your application's executable files reside, neither CurrentDomain.BaseDirectory, because that is not significative too (documentation says it's the directory where the loader will search for assemblies, but that may or may not be the directory of your application's executable files).
Copying from this other answer, the correct way to find the directory of your assembly is
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
Once you have the path, you can try to create the directory with System.IO.Directory.CreateDirectory() and a file with System.IO.File.WriteAllText() or its siblings, or any other standard method of creating files.
You may also want to use the newer Assembly.GetExecutingAssembly().Location property, and use Path.GetDirectoryName() on that.
This applies to both web and windows apps:
Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
You can get the path for the executable using this code (most of the time, actually it returns the current working directory)
System.Environment.CurrentDirectory
If you only specify a path that doesn't start with a drive letter then the path will be relative to where the application is running. e.g. The following program will create a folder and file in the application's local folder.
class Program
{
static void Main(string[] args)
{
var installedLocation = Directory.GetParent(Assembly.GetExecutingAssembly().Location);
var di = installedLocation.CreateSubdirectory("MyFolder");
File.WriteAllText(Path.Combine(di.FullName, "File.txt"), "This will be written to the file");
var installedPath = AppDomain.CurrentDomain.BaseDirectory;
var di2 = Directory.CreateDirectory(Path.Combine(installedPath, "MyFolder2"));
File.WriteAllText(Path.Combine(di.FullName, "File2.txt"), "This will be written to the file");
}
}

Windows service accessing invalid directory with StreamReader

I am reading a file that is located in the same directory as my executable using a StreamReader with the following method:
StreamReader reader=new StreamReader(".\\file.txt"); //NOTE: 2nd backslash is escape character in C#
When I do this in the debug environment, it reads the file fine, but when I install the service it tries to read the file in C:\Windows\System32\ as if the working directory is set to that path, but in the services properties there is no working directory option. I'm guessing it's using the working dir of sc.exe.
Is there a way I can get it to resolve to the location of the current executable using relative file paths? Because the service might be placed in different locations based on deployments.
Yes, working directory of a service is %WinDir%\System32.Also GetModuleFileName() will return incorrect result because your service is hosted by another executable (by chance placed in that directory too).
You have to find executing assembly and its location, longer to describe than to do:
string assemblyPath = Assembly.GetExecutingAssembly().Location;
Now just extract directory name and combine with file you want:
string path = Path.Combine(Path.GetDirectoryName(assemblyPath), "file.txt");

How can i find the directory from where im running my program exe file?

In my project \debug directory i have the program exe file for example:
test.exe
Now once i will run this test.exe from c:\
And in the second time i will copy the test.exe to d:\ and run it from there.
In my code i have this line:
string programFilesX86 = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86) + "\\Diagnostic Tool\\7z.dll";
Instead the program files x86 how can i get each the directory from where im running the exe file ?
One way (sure fire way also in .Net CE) is
string path = Path.GetDirectoryName(
Assembly.GetEntryAssembly().GetModules()[0].FullyQualifiedName);
or
string path = Path.GetDirectoryName(
Assembly.GetEntryAssembly().Location);
This will prevent Shortcut's from setting the applications CurrentDirectory or StartupPath which could technically be different from it's execution path (ClickOne programs for example).
You can get the running directory by doing:
Application.StartupPath
You can read more about it here
Alternatively you can try Environment.CurrentDirectory but that may not yield you the results you want because of short cuts and other ways of getting to your file.
http://msdn.microsoft.com/en-us/library/system.environment.currentdirectory.aspx
You can also do:
System.IO.Path.GetDirectoryName(Application.ExecutablePath);
Or
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);

Getting full path for Windows Service

How can I find out the folder where the windows service .exe file is installed dynamically?
Path.GetFullPath(relativePath);
returns a path based on C:\WINDOWS\system32 directory.
However, the XmlDocument.Load(string filename) method appears to be working against relative path inside the directory where the service .exe file is installed to.
Try
System.Reflection.Assembly.GetEntryAssembly().Location
Try this:
AppDomain.CurrentDomain.BaseDirectory
(Just like here: How to find windows service exe path)
Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)
This works for our windows service:
//CommandLine without the first and last two characters
//Path.GetDirectory seems to have some difficulties with these (special chars maybe?)
string cmdLine = Environment.CommandLine.Remove(Environment.CommandLine.Length - 2, 2).Remove(0, 1);
string workDir = Path.GetDirectoryName(cmdLine);
This should give you the absolute path of the executable.
Another version of the above:
string path = Assembly.GetExecutingAssembly().Location;
FileInfo fileInfo = new FileInfo(path);
string dir = fileInfo.DirectoryName;
Environment.CurrentDirectory returns current directory where program is running. In case of windows service, returns %WINDIR%/system32 path that is where executable will run rather than where executable deployed.
This should give you the path that the executable resides in:
Environment.CurrentDirectory;
If not, you could try:
Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName
A more hacky, but functional way:
Path.GetFullPath("a").TrimEnd('a')
:)

Categories