Launching an .exe from the current folder sometimes fails - c#

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)

Related

File path for project files?

I am working on a media player in C# but when I want to make my test I have a problem.
I have to create a new object song with the following path:
#"C:\Users\Jesus Antonio\Desktop\JukeboxV2.0\JukeboxV2.0\Datos\ich will.mp3"
It works but when I change the computer I have to rewrite the entire path,
My project is called JukeboxV2.0
In java I remember you can just write the path for example
#"JukeboxV2.0\JukeboxV2.0\Datos\ich will.mp3"
This will save a lot of time because I can take my project to different computers and it works, but here I don't known how to do that, anyone know?
You would do something like this to get the path "Data\ich_will.mp3" inside your application environments folder.
string fileName = "ich_will.mp3";
string path = Path.Combine(Environment.CurrentDirectory, #"Data\", fileName);
In my case it would return the following:
C:\MyProjects\Music\MusicApp\bin\Debug\Data\ich_will.mp3
I use Path.Combine and Environment.CurrentDirectory in my example. These are very useful and allows you to build a path based on the current location of your application. Path.Combine combines two or more strings to create a location, and Environment.CurrentDirectory provides you with the working directory of your application.
The working directory is not necessarily the same path as where your executable is located, but in most cases it should be, unless specified otherwise.
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"JukeboxV2.0\JukeboxV2.0\Datos\ich will.mp3")
base directory + your filename
I was facing a similar issue, I had a file on my project, and wanted to test a class which had to deal with loading files from the FS and process them some way. What I did was:
added the file test.txt to my test project
on the solution explorer hit alt-enter (file properties)
there I set BuildAction to Content and Copy to Output Directory to Copy if newer, I guess Copy always would have done it as well
then on my tests I just had to Path.Combine(Environment.CurrentDirectory, "test.txt") and that's it. Whenever the project is compiled it will copy the file (and all it's parent path, in case it was in, say, a folder) to the bin\Debug (or whatever configuration you are using) folder.
Hopes this helps someone

How to set the path of an input file in Console application?

I am facing a problem in setting the path of input ".txt" file. I am reading the contents of the file and modifying the contents. So how can I set the path so that it will work for any computer(if someone will simply paste the project and try to run it.)
I have tried following options.
1) var path = Environment.CurrentDirectory + #"\input.txt";
2) var path = "input.txt";
But I am getting a run time DirectoryNotFound exception. For
var path = #"D:\Projects\Demo Project\C#\Problem1\Problem1\input.txt" ;
It is working fine. But it will work only for this directory structure.
I need something like:- ResolveUrl("~/input.txt"); So that it will work for every case.
System.Reflection.Assembly.GetExecutingAssembly().Location
Combine that with System.IO.Path.GetDirectoryName if all you want is the directory.
if you working in a website, as the comments on question shows, you can use
HttpContext.Current.Request.PhysicalApplicationPath
You can use
System.Windows.Forms.Application.StartupPath;
to get the directory the app started in.
Just remember to add a reference to System.Windows.Forms if it's a console app.
Hope this helps.
If you need the directory where your application is:
AppDomain.CurrentDomain.BaseDirectory

How to create a folder in the application installed directory

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");

How to get a path from a directory in a C# console application?

Say I have this file structure
Soultion-> Folder1 -> FileIwant.html
So this could be something like C:\Soultion\Folder1\FilterIwant.html
Now I need to read this file into my application. I can't just hardcode it since when I give it to someone else they might put it on F: drive or something.
Or when I create a msi file the path might be completely different. So how can I say maybe take
"Folder1\FilterIwant.html"
and use that to get the folder path regardless of where they put it?
Edit
I tried Path.GetFullPath but I land up in the bin/debug directory. But my file is not in that directory. I think it is a couple directories before. Also if I make a msi file will I have bin/debug directory?
Why is a file which is used as part of your application not in the same folder as the application? It sounds to me like you should set the properties on that file to copy to the output folder when you do a build.
Doing that will make sure your file is in the bin\debug folder.
EDIT:
either that or you should be placing your files in one of the special folders, app data or my documents spring to mind.
When Visual Studio compiles your project, it will be putting the output into the bin\debug directory. Any content files that you want to reference must also be copied to those locations, in order for your app residing in that directory to be able to read that file.
You have two choices:
either you set the Copy to Output Directory property on your FilterIwant.html to Copy if newer; in that case, if the file has changed, it will be copied to the output directory, and you should be able to reference it and load it there
or
you just define a path in your app.config, something like DataPath, and set it to your folder where the file resides. From your app, you then create the full path name for that file as Path.Combine(AppSettings["DataPath"], "FilterIwant.html") - with this approach, you become totally independant of where the file really is and you don't need to move around anything. Also: this gives you the opportunity to create an admin/config utility for your users later on, so that they can pick any directory they like, and your app will find those files there.
In my console app, I started with the debug directory until i found the closest parent folder I wanted.
static void Main(string[] args)
{
Console.WriteLine("Start");
var debugDir = Environment.CurrentDirectory;
DirectoryInfo di = new DirectoryInfo(debugDir);
var searchDir = "";
while (!di.FullName.ToLower().EndsWith("Folder1"))
{
if(di.FullName.ToLower().EndsWith(":")) //if you went too far up as in "D:" then
break;
di = di.Parent;
}
Console.WriteLine(di.FullName);
}
You need the help of System.Io.Path class:
GetFullPath: Returns the absolute path for the specified path string.
Edit:
You might also need the application directory - this is where your application will be installed:
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
Path.GetFullPath
Edit
The bin/Debug path will not be present when you run your installed application (unless you specifically tell the installer to use that subdirectory, of course).
You probably want to pass the full path as a command line argument. You can then get the argument using the args parameter of the Main method. To convert a relative path to an absolute one you can use Path.GetFullPath:
using System;
using System.IO;
public class CommandLine
{
public static void Main(string[] args)
{
// The path is passed as the first argument
string fileName = arg[0];
// get absolute path
fileName = Path.GetFullPath(fileName);
// TODO: do whatever needs to done with the passed file name
}
}

