Issue in file access with absolute paths - c#

I've created a .NetCore console application in which am trying to check if a file exists using its absolute path, but am facing issues, I always get a false response even though the file exists. Even though I pass absolute path as parameter to API, it always prefixes the current working directory, so the path gets evaluated as doesn't exists.
I'm running this code on a windows 10 desktop and the application is created using .NetCore 2.1. I've tried various different methods to evaluate the existence of file like FileInfo Class instance and File.Exists static method. They've failed so far. I've diagnosed the issue, but I couldn't find a way to fix it.
using System;
using System.IO;
namespace FileAccess
{
class Program
{
static void Main(string[] args)
{
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Console.WriteLine($"Full Name: {fileInfo.FullName}");
Console.WriteLine($"FileInfo.Exists: {fileInfo.Exists}");
Console.Write($"File.Exists with #: {File.Exists(#"‪D:\ScriptData\test.zip")}")
Console.ReadLine();
}
}
}
The output of the code is:
Full Name: D:\Work\Samples\FileAccess\FileAccess\bin\Debug\netcoreapp2.1\?D:\ScriptData\test.zip
False
False
Even though am passing the absolute path, it prefixes the current working directory to the path I've passed. I've checked the Access to the file, its all fine, still I get false as response for both the cases.
Screenshot of Error
Screenshot of Debug Info

