File.Exists isn't find the document but it is there - c#

So something must be wrong with my string.
I am grabbing the value from a SQL database which comes out like this:
while (reader.Read())
{
// Row Values
// 0 = UID
// 1 = CreatedDate
// 2 = Location
documentID = reader.GetGuid(0);
fileName = reader.GetSqlValue(0).ToString() + ".zip";
location = reader.GetString(2);
createdDate = reader.GetDateTime(1);
The values returned from the database are as follows:
GUID: DC5A30D7-D528-4BA4-AA5A-5ECEB2CD9006
fileName: DC5A30D7-D528-4BA4-AA5A-5ECEB2CD9006.zip
Location: \\192.168.22.1\documentation
if (!DoesFileExist(location + fileName))
{
// Log error to database
}
static bool DoesFileExist(string location)
{
bool doesExist = false;
if (File.Exists(location))
{
doesExist = true;
}
return doesExist;
}
When it gets to the part File.Exists(location) it passes over it as if it dind't exist. Bur it does... When I navigate to it in an Explorer I find the zip file just fine...
What am I doing wrong here?
UID CreatedDate Location
DC5A30D7-D528-4BA4-AA5A-5ECEB2CD9006 2009-10-28 11:17:06.690 \\192.168.22.1\documentation

As it is written in the example above, the Location + Filename doesn't produce a correct full filename. There is no backslash to separate the path from the filename.
I suggest to use the appropriate method Path.Combine from the class (System.IO.Path) to make the correct full filename
if (!DoesFileExist(Path.Combine(location, fileName)))

The way I see it, you're sending: "\192.168.22.1\documentationDC5A30D7-D528-4BA4-AA5A-5ECEB2CD9006.zip" to the method.
Try putting another "\" there.

Most of the time I have a problem like that, it is because of permissions. Often, the user for the file explorer is different that is trying to find the file with file exists. If everything is correct with the location, the next place to look would be the permissions.

Related

validating file path for directory creation

I am using Directory.CreateDirectory(string) method to create folders, now the problem is if the user enters string as:
"C:\folder1" then it creates the folder in the respective location, fine by me.
but if he writes
"C:\\\\\\\\\\\\\\\\\\\\\\\\\folder1" it is also navigating to the same path, creates folder and not giving any error, this is a problem for me.
So in order to solve the above mentioned problem I try to do some validation before on the path and I tried with Path.GetFullPath() and other Path methods and I see:
Path.GetFullPath("C:\\\\folder1") no exception or error
Path.GetFullPath("C:\\\folder1") exception or error
somehow when the count of backslashes are in even number no exception is thrown but when the count is in odd number then exception is thrown.
How can I achieve this simple thing that when user enters path like:
C:\folder 1 valid path
C:\\\\\\folder1 invalid path
Please let me know if further details are required
Possible solution using FolderBrowserDialog - Users will not manually input the path but rather select/create it via FolderBrowserDialog.
The below code will return all the files in a folder but you can amend it to return whatever information you need.
private void Form1_Load(object sender, EventArgs e)
{
//
// This event handler was created by double-clicking the window in the designer.
// It runs on the program's startup routine.
//
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
//
// The user selected a folder and pressed the OK button.
// We print the number of files found.
//
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
}
}
Code found here
If you want to get a proper path from that, maybe you can use the following technique (in addition to what you already have, of course, this is only to remove the repeated backslashes)
Split the path using the '\' character
Remove the empty values (you can filter here the non valid
characters, etc)
Reconstruct the path string using join with the character '\' again
Something like:
pathString = "C:\\\\\\folder1";
splitString = pathString.Split('\\');
nonEmpty = splitString.Where(x => !string.IsNullOrWhiteSpace(x));
reconstructed = string.Join("\\", nonEmpty.ToArray());
Test code here: https://dotnetfiddle.net/qwVqv8
What about sanitizing the path?
char[] separator = new char[] { System.IO.Path.DirectorySeparatorChar };
string inputPath = "C:\\\\\\\folder1";
string[] chunks = inputPath.Split(separator, StringSplitOptions.RemoveEmptyEntries);
string validPath = String.Join(new string(separator), chunks);

How can I fix this DirectoryNotFoundException?

