Why does
Console.WriteLine(Path.GetFullPath(#"\\folder1\folder2\..\anotherFolder"));
print \\folder1\folder2\anotherFolder and not \\folder1\anotherFolder?
While Console.WriteLine(Path.GetFullPath(#"\\folder1\folder2\folder3\..\anotherFolder")); prints \\folder1\folder2\anotherFolder as I would expect it.
It seems as if I can not escape the first two folders of my path. But every folder after the two.
Edit:
Actually it is:
Console.WriteLine(Path.GetFullPath(#"\server\share\..\anotherFolder"));
Which explains the behaviour.
When you specify a network path the first part (folder1 in your example) is the server name. The second part folder2 is the share name. You can use .. to traverse up an actual folder but not a share.
Related
I have a program that tracks changes on a local folder using a FileSystemWatcher object.
The issue is that sometimes, on some environments and situations (I do not know which ones), this watcher gives me an event on a DOS path ("/Hello/How/Are/You" becomes something like "/HE~1/HO~1/AR~1/YO~1").
What I am looking for is a way to force this path back into its full and normal aspect.
Or at least something that can tell me that the path is indeed a DOS path, so I can process the entry differently.
EDIT: it has to work on long paths (+260 chars), so Path.GetFullPath(sShortPath) does not work for me here!
Path.GetFullPath(#"/HE~1/HO~1/AR~1/YO~1") should do what you need.
The best method depends what you are looking for, if you just want to access the file once then the 8byte file names will work for internal file references
if you want to display to the user or store then there are 2 option
Path contains most of the tools you need to manipulate paths
fullPath = Path.GetFullPath(path1);
FileInfo and DirectoryInfo these 2 classes provide persistent access to files and directory information and while they can be created with any valid path both have a Full name property that provides access to the full path
As others said, Path.GetFullPath(sShortPath) works fine if not used on very long paths (+260 chars).
Here is a link I followed that worked for me.
GetLongPathName from kernel32.dll worked fine with me, I just had to change the 255 StringBuilder limit to a higher value to make it work with long paths.
I have an application that accepts user input and does stuff to files. The users select a file and it might move it, delete it, rename it, ftp it etc. The application uses a hash table to store recently used files and their paths.
The main problem I am looking into now is one of the add-ins is saving the path incorrectly, it is saving it as such: C:\David\\File.txt
The part of the application that deals with file io tries to ensure the file exists prior to doing stuff with a File.Exists(path) call. This call is returning true even for the above example. Can anyone explain why this might be?
The issue I am facing is, beyond one module saving the path incorrectly, certain modules that interact with the file are accepting that incorrect path and working fine while others see it and crash. Although currently I am going to fix this by getting the path saved correctly, I'd like to understand what is going on here.
You have a false premise: that C:\David\\File.txt is an invalid path. Multiple backslashes are accepted fine in Windows. Try notepad C:\David\\File.txt in a command prompt as an experiment--it should work.
For more info, see this other SO q/a that reaffirms this. Any number of backslashes are fine, and this can be used as a "easy" way to combine paths without worrying about the number of backslashes. For example, the user can provide C:\David or C:\David\ and you can add \test.txt without worrying which input the user provided. However, Path.Combine is the real way to do this in C#.
Edit: To remove your extra \'s easily before passing the path into the other program, try splitting the path into the drive and folder names and combining it back together into a path. Like this:
string path = Path.Combine(pathWithManyBackslashes.Split('\\'));
Because Split doesn't create new entries when the delimiter repeats, you get rid of them. For example, C:\David\\File.txt => [C:, David, File.txt].
I'm creating a program that controls if words in a textbox are present in a text file.
The question is: Is there a way to find the path of that file without depending on the computer you're on?
If you don't use an absolute value for the path - it'll always try to resolve it relative to where your application is.
So if you put the file in the same folder as your application, it'll find it.
Otherwise, if you want your user to locate the file for you, you could use an OpenFileDialogExample here
Another option is to use one of the 'known' paths (such as My Documents). You can do this using Environment.GetFolder
But all of these depend on what you're trying to do exactly.
You can use relative paths. For example, if your path is "file.txt" and save the file, it will be saved next to your exe. Same thing for opening.
We have a concret directiory (e.g. "C:\personal\app\cherry\") where while the runtime of another application a folder with 2 significant information in its name will be generated randomly.
One of those information will remain constant, everytime the folder is generated. As well the folder will be removed while runtime too, but this is not really relevant in this case.
So there would be a folder with two information split with a simple dot.
Example: \oskdfo.chips\
Where oskdfo is the randomly generated part, and chips will be the constant.
So the constant is the information we need to find this specific directory, hence the other information will never remain the same, a uncommon way to find the actual position of this directory is needed here.
So now I'm searching for a procedure to find this directory with this specific format inside a given path, where also all subdirectories should be included for the search.
You never said if the directory is created under your application path or if you want to search the entire hard drive.
Anyway you should use Directory.GetDirectories method to search for it. The return value is an array with all directories that can be found in the specified path.
You can get all folder in the app path by using the following:
var folders = Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory)
With LINQ you can narrow it down:
var folders = Directory
.GetDirectories(AppDomain.CurrentDomain.BaseDirectory)
.Where(folder => folder.Contains("usuall")
.ToList();
How can you convert a drive relative path such as D:test.xml into an absolute path that a function such as XDocument.Load() will accept. The D drive could have D:\data as its current working directory, for example, so D:test.xml would mean D:\data\test.xml . I've already tried such concoctions as D:.\test.xml .
Here is the error I get for something like D:test.xml:
Invalid URI: A Dos path must be rooted, for example, 'c:\'
You could use GetFullPath. For example:
// should return "D:\data\test.xml" if the current working dir is "D:\data"
string absolutePath = Path.GetFullPath("D:test.xml");
If the CWD is "D:\Data", Path.GetFullPath("D:test.xml") would indeed return "D:\data\test.xml", as it would getting full path directly for "test.xml".
However, if using a different drive letter than the one used for the CWD, the result will not be consistent. For example Path.GetFullPath("C:test.xml") would return "C:\test.xml".
This is by design. Take a look at http://msdn.microsoft.com/en-us/library/aa365247.aspx#fully_qualified_vs._relative_paths.
If a file name begins with only a disk designator but not the
backslash after the colon, it is interpreted as a relative path to the
current directory on the drive with the specified letter. Note that
the current directory may or may not be the root directory depending
on what it was set to during the most recent "change directory"
operation on that disk.
[Emphasis added by me]
You should simply use "test.xml" as a relative path and if the current folder is "D:\data", the full path would be resolved to "D:\Data\test.xml". This is also illustrated in the MSDN example for the Load() method: http://msdn.microsoft.com/en-us/library/bb343181.aspx
Please note that "driveLetter:fileName" is not a relative path in .Net. (Please read Update)
You can transform a relative path into a full path using Path.GetFullPath(), but you do not have to do that XDocument.Load(), since it will also accept relative paths.
Update
LukeH, thanks for pointing this out! "driveLetter:fileName" are accepted by Path.GetFullPath() and are computed as relative paths to the current directory of the specified drive, as specified here.
The concept of current directory at drive level is inherited from the very old days of the DOS. Not necessarily a feature on which I would build modern applications.
Path.GetFullPath can work. see the doc here
As noted in Luke's answer, the solution is due to how the current working directory is used. As an addendum to that answer here is some background. There is seemingly strange behavior of whether the current working directory is per-drive or not. Here is a blog article from Raymond Chen of Microsoft which explains this.
I had to dig around a bit to find a good link for this, so I've copied the contents as well in case it goes bad.
Why does each drive have its own current directory?
Commenter Dean Earley asks, "Why is there a 'current directory' AND
an current drive? Why not merge them?"
Pithy answer: Originally, each drive had its own current directory,
but now they don't, but it looks like they do.
Okay, let's unwrap that sentence. You actually know enough to answer
the question yourself; you just have to put the pieces together.
Set the wayback machine to DOS 1.0. Each volume was represented by a
drive letter. There were no subdirectories. This behavior was carried
forward from CP/M.
Programs from the DOS 1.0 era didn't understand subdirectories; they
referred to files by just drive letter and file name, for example,
B:PROGRAM.LST. Let's fire up the assembler (compilers were for rich
people) and assemble a program whose source code is on the A drive,
but sending the output to the B drive.
A>asm foo the ".asm" extension on "foo" is implied
Assembler version blah blah blah
Source File: FOO.ASM
Listing file [FOO.LST]: NUL throw away the listing file
Object file [FOO.OBJ]: B: send the object file to drive B
Since we gave only a drive letter in response to the Object file prompt, the assembler defaults to a file name of FOO.OBJ, resulting in
the object file being generated as B:FOO.OBJ.
Okay, now let's introduce subdirectories into DOS 2.0. Suppose you
have want to assemble A:\SRC\FOO.ASM and put the result into
B:\OBJ\FOO.OBJ. Here's how you do it:
A> B:
B> CD \OBJ
B> A:
A> CD \SRC
A> asm foo
Assembler version blah blah blah
Source File: FOO.ASM
Listing file [FOO.LST]: NUL
Object file [FOO.OBJ]: B:
The assembler reads from A:FOO.ASM and writes to B:FOO.OBJ, but since
the current directory is tracked on a per-drive basis, the results are
A:\SRC\FOO.ASM and B:\OBJ\FOO.OBJ as desired. If the current directory
were not tracked on a per-drive basis, then there would be no way to
tell the assembler to put its output into a subdirectory. As a result,
DOS 1.0 programs were effectively limited to operating on files in the
root directory, which means that nobody would put files in
subdirectories (because their programs couldn't access them).
From a DOS 1.0 standpoint, changing the current directory on a drive
performs the logical equivalent of changing media. "Oh look, a
completely different set of files!"
Short attention span.
Remembering the current directory for each drive has been preserved
ever since, at least for batch files, although there isn't actually
such a concept as a per-drive current directory in Win32. In Win32,
all you have is a current directory. The appearance that each drive
has its own current directory is a fake-out by cmd.exe, which uses
strange environment variables to create the illusion to batch files
that each drive has its own current directory.
Dean continues, "Why not merge them? I have to set both the dir and
drive if i want a specific working dir."
The answer to the second question is, "They already are merged. It's
cmd.exe that tries to pretend that they aren't." And if you want to
set the directory and the drive from the command prompt or a batch
file, just use the /D option to the CHDIR command:
D:\> CD /D C:\Program Files\Windows NT
C:\Program Files\Windows NT> _
(Notice that the CHDIR command lets you omit quotation marks around
paths which contain spaces: Since the command takes only one path
argument, the lack of quotation marks does not introduce ambiguity.