20

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?

mhenrixon
  • 6,179
  • 4
  • 40
  • 64
  • 2
    What do you mean "base directory"? Where is the config file located in relation to the assembly? Your second example should work if the config file is in the same directory as the DLL... – Dean Harding Jul 02 '10 at 05:52
  • So you want the directory where the .exe is located? – Craig Jul 02 '10 at 06:17
  • @craig - yes that's what I am after – mhenrixon Jul 02 '10 at 07:43
  • Have simply tried asking for the CodeBase off one of the types in your assembly? I.e. something like `var path = typeof(SomeClassInMyAssembly).Assembly.CodeBase;`? – Thomas Jul 23 '10 at 03:22

9 Answers9

28

differents ways to get the base directory

  1. AppDomain.CurrentDomain.BaseDirectory

  2. Directory.GetCurrentDirectory() // not guaranteed to work on Mobile application

  3. Environment.CurrentDirectory // this calls Directory.GetCurrentDirectory()

  4. this.GetType().Assembly.Location // Assembly.location

  5. Application.StartupPath // for windows forms apps

  6. Application.ExecutablePath // same as Application.StartupPath

jgauffin
  • 99,844
  • 45
  • 235
  • 372
Bamara Coulibaly
  • 729
  • 1
  • 8
  • 7
11

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
jgauffin
  • 99,844
  • 45
  • 235
  • 372
11
string origAssemblyLocation = Assembly.GetExecutingAssembly().CodeBase;

Per MSDN:

Assembly.CodeBase Property

Gets the location of the assembly as specified originally

hemp
  • 5,602
  • 29
  • 43
9

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();
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
csharptest.net
  • 62,602
  • 11
  • 71
  • 89
1

try this one:

  Module[] modules = Assembly.GetExecutingAssembly().GetModules();
  return Path.GetDirectoryName(modules[0].FullyQualifiedName);
Arseny
  • 7,251
  • 4
  • 37
  • 52
  • Thank you I did not try that one before. It still tries to find the xml file in the solution dir instead of the build dir though. – mhenrixon Jul 02 '10 at 09:10
  • you may registrate the assembly file in build directiry after copy them. – Arseny Jul 02 '10 at 09:23
1

have you tried getting the FileName of the current process' MainModule?

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

Or GetEntryAssembly()?

System.Reflection.Assembly.GetEntryAssembly().Location
andyp
  • 6,229
  • 3
  • 38
  • 55
1

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.

GarethOwen
  • 6,075
  • 5
  • 39
  • 56
  • "If the loaded file was shadow-copied, the location is that of the file after being shadow-copied." / The Location property won't give the OP what he's after in this case. – hemp Jul 24 '10 at 07:09
  • As a side note, this is best if you plan on using the desktop bridge – Alexander Oct 03 '17 at 14:53
1

how about:

Application.StartupPath;
pieter.lowie
  • 108
  • 11
0
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,