Issue getting executable directory with .NET core? [duplicate] - c#

With asp.net core 1.0 There are lots of functionality added. But there is not way to get Bin Folder path.
Can anyone please know how we can get the bin folder path for asp.net core 1.0 application.

Alternative way (corresponds to the AppDomain.BaseDirectory):
AppContext.BaseDirectory

This works to retrieve the assembly's directory, from which we can determine the bin location.
var location = System.Reflection.Assembly.GetEntryAssembly().Location;
var directory = System.IO.Path.GetDirectoryName(location);
System.Console.WriteLine(directory);
Output
C:\MyApplication\bin\Debug\netcoreapp1.0

Well, the bin folder does exists but it is moved to artifacts folder next to the solution file. Since ASP.NET Core RC 1 compiles everything in memory, you will find empty bin folder. But if you set "Produce output on build" option to true (Right click Project file -> Properties and Build tab) then you will find the generated files in bin folder.
I don't think so there is any direct property available as to get the path of this but you can use the same solution pointed out by #Nikolay Kostov to get application path. And then using System.IO classes jump to bin folder.
Code updated to for ASP.NET Core as mentioned here.
http://www.talkingdotnet.com/get-application-wwwroot-path-aspnet-core-rc2/
public Startup(IHostingEnvironment env, IApplicationEnvironment appenv)
{
string sAppPath = env.ContentRootPath;
string sRootPath = Path.GetFullPath(Path.Combine(sAppPath, #"..\..\"));
string sBinFolderPath = #"artifacts\bin\" + appenv.ApplicationName;
string sBinPath = Path.Combine(sRootPath, sBinFolderPath);
}

You can't really get the /bin/ folder since it is not relevant to your project and the ASP.NET environment doesn't know what a /bin/ folder is.
And also there isn't exactly a /bin/ folder. You may want to read this article: http://docs.asp.net/en/latest/conceptual-overview/understanding-aspnet5-apps.html
But you can get the so called ApplicationBasePath which is the directory in which you application runs:
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
string baseDir = appEnv.ApplicationBasePath;
// Other startup code
}

AppDomain.CurrentDomain.BaseDirectory;

Related

Excel files are not being read when executing Selenium C# Scripts on Azure Releases

I have some Selenium C# tests hosted on Azure which they need to look for the pre-built excel file in project tree, stored inside bin folder, to execute some file upload validation scenarios.
When they are executed locally these scenarios pass without any problem, but when it comes to be executed on the Azure they receive the following error.
invalid argument: File not found : D:\a\r1\a_Selenium_Tests\TestApplication\bin\Debug\netcoreapp3.1\Files\SC003_CT014_ActiveEmployees.xlsx
The files do exists in the following path: ...\bin\Debug\netcoreapp3.1\Files...
And the code I use to them is:
string root = Directory.GetCurrentDirectory() + "\\Files\\" + file;
Do you know if there's a missing file configuration or building the filePath in another way?
Thanks for your help :D
Directory.GetCurrentDirection() returns the current working directory, not the folder in which the DLL file resides. The current working directory is a different thing. In your case, the current working directory is probably something like D:\a\r1\. Instead, you need to get the folder in which the test assembly resides:
var binDirectory = Path.GetDirectoryName(GetType().Assembly.Location);
// ^^^^^^^^^
var excelFilePath = Path.Combine(binDirectory, "Files", "SC003_CT014_ActiveEmployees.xlsx");
Note: Replace GetType() with typeof(ClassName) if you are executing your code from a static method, or you would like to specify a path to a different assembly than the one that is currently executing.

how to reference file by path in published c# visual studio build

I have a file path which I access like this
string[] pathDirs = { Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\")),
"config", "file.txt" };
string pathToFile = Path.Combine(pathDirs);
When I run the build from within visual studio it gets the config directory from the root directory of the project but when I publish the build and run the program from the published build I get the error
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\<user>\AppData\Local\Apps\2.0\GA3VWRPE.G83\KDK3Q6QC.VP1\sv20..tion_333839f4362dc717_0001.0000_958d209d94853f42\config\file.txt'.
I'm unsure how to access this directory and file in the published build. How would I do this?
To get the path to the executable, you can use Assembly.GetExecutingAssembly().Location, which could be incorporated into your code like:
string filePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location), "..", "..", "config", "file.txt"));
Thanks to #ManiVI for that comment.
Go to Solution Explorer and click Show All Files
Go to file.txt, right-click and select Include In Project
in Properties
Build Action: Content,
Copy To Output Directory: Copy always
Once I followed these steps the published program managed to find file.txt.

DbMigration.SqlFile difference in base directory