Judging your screen shot and the output, there is an invisible character at the start of the file path. That will cause .NET not to recognize it is an absolute path and automatically it will make it an absolute path itself.
If you use this code, you will notice that the inserted ? causes the problem here:
System.IO.FileInfo fi = new System.IO.FileInfo(#"?D:\some_file.ext");
Which outputs: C:\Users\...\ConsoleApp8\bin\Debug\netcoreapp2.2\?D:\some_file.ext.
Instead of:
System.IO.FileInfo fi = new System.IO.FileInfo(#"D:\some_file.ext");
Which outputs: D:\some_file.ext.
If you put your code in a HEX editor, you will see there is indeed a character before D:.

Thank goodness you cut and paste your original code! I know you did because when I cut and paste your code I can see that you have invisible characters after the open quote and before the D:\.
These two lines look identical but they're not! Cut and paste them if you don't believe me!
Your code:
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Fixed code:
FileInfo fileInfo = new FileInfo(#"D:\ScriptData\test.zip");
Here's what the binary editor shows.
You've got E2 80 AA secretly stuck in your source code file at the beginning of your filename. Which happens to be the UTF-8 representation of the LEFT-TO-RIGHT EMBEDDING character.

Related

How do I create this directory using this function? I keep getting an access denied error.(C#)

First, let me begin by saying I know this appears to be a commonly asked question, but trust me, I've searched extensively and I couldn't find the answer to my question specifically. IF you do happen to know where this specific question was asked, by all means, mark it as a duplicate and reference me there, and accept my apologies for not finding it.
Now, I have a simple if function in my code:
if (!Directory.Exists(FileDirectory))
{
Directory.CreateDirectory(FileDirectory);
}
However, upon running this if Function, I get this error code:
System.UnauthorizedAccessException: 'Access to the path 'C:\Program Files\LockingProgram\Password.txt;' is denied.'
Now, obviously the problem is that the access is denied. How would I gain access?
I have tried simply writing the file instantly, however then it won't find the path
File.WriteAllText(FileDirectory, Password);
throws this error:
System.IO.DirectoryNotFoundException: 'Could not find a part of the path 'C:\Program Files\LockingProgram\Password.txt;'
The FileDirectory string is:
string FileDirectory = "C:\\Program Files\\LockingProgram\\Password.txt;";
Currently, what the program is trying to do is get a password from the user when they click a button, and then saves that password to a txt file located at the file directory for future reference. When they open the program, it checks if the file exists. If it exists, it sets the password to that file, and if it doesn't it forces the user to enter a string into a text box and from there, I am trying to save it. However, that's where I'm having the problem.
Any help would be greatly appreciated!
Edit: I now understand it's generally a bad idea to save it to Program Files, and you should use AppData instead. I'll try that and update you if it works that time.
Edit 2: It now works. I changed the file directory to:
string FileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "LockingApp";
And I added a new variable:
string FileName = "Password.txt";
And I modified where the directory is created to:
if (!Directory.Exists(FileDirectory))
{
Directory.CreateDirectory(FileDirectory);
}
File.WriteAllText(Path.Combine(FileDirectory, FileName), Password);
Thanks for your help guys! Hopefully I formatted this question well.
C:\\Program Files\\LockingProgram\\Password.txt;
is not a directory, use
FileDirectory = #"C:\Program Files\LockingProgram";
Directory.CreateDirectory(FileDirectory);
Also there is a probably a good chance you will need to run your program at an elevated privilege or with the appropriate permissions, i.e as an administrator
However there are better places to store data
Where Should I Store my Data and Configuration Files if I Target Multiple OS Versions?
ie AppData, for example
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
You can use Isolated Storage for saving files (Seems the easiest and least tasking to use).
Check this code sample below
using System;
using System.IO;
using System.IO.IsolatedStorage;
public class CreatingFilesDirectories
{
public static void Main()
{
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
{
isoStore.CreateDirectory("TopLevelDirectory");
isoStore.CreateDirectory("TopLevelDirectory/SecondLevel");
isoStore.CreateDirectory("AnotherTopLevelDirectory/InsideDirectory");
Console.WriteLine("Created directories.");
isoStore.CreateFile("InTheRoot.txt");
Console.WriteLine("Created a new file in the root.");
isoStore.CreateFile("AnotherTopLevelDirectory/InsideDirectory/HereIAm.txt");
Console.WriteLine("Created a new file in the InsideDirectory.");
}
}
}

How is my app finding an old version of an ancillary text file?

I have code that reads encrypted credentials from a text file. I updated that text file to include a connection string. Everything else is read and decrypted fine, but not the connection string (naturally, I updated my code accordingly, too).
So I got to wondering: is it reading the correct file. The answer: No! The file in \bin\debug is dated 6/5/2012 9:41 am, but this code:
using (StreamReader reader = File.OpenText("Credentials.txt")) {
string line = null;
MessageBox.Show(File.GetCreationTime("Credentials.txt").ToString());
...shows 6/4/2012 2:00:44 pm
So I searched my hard drive for all instances of "Credentials.txt" to see where it was reading the file from. It only found one instance, the one with today's date in \bin\debug.
???
Note: Credentials.txt is not a part of my solution; should it be? (IOW, I simply copied it into \bin\debug, I didn't perform an "Add | Existing Item")
Provided you don't change the current directory, the file in bin\Debug is going to be the one being read, as you're not specifying a full path.
The problem is likely due to the differences between the different File dates. The Creation Date (which is what you are fetching and displaying as 6/4 # 2:00:44pm) is likely different from the Date modified (which is what is shown by default in Windows Explorer). This date can be fetched using File.GetLastWriteTime instead of GetCreationTime.
That being said, I would recommend using the full path to the file, and not assuming that the current directory is the same as the executable path. Specifying the full path (which can be determined based on the executable path) will be safer, and less likely to cause problems later. This can be done via:
var exePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var file = System.IO.Path.Combine(exePath, "Credentials.txt");
using (StreamReader reader = File.OpenText(file)) { // ...

C# How to grep the last word from a directory path?

I have a program that "greps" out various directory paths from a log text file and prints various results according to the word.
Examples of Directory paths:
C:/Documents and Settings/All Users/Desktop/AccessData FTK Imager.lnk
C:/Documents and Settings/All Users/Start Menu/Programs/AccessData
C:/Documents and Settings/Administrator/Desktop/AccessData FTK Imager.exe:Zone.Identifier
Therefore how can I grep out the file or folder name after the last "/"? This is to help the program to identify between files and folder. Please do take note of the multiple "." and white spaces found within a directory paths. etc "Imager.exe:Zone.Identifier". Therefore it is difficult to use if(!name.contains()".")
Etc. How to get the "AccessData FTK Imager.lnk" or "AccessData" or "AccessData FTK Imager.exe:Zone.Identifier" from the path STRING?!
May someone please advise on the methods or codes to solve this problem? Thanks!
The codes:
if (!token[7].Contains("."))
{
Console.WriteLine("The path is a folder?");
Console.WriteLine(token[7]);
Console.WriteLine(actions);
MacActions(actions);
x = 1;
}
Use the Path class when working with file paths, and use the File and Directory class when working with actual files and folders.
string str1=#"C:/Documents and Settings/All Users/Desktop/AccessData FTK Imager.lnk";
string str2=#"C:/Documents and Settings/All Users/Start Menu/Programs/AccessData";
string str3=#"C:/Documents and Settings/Administrator/Desktop/AccessData FTK Imager.exe:Zone.Identifier";
Console.WriteLine(Path.GetFileName(str1));
Console.WriteLine(Path.GetFileName(str2));
Console.WriteLine(Path.GetFileName(str3));
outputs:
AccessData FTK Imager.lnk
AccessData
Zone.Identifier <-- it chokes here because of the :
This class operates on strings, as I do not have those particular files and/or folders on my system. Also it's impossible to determine whether AccessData is meant to be a folder or a file without an extension.
I could use some common sense and declare everything with an extension to be a file (Path.GetFileExtension can be used here) and everything else to be a folder.
Or I could just check it the string in question is indeed a file or a folder on my machine using (File.Exists and Directory.Exists respectively).
if (File.Exists(str2))
Console.WriteLine("It's a file");
else if (Directory.Exists(str2))
Console.WriteLine("It's a folder");
else
Console.WriteLine("It's not a real file or folder");
Use Path.GetFileName.
The characters after the last directory character in path. If the last character of path is a directory or volume separator character, this method returns String.Empty.
This is to help the program to identify between files and folder
There is no way to determine is a path represents a file or folder, unless you access the actual file system. A directory name like 'Foo.exe' would be perfectly valid, and a file with no extension ('Foobar') would be valid too.
how about tokenized it with "/" like what you're doing ... and then you'll know that the last token is the file, and whatever before it is the path.
You can simply split the whole string by /
e.g.:
string a="C:/Documents and Settings/All Users/Desktop/AccessData FTK Imager.lnk";
string[] words=a.split('/');
int len=words.length;
so now words[len] returns the data after last slash(/)..
I hope you understand...
I guess you only have a string that represents the name of the file, if that is the case you can't really be sure. It's totally ok to have a folder namen something like Folder.doc. So if you don't have access to the actual file system it is hard to check. You can get close though using regular expression like:
(.*\\)(.+)(\..*)
Try it on: http://www.regexplanet.com/simple/index.html
If you get any output in group number 3 it's likely that it is a file and not a folder. If you don't get some output try this direct after:
(.*\\)(.+)(\..*)?
That will give you the folder in group 2.

File.Copy and WPF

I have a little problem with the File.Copy method in WPF, my code is very simple and I get an exception when I run it,
Could not find a part of the path 'Images\37c31987-52ee-4804-8601-a7b9b4d439fd.png'.
where Images is a relative folder.
Here is my code, as I said simple and the same code works fine in a console application, no problem at all.
string filenamae = System.IO.Path.Combine(images, Guid.NewGuid().ToString() + System.IO.Path.GetExtension(imageFile)); ;
System.IO.File.Copy(imageFile, filenamae);
this.ImageLocation = string.Empty;
So if any can help, thanks.
Does the images folder exist? File.Copy doesn't create it automatically.
Do you know what your current directory is? File open/save boxes can change that. So it's always safer to work with absolute paths.
Do a
Path.GetFullPath(filename)
and see where that points to. Is it the right location?
If you use the absolute instead of the relative path, does it work then?
Before you access a file, you should call System.IO.File.Exists(). It's not clear from your error description if the origin file exists or not before the copy.
If you don't specify an absolute path, your relative path with often be resolved from unexpected places, usually the current working directory of the process. Calling this method may tell you were the process is currently running:
System.IO.Directory.GetCurrentDirectory()
You should never make assumptions about the current working directory of a running process as the user could start your program from anywhere. Even if you think you always control the current working directory, you will be surprised how often you will be wrong.
Do you have a debugger? Why not insert a breakpoint and check the values used at each step?
If the file system says "cannot find file", I wouldn't bother arguing with it...
use \\ for the file path directory if it in local.. if your file exists in network path use \\\\(atfirst).. So that it look for network drive..
Thanks
It is necessary to embed all external files into the executable and change your code to work with these embedded files rather than to expect files on the disk.
To use images or whatever you need files("xml/txt/doc"), you need to set the build action of your file to Embedded Resource, and call the method with the fully qualified name of the file, where the name is assembled like this:
[RootNameSpaceOfTheProject].[NameOfFolderInTheProject].[FileNameWithExtension]
Example:
Call the method:
var b = ResourceOperations.GetResourceAsByteArray("Store.Resources.EmbeddedIcons.toolbox.png");
Now you can write the byte array to a temporary file for example and use this as an image source, or you can build an image from the byte array directly. At least, you've got your data...
and to save this files to a disk we should write a code by #Jon Skeet :
public static void CopyStream(Stream input, Stream output)
{
// Insert null checking here for production
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
then call it:
using (Stream input = assembly.GetManifestResourceStream(resourceName))
using (Stream output = File.Create(path))
{
CopyStream(input, output);
}

Why does DirectoryInfo.GetFiles() match files that don't match the mask?

Basically, I have this code:
DirectoryInfo dir = new DirectoryInfo(#"\\MYNETWORK11\ABCDEFG\ABCDEFGHIJKL\00806\");
FileInfo[] files = dir.GetFiles("200810*");
I expect it to match any files starting with 200810. However, it's matching files named
20070618_00806.bak and 20070817_00806.bak (the stars aren't in the filename, that was the only way I could include the underscore)
I tried it with dir from a command prompt, and it matches those files also. Why?
Edit:
Maybe using C: as the example was not a good thing. The directory I'm actually querying is a network share
\\MYNETWORK11\ABCDEFG\ABCDEFGHIJKL\00806\
If checking against the short name has anything to do with it, won't 20070817_00806.bak be 200708~1.bak? That doesn't match either
msdn states that
"Because this method checks against
file names with both the 8.3 file name
format and the long file name format,
a search pattern similar to "*1*.txt"
may return unexpected file names. For
example, using a search pattern of
"*1*.txt" will return
"longfilename.txt" because the
equivalent 8.3 file name format would
be "longf~1.txt"."
Could this be the cause?
Try this from the command line:
dir /x 200810*
The "/x" will make it show the short filenames, as well as the long filenames. This would let you see whether the short filename actually does start with "200810".
I can't reproduce this, either from the command line or in a test app:
c:\Users\Jon\Test>echo > 20070618_00806.bak
c:\Users\Jon\Test>echo > 2007081700806.bak
c:\Users\Jon\Test>dir 200810*
Volume in drive C is OS
Volume Serial Number is B860-7E20
Directory of c:\Users\Jon\Test
File Not Found
And the C# app:
using System;
using System.IO;
class Test
{
static void Main()
{
foreach (var file in new DirectoryInfo(".").GetFiles("200810*"))
{
Console.WriteLine(file);
}
}
}
(This doesn't print any results.)
Perhaps there's some OS setting somewhere which is making a difference... which OS are you using? (I'm on 32-bit Vista.)
GetFiles will search the long file name and the short filename...it's not somehow matching short file names is it?

Categories

Resources