How to determine whether an relative path points outside an given path - c#

I have the following scenario (C#, WinForms). I have some kind of project file which is saved in some directory. The project file contains a reference to another file. This reference is relative from the place where the project file is saved.
Sample: The project file is saved under c:\projects\project.xyz. The other file is referenced as "\someotherdir\file.abc".
This works fine, but there may be the case someone tried to manipulate that relative path to something like "..\Windows\System32\file.abc". So there's a need to check whether the relative path points outside the path where the project is saved (it's a defined requirement, that all referenced files are inside the project path).
How to detect this scenario?

You could try using the following extension method:
public static bool IsChildOf(this string path, string parentPath)
{
return Path.GetFullPath(path).StartsWith(Path.GetFullPath(parentPath),
StringComparison.InvariantCultureIgnoreCase);
}

Not very pretty but I think it should work.
if (System.IO.Path.GetFullPath(path).IndexOf(projectPath, StringComparison.CurrentCultureIgnoreCase) == -1)
{
// naughty
}
Edited to be a good global citizen.

Windows has posix symlinks: ln -s c:\windows\system32\mshtml.dll c:\projects\project.xyz\innocent.txt. When your program opens c:\projects\project.xyz\innocent.txt you get c:\windows\system32\mshtml.dll. Does System.IO.Path.GetFullPath() work here?
POSIX also supports hardlinks. A file can have zero (when deleted), one, two, ten, one hundred filenames. And all are "The Filename", none more correct or less correct than any other.
Windows supports mounting folders into folders. Again, all names are correct.
You can solve this with filesystem permissions: Create a new user for your application. Give that user permissions to your project path. Do not give that user (or Everyone, or any groups the user is a member of) privileges to anything else in any filesystem. Let Microsoft's kernel team solve your problem for you.

Related

How to get directory of an xls file C#

I need to make a program that reads the columns of an excel. But for that, I need to get the path (directory) of this excel. What prevents me from doing this, is that I didn't want to leave my local directory fixed, because if someone downloads the file on another machine, they will need to change the path.
You asked How to get directory of an xls file C#.
As others have pointed out, the file needs to be in a known location and one way to do that is to add the Excel file to your solution and mark it as Content, specifying that it should be copied to the output directory. The image below shows how to set these properties.
You also seem to be looking for a robust way to make this happen when you deploy the app for other users. For this, you will need a strategy for making an .msi or .msix that will place this file where it needs to be. But to answer your basic question the way you asked it the path in this case can be obtained in this manner. This code will get the path and open the Excel file.
// Get the path and open the Excel file
static void Main(string[] args)
{
var path =
Path.Combine(
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
"Microsoft Excel Worksheet.xlsx");
Console.WriteLine(path);
System.Diagnostics.Process.Start("explorer.exe", path);
}
I should mention that a file in the executing directory can be read but not written (without elevated permissions). If the file is user data then refer to the answer that uses an Environment variable:
var appdata = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
You have two options:
If you don't want to your excel files to be stored in your application's directory, you can simply put things in the root of your C: partition. Every windows device is gonna have the C: partition. As the user Lee Taylor has pointed out, it turns out you can have a windows device without the C: partition, although uncommon
If you don't mind having your excel files stored in your application's directory, you can get the relative path of your application's directory throughPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
There are other ways but I believe these are the simplest and easiest to do.
If you just need to dynamically get the path to a file that is in the same project directory, then the following code works for me -
string filePath = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName + "\\excel\\Prices.xlsx";
where "\excel" is the folder in my project and "\Prices.xlsx" the file in the project

File.Exist always return false