I have a DirectoryNotFoundException on a .txt file if I use the full path it's working but I don't want to use the full path because I want the program work no matter where it is placed (compatibilty with the maximum of computer)
Here's my code
private void SaveClose_Click(object sender, RoutedEventArgs e)
{
if (Windowed.IsChecked == true)
windowed = true;
else
windowed = false;
string textWriteWindowed;
if (windowed == true)
{
textWriteWindowed = "-screen-fullscreen 0" + Environment.NewLine;
}
else
{
textWriteWindowed = "-screen-fullscreen 1" + Environment.NewLine;
}
var selectedResolution = ResolutionBox.SelectedItem.ToString();
var split = selectedResolution.Split('x');
widthChoose = Int32.Parse(split[0]);
heightChoose = Int32.Parse(split[1]);
string textWriteWidth;
textWriteWidth = "-screen-width " + widthChoose + Environment.NewLine;
string textWriteHeight;
textWriteHeight = "-screen-height " + heightChoose + Environment.NewLine;
File.WriteAllText(#"\Resources\arguments.txt", textWriteWindowed);
File.AppendAllText(#"\Resources\arguments.txt", textWriteWidth);
File.AppendAllText(#"\Resources\arguments.txt", textWriteHeight);
this.Close();
}
The first argument of File.WriteAllText takes a path as input. Whatever you have mentioned is not the absolute path but it is just the relative path of the file. WriteAllText creates the file but doesn't create the directory by itself. So something like:
File.WriteAllText(#"\arguments.txt", textWriteWindowed);
shall work (and create the file in the respective drive), but
File.WriteAllText(#"\Resources\arguments.txt", textWriteWindowed);
shall not work. Hence, if you want to create a file in the path where the application resides, you can do something like:
string folder=Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
File.WriteAllText(#"\arguments2.txt", "ABC");
If you want to create a directory, then you could do something like:
System.IO.FileInfo file = new System.IO.FileInfo(filePath);
file.Directory.Create();// If the directory already exists, this method does nothing.
System.IO.File.WriteAllText(file.FullName, textWriteWindowed);
Hope this answers your query.
you have to check whether the folder is exist before save the file,
if folder not exist create it using
Directory.CreateDirectory(...)
Directory.Exists(..)
you can use to check folder existence
IF you wanted to get the local path of the file you are executing use this:
var fInfo = new FileInfo(System.Reflection.Assembly.GetCallingAssembly().Location);
From there, you would do the following:
var parentDir = new DirectoryInfo(fInfo.DirectoryName);
var subDir = new DirectoryInfo(parentDir.FullName + "Resource");
if(!subDir.Exists)
subDir.Create();
This would ensure that you always have a folder in the directory of your executable. But just so you know, this is absolutely horrible code and should never ever be implemented in a production like environment. What if some knucklehead sysAdmin decides to place your program/folder in an area that the current user does not have access/writes too? The best place to write to is %APPDATA%, this will ensure the user always has read/write permissions to what you are trying to accomplish.
I don't know how but doing that worked for me :
File.WriteAllText(#"./arguments.txt", textWriteWindowed);
File.AppendAllText(#"./arguments.txt", textWriteWidth);
File.AppendAllText(#"./arguments.txt", textWriteHeight);

File.Move Not Working, No Error

I'm running into some issues trying to move flat HTML files around on a server.
In short, the process says that it should take whatever file is currently in the newpath (if there is one) and move it to the backup folder. Then take the file in the old path and move it to the new path. Then it checks to see if it was successful (i.e. does the newpath exist) and if it wasn't, it replaces the backup. I've pasted the method below for your viewing pleasure.
public bool MoveContent(string oldPath, string newPath, string backupDirectoryPath, out string backupPath)
{
backupPath = String.Empty;
var oldFilePath = HttpContext.Current.Server.MapPath(oldPath);
var newFilePath = HttpContext.Current.Server.MapPath(newPath);
var newDirectory = Path.GetDirectoryName(newFilePath);
// If the file we're moving doesn't exist, fail.
if (!File.Exists(oldFilePath))
throw new InvalidPathException(oldFilePath);
// If no destination is found, fail.
if (string.IsNullOrWhiteSpace(newDirectory))
throw new InvalidPathException(newFilePath);
if (!Directory.Exists(newDirectory))
Directory.CreateDirectory(newDirectory);
var backupPhysicalPath = String.Empty;
// If there is a file in our destination, back that one up.
if (File.Exists(newFilePath) && !String.IsNullOrWhiteSpace(backupDirectoryPath))
{
var backupFilePath = HttpContext.Current.Server.MapPath(backupDirectoryPath);
var backupDirectory = Path.GetDirectoryName(backupFilePath);
// If the backup destination doesn't exist, fail.
if(string.IsNullOrWhiteSpace(backupDirectory))
throw new InvalidPathException(backupDirectory);
if(!Directory.Exists(backupDirectory))
Directory.CreateDirectory(backupDirectory);
var fileName = Path.GetFileNameWithoutExtension(newFilePath);
var currentDateTime = DateTime.Now.ToString(FileHelpers.TempFileDateFormat);
var fileExtension = Path.GetExtension(newFilePath);
// Example Result: hardware-2015-01-30-08-35-26-475.html
backupPath = backupDirectoryPath.Replace(fileName, fileName + "-" + currentDateTime);
backupPhysicalPath = String.Format("{0}\\{1}-{2}{3}", backupDirectory, fileName, currentDateTime, fileExtension);
// If there is already a file in our backup destination, fail.
if (File.Exists(backupPhysicalPath))
throw new InvalidPathException(backupPhysicalPath);
// Backup the file that currently exists in our new destination.
File.Move(newFilePath, backupPhysicalPath);
}
// Move our file to the new destination.
File.Move(oldFilePath, newFilePath);
// Return false if the new file doesn't exist.
if (!File.Exists(newFilePath))
{
// If we made a backup, return the backup to the original loction, since there's nothing in the destination.
if (!String.IsNullOrWhiteSpace(backupPhysicalPath) && File.Exists(backupPhysicalPath))
{
File.Move(backupPhysicalPath, newFilePath);
}
throw new Exception(String.Format("Failed to move content. OldPath: '{0}'; NewPath: '{1}'; BackupPath: '{2}'", oldFilePath, newFilePath, backupPhysicalPath));
}
return true;
}
Here's an example of the parameters being passed in:
oldPath: "/client/content/en/unpublished/Anpan.html"
newPath: "/client/content/en/Anpan.html"
backupDirectoryPath: "/client/content/en/backups/Anpan.html"
The problem that I'm running into is that sometimes the backup file will be made (it will move from newpath to backuppath), but it won't move from oldpath to newpath.
I've been unable to actually reproduce the issue as it happens so infrequently and without any exceptions being thrown, but the symptoms exist (I can see the files on the filesystem when the client reports the issue) and it's been reported multiple times.
I put some logging around it and wrapped the entire method in a try/catch. It never fails unexpectedly (except when I specifically throw the InvalidPathException). There is nothing in my logs when it happens.
Can anyone help me to diagnose this issue, or tell me if I'm doing something very wrong in my method that would cause the problem?
Thanks so much!

File not relocating correctly c#

I have my program setup to rename and store a file according to checkbox input. I used another stackoverflow post for my template. Only problem is when I tried setting it up for sub-folders, it never puts it in the correct folder. I have a label folder with two sub folders called L-Labels and B-Labels. The user checks which label type it is and the file gets renamed and placed in the according sub-folder. When I used breakpoint my variables are getting the correct value so I don't see what's wrong I have provided my variables and code for relocating the file. What is causing this to not put it in my sub-folder?
Varibales:
string oldPath = lblBrowseName.Text;
string newpathB = #"C:\Users\Public\Labels\B_Labels";
string newpathL = #"C:\Users\Public\Labels\L_Labels";
Method:
if (rChkBoxBizerba.Checked == true)
{
string newFileName = rtxtBoxNewVersion.Text;
FileInfo f1 = new FileInfo(oldPath);
if (f1.Exists)
{
if (!Directory.Exists(newpathB))
{
Directory.CreateDirectory(newpathB);
}
f1.CopyTo(string.Format("{0}{1}{2}", newpathB, newFileName, f1.Extension));
if (System.IO.File.Exists(lblBrowseName.Text))
System.IO.File.Delete(lblBrowseName.Text);
}
I would say this is the problem:
f1.CopyTo(string.Format("{0}{1}{2}", newpathB, newFileName, f1.Extension));
You declare your path but it doesn't have a trailing directory separator, so when you combine all the parts, as above, the actual result is invalid.
You really should use Path.Combine() to combine parts of paths together, this uses the correct directory separator and makes additional checks.
Try something like this:
// Build actual filename
string filename = String.Format("{0}{1}",newFileName, f1.Extension));
// Now build the full path (directory + filename)
string full_path = Path.Combine(newpathB,filename);
// Copy file
f1.CopyTo(full_path);

Checking File Path When Deleting A File

If I have a web method that deletes a file when called and it accepts three parameters (cNum, year, and fileName). Do I need to be worried about exploits of this method. The only thing I could think of would be using ..\..\..\ to drive the delete further up the folder structure. that should be pretty easy to remove that. But is there anything else that I should be worried about?
[WebMethod(EnableSession = true,
Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
try
{
if (String.IsNullOrEmpty(cNum)
|| String.IsNullOrEmpty(year)
|| String.IsNullOrEmpty(fileName))
throw new Exception();
string path = Server.MapPath(#"~\docs\custFiles\"
+ year + #"\"
+ cNum + #"\" + fileName);
File.Delete(path);
}
catch
{
throw new Exception("Unable to delete file");
}
return true;
}
I would recommend using the GetFileName method on the Path class to cleanse the filename parameter, like so:
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
// Cleanse fileName.
fileName = Path.GetFileName(fileName);
The GetFileName method strips all directory information from a path, which is exactly what you want to do here.
With input like:
..\..\..\filename.ext
You would get:
filename.ext
In return, you don't have to worry about someone injecting a path which would escape the directory that you are targeting (assuming that this filename is user-input or from an open endpoint where someone could enter any input they want).
This then allows you to then append your custom path to fileName.
This only works of course if all of your files are in a pre-defined directory, which it seems it is.
This does not however, do anything to handle deleting files that a user doesn't have access to. If the files belong to another user in that directory, then there's no check here to see if that's the case (but if all users have rights to delete these files, then it's ok).
Also, you might want to use the Combine method on the Path class to combine your paths, like so:
string path = Server.MapPath(#"~\docs\custFiles\")
path = Path.Combine(path, year);
path = Path.Combine(path, cNum);
path = Path.Combine(path, fileName);
If you're using .NET 4.0 or above, you can use the overload of the Combine method that takes the parts of the path as a parameter array:
string path = Path.Combine(
Server.MapPath(#"~\docs\custFiles\"),
year, cNum, fileName);
Finally, as Shai points out, if possible (for a complete solution), to make this even more secure you should be enabling permissions on the file-system level.
If you are impersonating the user or using a constrained user account to handle all of the requests, then you should grant that user access to just the ~\docs\custFiles\ directory (and any sub directories).
Anything above that directory the user account should have no access to.
It is a good idea to check the file names and directory names if they are valid file names or not, check them against this char array:
Path.GetInvalidFileNameChars
EDIT:
And you should probably also validate the year and number like this:
bool valid = int.TryParse(num, out temp);
You may also want to consider using built in security on the file system to prevent users from deleting files in unwanted directories. If the web app is running under a specific user that has rights to delete files in only one directory, no matter what the user tries, the app will not have the rights to perform the delete.
In addition, this would make maintenance (ie: adding new directories) pretty easy without redeploying the app.
You could then catch the attempt to access the invalid access attempt and do something with it if you so desire.
[WebMethod(EnableSession = true,
Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
try
{
if (String.IsNullOrEmpty(cNum) || String.IsNullOrEmpty(year) ||
String.IsNullOrEmpty(fileName))
throw new Exception();
string path =
Server.MapPath(#"~\docs\custFiles\" + year + #"\" + cNum +
#"\" + fileName);
File.Delete(path);
}
catch (System.Security.SecurityException e)
{
throw new Exception("Unauthorized attempt to delete file");
}
catch
{
throw new Exception("Unable to delete file");
}
return true;
}

Categories

Resources