Better way to get the base directory?

I have this code to load a config file and read all the values and it works fine when running the application but of course fails on team city because the appdomain's base directory is where the build script (psake) is started. I know I can change directory to the build dir before executing the tests but I thought it's better to make loading the config file work at all times regardless.
XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, cfgFile));
Is there another way to get the "BaseDirectory" that really works all times? I tried the below as well with same results:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
XDocument.Load(Path.Combine(path, cfgFile));
EDIT 1 The problem is the following. My solutions base directory is "C:\Project", all compiled files are copied to "C:\Project\build". Now in the psake build script I have the following code:
task Test -depends PrepareTests {
try {
#$old = pwd
#cd $build_dir
&$mspec $mspec_projects --teamcity
#cd $old
}
catch {
&echo "Error starting test runner"
Exit 1;
}
}
As you can see I commented out the changing of directories which makes the BaseDirectory the location of the build file / solution instead of the build directory regardless of how I try to access it. Kind of confusing if you ask me.
UPDATE I really like to know if it is possible to get the directory of the assembly regardless of what directory the application that started the app domain is located. How?
differents ways to get the base directory
AppDomain.CurrentDomain.BaseDirectory
Directory.GetCurrentDirectory() // not guaranteed to work on Mobile application
Environment.CurrentDirectory // this calls Directory.GetCurrentDirectory()
this.GetType().Assembly.Location // Assembly.location
Application.StartupPath // for windows forms apps
Application.ExecutablePath // same as Application.StartupPath
string origAssemblyLocation = Assembly.GetExecutingAssembly().CodeBase;
Per MSDN:
Assembly.CodeBase Property
Gets the location of the assembly as
specified originally
Your question is a bit unclear. I don't really know if this is what you want.
I typically use AppDomain.CurrentDomain.BaseDirectory
Alternatives
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Environment.CurrentDirectory
So it sounds/looks like you're attempting to obtain the configuration file for an assembly. The following should accomplish that task by accessing the 'Location' property of the assembly and using it to retrieve the configuration path:
static string GetConfigFileByType(Type type)
{
Configuration config =
ConfigurationManager.OpenExeConfiguration(type.Assembly.Location);
if (config.HasFile)
return config.FilePath;
throw new FileNotFoundException();
}
try this one:
Module[] modules = Assembly.GetExecutingAssembly().GetModules();
return Path.GetDirectoryName(modules[0].FullyQualifiedName);
have you tried getting the FileName of the current process' MainModule?
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
Or GetEntryAssembly()?
System.Reflection.Assembly.GetEntryAssembly().Location
I like to make my classes configurable - for example they get the folder name as a parameter in their constructor.
This makes it possible to test with different config files.
In test code we use:
TestContext.TestDeploymentDir
This is the testrun folder, where all assemblies for a test run are copied into, together with the test deployment items. We 'deploy' our unit test config files to the test run folder - this can be specified in the testrunconfig dialog in visual studio.
For our production code we pass
Assembly.GetExecutingAssembly().Location
to the constructor, which works for us.
how about:
Application.StartupPath;
string baseDirectory=Application.StartupPath.Split(Path.DirectorySeparatorChar)[0];
Application startup path will return the path where exe is kept, we will split this using "\" and get the base directory as "C:" for example,

Categories

Resources