I know it's been asked a lot already, but I still can't get my code to work.
I built a little programm which lets you choose a product and asks for your information if you want to buy it. Every time the given information like name, address and so on... is saved in a single Excel file.
Now I want this file to be created if it doesn't already exists. It works to create one, and overwrite it. But if it exists, File.Exist will return a false anyway and overwrite the entire file with a new blank. It get's created to [user]\Documents folder.
My idea to check if the file already exists was this:
if (!File.Exists(#"C:\Bestellungen.xlsx"))
{
CreateNewHistory(); // Method which creates the file in correct format
}
WriteData(); // Method to write given information to correct cells
The method for creating the file is simply:
private void CreateNewHistory()
{
Excel excel = new Excel();
excel.CreateNewFile();
excel.SaveAs(#"Bestellungen.xlsx");
...
// some cells get writte here, just for format
...
excel.Close();
}
"Bestellungen" is German for "orders"... ;)
I suppose it has something to do with the way I pass the path into File.Exist but I am just clueless. I tried to copy the file into the bin\debug folder of my project. If it's there it works perfectly, but i really would like to know how i can find the file in the documents folder. I already tried put the absolute path, but it's always returning false.
If you need more information about the code let me know, I'm really new to c# or coding basically.
You're saving the file using a relative path. The file will be saved in the program's working directory. Using C:\ will never work. In fact, you can't even write to the root folder without elevated privileges. Program Files is another folder you can't (and shouldn't even try) to save into, since 1995.
Older Windows versions would just throw an exception. Some developers would try to force permissions instead of fix their bugs, so newer versions redirect inappropriate writes to eg Documents or APPDATA. I suspect you run your program from Program Files and the OS redirected the file save operation to Documents.
You should use an absolute path to save files in the correct folder. User documents go to Documents, application files go to APPDATA etc. You can get the absolute path to each of those locations with Environment.GetFolderPath, and one of the SpecialFolder values like Desktop or MyDocuments eg :
var docFolder=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath=Path.Combine(docFolder,"Bestellungen.xlsx");
excel.SaveAs(filePath);
And retrieve it the same way:
var docFolder=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath=Path.Combine(docFolder,"Bestellungen.xlsx");
if (!File.Exists(filePath))
...
The SpecialFolder enumeration explains the purpose of the various folders:
MyDocuments contains document files for the current user,
Desktop points to the current user's desktop
ApplicationData and LocalApplicatinoData contain application-specific files used by the current user, like logs and settings etc.
CommonDocuments, CommonDesktop, CommonApplicationDatacontain files used by all users on a computer
Use the Document folder to save your file.
Get the User Document Folder
String path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
Set the Filename
string file="Bestellungen.xlsx";
Finally, generate your actual path
String absolutePath = System.IO.Path.Combine(path , file);
its throw a exception due to permission issue
please change directory or give proper permission

Listing file in location

I'm a little stuck, as for this moment i don't have any code only an idea.
I was thinking to make a program in asp.net to list files within a location.
The file will probably be releases for programs and mods for gaming and stuff.
But i have searched everywhere to get files in a location. I could use system.io.fileinfo to list files in a directory.
But how to I get a Directory not in the solution but somehwere on the hard drive or even external storage server? The location i prefer not to be hard coded but selected by the user? any toughts on how a user can select a 'location' ?
In a console application, you could be doing something like this :
Ask for the path from the user with a readline.
Check if the path is correct / exists. (if not you could create it or display an error, also it could be a path with a file, you need to check if the path is to a directory or to a file)
Do the display of the files inside of the directory as intended.
We need more precisions if you want a better answer.

Get FilePath for my excel file with sheetname

I am trying to do is to get filepath for my excel file. But I am unable to do so.
File is in Document/Visual Studio 2013/Project/ProjectName/a.xlsx
string path = Path.Combine(HttpContext.Current.Server.MapPath("~/"),"a.xlsx");
string SheetName="Sheet1";
Is it wrong way to do it or is it correct way?
This is the better answer according to me.
Better to save in
C:\Users\AJ1110\Documents\Visual Studio 2013\Projects\Proj\Proj
And in
program.cs
string pathfile = #"..\..\a.xlsx";
string sheetName = "Whatever_SheetName_IS!!!";
This might solve your problem.
HttpContext.Current does not work outside of a web context.
If your project is running inside a console or windows program, it cannot work with HttpContext.Current. MapPath is meant to translate a web path to a file system path. ~/ is a .Net convention for pointing the root web path of a web application.
You should explicit what are your requirements about how to resolve the folder containing your file.
Maybe should you simply put that in some configuration file (using settings property tab of the project by example) and retrieve it from there.
Edit:
So, from your comment on this question, it looks like you have to seek the xl file in the executing folder.
There is a number of ways for achieving this, depending on your application use cases.
By example, check this question.
Since your project is not a Web one, I expect that you some sort of Output where build process generates an executable file, some assemblies etc. You can put Build action of your Excel as Content (more details here) and use this base path to retrieve it:
System.Reflection.Assembly.GetExecutingAssembly().Location
It is important to think in terms relative to your executable (or executing assembly to be more precise), since your output will have to run outside your development environment and your excel must still be accessible.
Also, getting the exact executing assembly might be tricky in some scenarios.

Change pictureBox.Image with c# = FileNotFoundException

i have a small app in C# winform. It work great but i don't understand how to change the image of a picture box in code :
i have this directory for my image :
myProjectDirectory/bin/Pics/myImage.jpg
and this code give me an FileNotFoundException :
this.imgInvader.Image = Image.FromFile("../Pics/invader2.jpg");
i don't understand because i see on stackoverflow that FromFile method begin at bin/Release. So a ../Pics/myImage.jpg should work no ?
Thx
Use the relative path of the image.
this.imgInvader.Image = Image.FromFile(#"bin\Pics\invader2.jpg");
Here give the path from the location where your code behind file is located. Suppose if your file is in root directory and if your images are in bin/Pics/ folder then the above code works. It automatically gets the path related to the location the program is running from.
Trying to reference image files that are outside the executable output directory is incredibly fragile. There are lots of ways it can go wrong (unfortunately, there's not enough context in your question for anyone to know exactly which of these ways is your specific problem).
If you must use files on disk to store your image resources, then they should be copied into the build output directory (i.e. "Release") and referenced there. Add the file to your Visual Studio project, select it, and in the properties window, set the "Build Action" value to "Content". If the file is in a folder under the project, then it will also be copied to a folder of the same name in the output directory.
If you do use files on disk, the other thing to make sure you do is find the executable's directory (e.g. via Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)) and then combine that with your expected relative path (e.g. just the file name, or the file name under whatever folder/subdirectory you gave it in the project, if you did) using the Path.Combine() method, and then using that absolute file name as the source. Otherwise, your code can be confused by changes in the current directory made elsewhere in your program (basically, don't ever rely on the current directory…global state like that is too easy to get mixed up, once you get into the habit of using it).
For example:
string exeDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string imageFileName = Path.Combine(exeDirectory, "invader2.jpg");
Now, all that said, IMHO it is probably a better idea to add your images as resources in the executable itself, and then reference them from the Properties.Resources class. Then the images are always with the executable, because they are in the same file. The code is a lot easier too, because you're just referencing properties in the Resources class that return the actual Image objects you need.
As the previous comment stated, using resources outside of your exe is not advised however you can still do this by using the Path.GetDirectoryName Method.
I am left to question why your resources are based outside of your exe, why not embed it into your resources located in properties > resources.resx and simply call it with imgInvader.Image = Properties.Resources.FileNamehere; it is a lot safer than trusting the external environment.

Categories

Resources