I have an ASP.NET website in which I am loading some validation rules from an xml file. This xml file name, with no path info, is hard coded in a library. (I know that the hard coded name is not good, but let's just go with it for this example).
When I run the website, ASP.NET tries to find the xml file in the source path, where the C# file in which name is hard coded is. This is completely mind boggling to me, as I can't fathom how, at runtime, we are even considering a source path as a possibility for resolving an unqualified filename.
// the config class, in C:\temp\Project.Core\Config.cs
public static string ValidationRulesFile {
get { return m_validationRulesFile; }
} private static string m_validationRulesFile = "validation_rules.xml";
// using the file name
m_validationRules.LoadRulesFromXml( Config.ValidationRulesFile, "Call" );
Here is the exception showing the path we are looking in is the same as Config.cs:
Exception Details: System.IO.FileNotFoundException:
Could not find file 'C:\temp\Project.Core\validation_rules.xml'.
Can anyone explain this to me? I already know how you are supposed to handle paths in general in ASP.NET so please don't respond with solutions. I just really want to understand this, since it really surprised me, and It is going to bother me to no end.
UPDATE
Here is the relevant code for LoadRulesFromXml
public void LoadRulesFromXml( string in_xmlFileName, string in_type )
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load( in_xmlFileName );
...
UPDATE2
It looks like the Cassini web server gets its current directory set by VS, and indeed it is set to the path of my library project. I'm not sure exactly how VS determines which project to use for the path, but this at least explains what is happening. Thanks Joe.
If you don't supply a path, then file access will normally use the current working directory as the default. In ASP.NET this is probably your web application directory.
It's not usually a good idea to rely on the current working directory, so you can use Path.Combine to specify a different default directory, e.g. one relative to AppDomain.CurrentDomain.BaseDirectory, which is also the web application directory for an ASP.NET app.
You should add the path explicitly to the name of the file you're opening. You could also try tracing the current working directory.
When running Cassini from Visual Studio, the current directory is inherited from whatever happens to be Visual Studio's working directory: this seems to be your case.
I.e.:
public void LoadRulesFromXml( string in_xmlFileName, string in_type )
{
// To see what's going on
Debug.WriteLine("Current directory is " +
System.Environment.CurrentDirectory);
XmlDocument xmlDoc = new XmlDocument();
// Use an explicit path
xmlDoc.Load(
System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
in_xmlFileName)
);
...
At a complete guess I would say that the Method LoadRulesFromXml() is looking at the path of the Application Root URL for where the site is hosted... which is C:\temp\Project.Core\
probably by doing a Server.MapPath("~")
Can you post the code for LoadRulesFromXML or do you have that code ?
Related
I'm trying to load test our application at work and I have created a web-test (coded web-test) that works perfectly locally.
It uses a helper class to create data that's required for the application like name, email etc (which must be unique for each application).
Name is returned by a method that resides in helper class as an object of Name class which is pretty basic contains 2 props First and Last.
public static Name GetRandomName()
{
// if (!File.Exists(#"..\..\..\Apps-Load-Performance-Tests\Data Files\fNames_1.csv")) return new Name();
var allLines = File.ReadAllLines(#"..\..\..\Apps-Load-Performance-Tests\Data Files\fNames_1.csv");
var maxLength = allLines.Length;
var random = new Random();
return new Name
{
First = allLines[random.Next(maxLength)],
Last = allLines[random.Next(maxLength)]
};
}
Problem is when I run a load test via Visual Studio cloud - it throws FileNotFoundException (fNames_1.csv)
In my test settings - I have 'Enable Deployment' checked and added the .csv file and the directory that contains the .csv file... but that doesn't seem to solve the problem.
I also tried adding [DeploymentItem()] attribute but no go...
What am I doing wrong? Any help or if someone can point me to right direction - I'd highly appreciate it.
Thanks in advance!
Deployment via the options listed in the question copies files into the TestResults\{{name+datetime+etc}}\Out directory for the test run. The relative path in the question appears to be expecting the Apps-Load-Performance-Tests directory to be in the same directory as TestResults, or even closer to the root directory.
For a cloud load test the files need to be deployed to the cloud computer that runs the test and into the same directories as the other parts of the deployed test. I suggest changing the directory paths in the GetRandomName method and related code to expect the files to be in the TestResults\...\Out directory for the run. Also make sure the files are deployed to there.
I know there are many topics similar to this, but I've been unable to find a solution after looking through dozens of results.
I have a Project "Foo", and my controller is at "Foo\Controllers\Bar.cs, and in that C# file, I want to read from a file, located at "Foo\Data\Stuff.txt". It's so simple, but nothing I've tried works, mainly because things like Directory.GetCurrentDirectory() and all similar built-in functions reference the executing directory (in my case, "C:\Program Files (x86)\IIS Express").
What am I doing wrong? Or if I missed an identical question, please direct me there, this seems to small an issue to have spent so much time on. Thanks!
With command Server.MapPath("Foo\Data\Stuff.txt") you will find the phisical path where the file is stored
It sounds like you might be looking for System.Reflection.Assembly.GetExecutingAssembly().CodeBase, which allows you to find exactly where your running .exe is located; regardless of whether you're in the debugger or not.
Here's an example that uses "CodeBase" to find the path, then reads the Windows version info from the .exe:
// GetWindowsVersion: Fetch Winver info from specified file
public static string GetWindowsFileVersion()
{
String codeBaseUri =
System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
String codeBase =
new Uri(codeBaseUri).LocalPath;
System.Diagnostics.FileVersionInfo info = FileVersionInfo.GetVersionInfo(codeBase);
return info.FileVersion.ToString();
}
I am developing website using Visual Studio 2010. I am trying to save a file in a path. It works fine localhost.
But the same code is not working in IIS. It shows the following error
Exception Details: System.IO.DirectoryNotFoundException: Could not
find a part of the path 'C:\Inetpub\wwwroot\Vendor\cn.jpg'.
Could not find a part of the path 'C:\Users\shashank\Desktop\ab.csv'.
Here is the code:
protected void btnImportFile_Click(object sender, EventArgs e)
{
sArReportText = File.ReadAllText(txtFilePath.Text.Trim());
// Set the report Properties to insert Report information
SetProperties();
}
You might also be experiencing what I am: that the directory name contains some unusual characters. In my case,
Could not find a part of the path 'C:\Web\metBoot\wild iis\DigiCert© Certificate Utility for Windows_files'.
That copyright sign is the issue.
So using concepts drawn from Obtaining the short 8.3 filename from a long filename, I convert my paths to short form first, then use that to get my list of files.
StringBuilder sf = new StringBuilder(300);
int n = GetShortPathName(sourceFolder, sf, 300);
if (0 == n)
{
tk.write(Marshal.GetLastWin32Error().ToString());
continue;
}
...
IEnumerable<string> fileGroup = Directory.EnumerateFiles(sf.ToString(), ext);
Consider how you're launching VS too. Counter-intuitively I run into this problem only when I'm running VS in Administrator mode. Possibly a group policies thing.
This may be because, you are not having the specified file in web server, or you may be used an incorrect path. Specify the exact folder and filename as how it is stored in the web server. use HttpContext.Current.Request.ApplicationPath or Server.MapPath to specify the correct location where your desired file lies. And also make sure that you have given read and write permissions for this specific file and its folder.
You need to have permissions set in iis to allow files to be saved in the folder. Basically your uploaded files should be saved inside a separate folder present inside your root directory.
In order to access, create and delete files on the server, must have rights.
Like in my project I am using Impersonator class to access various files and folder from the server.
Otherwise it will throw an exception.
You could use code impersonation:
http://csharptuning.blogspot.com/2007/06/impersonation-in-c.html
http://www.codeproject.com/Articles/14358/User-Impersonation-in-NET
regardless, whomever you use as the impersonation must be able to read/write to the location that is being saved to. We use this method in applications for delete/create folders across network. Even if App_Data is best practice, it may be a business requirement to access the documents outside of that folder.
You can also set impersonation on IIS.
I also notice that your function is called btnImportFile. You may want to look into FileUpload control if you are uploading a file, which allows you to get the byte array of the file and save as needed. https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload%28v=vs.110%29.aspx. You might still need to use Server.MapPath or HttpContext.Current.Request.ApplicationPath depending on your needs.
It's usually best practice to use the App_Data folder to save files to.
Take a look here, Working with files, for a tutorial.
What is the best way to check the existence of a file using relative path.
I've used the following method but it returns false despite the fact that file is existing.
bool a = File.Exists("/images/Customswipe_a.png");
That's not a relative path. You need to leave off the first / otherwise it will be interpreted as being rooted (i.e. C:/images...)
I guess that you are running this code in asp.net application, thats why you get false.
In asp.net you should use Server.MapPath("/images/Customswipe_a.png") to get "correct" path (relative to the web application root directory). Otherwise you get path local to the webserver executable (IIS/WEBDAV/..name any other).
The relative path is relative to the current working directory. It may not be the application directory. Call GetCurrentDirectory() to check the actual path you are testing.
You just need to define what your file is relative to
Your application main assembly?
Current directory?
Application data directory?
name it...
In each of these cases I'd suggest you to convert it into an absolute path by Path.Combine method:
public static readonly string AppRoot = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
...
//calling with a '/' heading makes the path absolute so I removed it
var fullPath = Path.Combine(AppRoot, "images/Customswipe_a.png");
var exists = File.Exists(fullPath);
This way you can guarantee where you are looking for. Even the Open/Save file dialogs may change your current directory. So, calling File.Exists without full path is usually a wrong decision.
You can test this path with System.IO.DirectoryInfo:
DirectoryInfo info = new DirectoryInfo("/images/Customswipe_a.png");
string absoluteFullPath = info.FullName;
As Mike Park correctly answered this path is likely to be (i.e. C:/images...)
The relative path, is a relative to something.
In this API, it will, according to the documentation File.Exists:
Relative path information is interpreted as relative to the current
working directory.
So everything here is depends what is CurrentDirectoty at the moment of execution of this query.
Plus, your path is not valid Desktop path (I assume you pick it from some web file, or knowledge). To understand if specified path contains not valid characters use GetInvalidCharacters function.
In your specific case it would be enough to use #"\images\Customswipe_a.png".
The path is relative to the location of your binary file. In the case of a visual studio project, this would be %PROJECTDIR%/bin/(RELEASE||DEBUG)/
What I would do is put the filesystem root in a config file, and use that for your relative path.
In a WinForms application you can get the directory of the exe file with
string directory =
Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
Another solution uses Reflection
string directory =
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
As of .NET Core 3.1, this works:
Use dependency injection to include service IWebHostEnvironment
private IWebHostEnvironment Env;
public MyController (IWebHostEnvironment env){
Env = env;
}
Then use it to get path to root of app with Env.ContentRootPath
And combine it all:
var file = System.IO.Path.Combine(Env.ContentRootPath, "images", "some-file.png");
I am new to C# and I have made a simple Windows Forms Application that basically updates the persons files for a game.
They have to manually move and delete certain folders just to change version every time. I have successfully accomplished this.
However before I start giving it out I really should improve it. I know I need to change the name of the processes and remove my descriptions ETC.
I have stumbled onto an error and instead of me taking a guess I think it is best to get an opinion from a more experienced person about how to do this.
I am going to use Inno Setup to make the installer for my application, this way I can be sure it will go into their program files 32 and 64 bit. So I know this will be in program files.
So now I am wondering if I have done this the correct way or not? I was using this format to find their program files:
string programFilesFolder = Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") ?? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
However, would this work on all windows systems(XP, Vista, Win7, Win8) and is it completely accurate? I was going to use the above, and then use this:
string PATCHSELECTOR = Path.Combine(programFiles, #"PATCH SELECTOR");
if (Directory.Exists(PATCHSELECTOR))
{
string GamereliteFolder = Path.Combine(programFiles, #"GAMERELITE~1");
if (Directory.Exists(GamereliteFolder))
And then I move the files using the string method. If the file exists it is deleted before I copy the file over from PATCH SELECTOR to GAMERELITE.
Also will windows XP support using the .exe with an assembly resource embedded which is making the program need to be ran as administrator? I previously was making the assembly work through UAC however that wouldnt always work if they have UAC off or if it is XP so I thought I would try the admin assembly instead.
Can anyone possibly give me some insight, ideas or links?
For executables (not sure for websites & web application) this returns the directory where the executable lives (it's actually the base path where the framework will probe for Assemblies to load, 99% of the the that's the same thing).
System.AppDomain.CurrentDomain.BaseDirectory
This method works for any executable located in a folder which is defined in the windows PATH variable:
private string LocateEXE(String fileName)
{
string path = Environment.GetEnvironmentVariable("path");
string[] folders = path.Split(';');
foreach (var folder in folders)
{
if (File.Exists(Path.Combine(folder, fileName)))
{
return Path.Combine(folder, fileName);
}
}
return String.Empty;
}
Usage:
string pathToEXE = LocateEXE("Example.exe");
Reference:
how to find the execution path of a installed software
How can I get another application's installation path programmatically?
Couple things:
Among the already stated answers, Assembly.GetExecutingAssembly().Location will also give you the full file path of the currently "executing" Assembly. (Alternatively, GetCurrentAssembly)
If I'm reading your question correctly, you're trying to find both your own location as well as another application's. I would highly recommend seeing if the other application has a registry key that specifies the exact location - it'll make your copy step WAY more stable.