We are using the new DbMigration.SqlFile method in EF Migrations 6.1.2 to run a migration script in our migration. According to the documentation, the file has to be relative to the current AppDomain BaseDirectory. We have included these files in the project, and set them to copy to output directory.
Locally this all runs fine. They get output to the bin directory, and run fine.
When deploying the software to a server running IIS however, the migration fails, because it suddenly expects the files to be relative to the root. When I copy them there, the migration works.
How can I use DbMigration.SqlFile so it runs correctly both locally and on the server?
The SqlFile method uses the CurrentDomain.BaseDirectory if a relative path is given. A workaround is to map the path yourself and give an absolute path to the method. A solution would look like this:
var sqlFile = "MigrationScripts/script1.sql";
var filePath = Path.Combine(GetBasePath(), sqlFile);
SqlFile(filePath);
public static string GetBasePath()
{
if(System.Web.HttpContext.Current == null) return AppDomain.CurrentDomain.BaseDirectory;
else return Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"bin");
}
BasePath solution taken from: Why AppDomain.CurrentDomain.BaseDirectory not contains "bin" in asp.net app?
We're using it like this from within the migration: SqlFile(#"..\..\Sql\views\SomeView.sql");

Nancy Self Host and Static Content Files

Am I right in thinking that if you create a self host nancy console app and want to serve up html,javascript and css files that you have to go thru all these files (could be quite a few) and mark them all for copy to output directory.
public class HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = v => View["index.html"];
}
}
This will not be found if the index.html file is in the project folder and is not marked copy to output on it's properties.
Edit: I stand corrected, I misunderstood the question.
Yes you need to set all static content to copy, however when I setup my project's (I can't copy paste an example for you at the moment), I just add a Build Event in the project file, or I setup a Build Task for the CI / deployment.
Nope, you don't need to mark every file individually.
https://github.com/NancyFx/Nancy/wiki/Managing-static-content
You can mark an entire directory.
Alternatively, if you're using OWIN, you can use the Static Content middleware.
Something like:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var fileSystem = new FileServerOptions
{
EnableDirectoryBrowsing = false,
FileSystem = new PhysicalFileSystem("....")
};
app.UseFileServer(fileSystem);
app.UseNancy();
}
}
I had the same issue and I found a workaround that others might find useful:
Instead of copying the files to the output directory on each build, I created a directory junction in it, targeting the original static-files directories.
This allows real-time editing of the static content in Visual-Studio (without the need to rebuild in order to copy the edited files to the output directory)
e.g. (Post-build command line):
if not exist "$(TargetDir)Web" md "$(TargetDir)Web"
if not exist "$(TargetDir)Web\Content" mklink /j "$(TargetDir)Web\Content" "$(ProjectDir)Content"
if not exist "$(TargetDir)Web\Scripts" mklink /j "$(TargetDir)Web\Scripts" "$(ProjectDir)Scripts"
if not exist "$(TargetDir)Web\Fonts" mklink /j "$(TargetDir)Web\Fonts" "$(ProjectDir)Fonts"
if not exist "$(TargetDir)Web\Static" mklink /j "$(TargetDir)Web\Static" "$(ProjectDir)Web\Static"
You can use Visual studio build events and add xcopy command like this:
xcopy /E /Y "$(ProjectDir)\Views" "$(ProjectDir)\bin\$(ConfigurationName)\Views\*"
xcopy /E /Y "$(ProjectDir)\Content" "$(ProjectDir)\bin\$(ConfigurationName)\Content\*"
when project is built xcopy gets executed and files are copied in output dir, so your selfhost exe can see that files.

Application root path

I've recently been having some issues with correctly discovering application root path in c#. I want my applications to use the correct folder in following instances:
web application in debug (visual studio)
web application in release
deployed web application
console application in debug
console application in release
deployed console application
windows service (really same as console application)
Namely I need this for a logging assembly which is shared across all those types of applications. It's using log4net and it needs to correctly resolve physical path internally - inside logging assembly.
Because log4net requires either a call to BasicConfiguration.Configure to load it from web.config / app.config. Issue with this is it doesn't set up a file watcher so changes are not monitored. Solution is to have a log4net.config file separately.
Now, I don't like placing things inside bin, bin/debug or bin/release folder since it is never included in source control. Instead for things like that I have a Config folder in application root. So that you end up with ~\Application\Config\log4net.config.
In the static logger there are 2 methods:
public static string GetRootPath()
{
var debugPath = string.Empty;
#if (DEBUG)
debugPath = "..\\..\\";
#endif
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, debugPath);
}
public static void Init(string loggerName)
{
LoggerName = loggerName;
XmlConfigurator.Configure(new FileInfo(Path.Combine(GetRootPath(), "Config\\log4net.config")));
}
So you can just call Logger.Init() in Application_Start or inside Main() for console apps. This works great for console applications but not for web applications since AppDomain.CurrentDomain.BaseDirectory points to web application root and not to it's bin folder (which also has no debug or release).
Has anyone got a reliable way to resolve root path for all above requirements? So - what should GetRootPath be doing?
PS: I know I could be checking if (HttpContext.Current != null) then don't merge debug path in but there must be a more elegant way?
You could use the CodeBase property of the Assembly class to determine the path to the executing assembly:
public static string GetRootPath()
{
var debugPath = string.Empty;
#if (DEBUG)
debugPath = "..\\..\\";
#endif
return Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath), debugPath);
}
Note, for web applications and windows services the file path is in file URI scheme format. So, I use the Uri class to convert the path to standard windows path format.
Hope, this helps.

Categories