Is there any way of validating if a path can be correct in .net or do I need to write something myself?
What I have is a string that is supposed to be a valid path such as:
\\server\shared\folder\file.ext
c:\folder\file.ext
.\folder\file.ext
\folder\file.ext
%appdata%\folder\file.ext
The path does not need to exist on the machine where this is run and the network does not need to be accessible, I'm only interested to see if the path could ever be valid.
Was thinking about splitting the path into filename and path and then using the Path.GetInvalidPathChars() and Path.GetInvalidFileNameChars() arrays to check if the path contains invalid filenames which would at least be a start. But there may be better ideas?
You can use the following library which is part of NDepend: NDepend.Helpers.FileDirectoryPath It has rich API for processing pathes.
Can't you define a valid set of regular expressions? I think we can define the patterns..
Related
I have a file on mac which is at /Users/Bsh/Desktop/myProgram/myFile.txt when I use this address instead of Path.GetFullPath("myFile.txt") in the C# program, the file is found by the program but when I use Path.GetFullPath("myFile.txt") the program does not find the file. To find out what Path.GetFullPath returns, I used Console.WriteLine(Path.GetFullPath("myFile.txt")); and the output was /Users/Bsh/Desktop/myProgram/bin/Debug/netcoreapp3.0/myFile.txt.
Why is there an extra part: bin/Debug/netcoreapp3.0? And how to resolve the issue?
Thanks.
The first step you should take when a library method is not working as expected, is Read The Documentation.
In particular, you should be paying special attention to this part:
This method uses the current directory and current volume information to fully qualify path. If you specify a file name only in path, GetFullPath returns the fully qualified path of the current directory.
The answer to your question seems rather obvious.
I have a .NET MVC application where I am building a virtual path using the below:
Path.Combine("~/Documents/", "application", "username");
The output from this is "~/Documents/application\\username". This causes an error when passed to a Telerik RadFileExplorer however if I manually build the path as "~/Documents/application/username" it works fine. The example above uses strings but the actual code is using variables.
I'd prefer not to use String.Replace if possible... Is there an alternative to Path.Combine that would produce this output? "~/Documents/application/username"
Path.Combine adds the / for you, so you don't need to add it when combining the path.
Try like this: Path.Combine("~/Documents", "application", "username");
There are a lot of alternatives for combining the a path (which is basically a string).
you can use the $ - string interpolation and put the parameters like this: $"~/{Documents}/{application}/{username}" which is more readable than replace.
edit: just saw Raziel's answer, which is probably much better/simpler..
Livio's comment is in general incorrect. That's only true if run on a Unix-based system. If run on a Windows system Path.Combine defaults to backslashes unless otherwise specified.
From the documentation of Path.Combine it only uses the forward slash if it's explicitly included in the path component. I would suggest writing a function for the latter two arguments that just appends a forward slash to the end (and maybe also ensures that there are no slashes at the beginning because that would cause them to be interpreted as absolute paths and overwrite everything before that).
Say, I have two path strings, an absolute one such as #"C:\abc\xyz", and a relative one such as #"..\def". How do I reliably combine those to yield the minimal form #"C:\abc\def"?
As the process should work for any forms of path that .NET's I/O API supports (i.e. the native paths of the system that .NET or Mono is currently running on, or alternatively something like UNC paths and the like), manual string manipulation seems to be too unreliably a solution.
In general, the tidy way to combine path strings is to use the Path.Combine method:
Path.Combine(#"C:\abc\xyz", #"..\def")
Unfortunately, it does not minimize the path and returns C:\abc\xyz\..\def.
As is suggested in a couple of other questions (e.g. this, or this), the GetFullPath method should be applied to the result:
Path.GetFullPath(Path.Combine(#"C:\abc\xyz", #"..\def"))
The problem with this is that GetFullPath actually looks at the file system rather than just handling the path string. From the docs:
The file or directory specified by path is not required to exist. (...) However, if path does exist, the caller must have permission to obtain path information for path. Note that unlike most members of the Path class, this method accesses the file system.
Therefore, GetFullPath doesn't work if I just want to minimize arbitrary path strings: Depending on whether the path happens to exist on the system where the application is running, the method might fail with a SecurityException if the user does not have access to the path.
So, how do I reliably combine path strings that could be processed by System.IO methods to return the shortest possible absolute path?
You can use AbsolutePath of Uri class
var path = new Uri(Path.Combine(#"C:\abc\xyz", #"..\def")).AbsolutePath;
If you want to use it via System.IO you will run into access violation problems at that point.
Why bother to increase the time till the exception comes?
Use try {} catch {} around GetFullPath and handle the error in place would be my suggestion.
So, how do I reliably combine path strings that could be processed by System.IO methods to return the shortest possible absolute path?
I'm building an application (a side project which is likely to enlist the help of the stackoverflow community on more than one occasion) which will need to open a variety of file types (i.e. open Word documents in Word, not natively in my application).
I've been playing with some code for looking up the default application for the file type in the registry and passing this to Process.Start(). There seem to be two issues with this approach:
1) The application name is quoted in some instances, and not in others.
2) Process.Start() requires that the application path and it's arguments are passed separately (i.e. Process.Start("notepad.exe", #"C:\myfile.txt"); rather than Process.Start(#"notepad.exe C:\myfile.txt");).
This means when I retrieve the path from the registry, I have to split it (after determining if I need to split on quotes or spaces) to determine what part is the application path and what parts are arguments, then pass those separately to Process.Start().
The alternative seems to be to just pass the filename, as in Process.Start(#"C:\myfile.txt"), but I think this only works if the application is in the Path environment variable.
Which way is better? In the case of the registry, is there a common solution for how to do the argument parsing?
Thanks for any and all help!
Update:
I guess the short answer is 'No.'
It seems like I was really going the overkill route, and that passing just the filename will work whenever there's an associated value in the registry. I.e. anything I find in the registry myself, Process.Start() already knows how to do.
I did discover that when I try this with a "new" filetype, I get a Win32Exception stating "No application is associated with the specified file for this operation." Fredrik Mörk mentions in a comment that this doesn't occur for him in Vista. What's the proper way to handle this?
If the extension is registered to be opened with a certain application, it doesn't need to be in the PATH in order to run.
The application does not need to be in the PATH if you only specify the filename. The following code worked fine for me:
System.Diagnostics.Process.Start(#"C:\Users\Dan\Desktop\minors.pdf");
You typically do not need to lookup the program for registered types, and the program does not typically need to be in the PATH environment variable. Usually the command in the registry contains the full path. This is how the command for .kml files (Google Earth) looks (in my computer):
C:\Program Files\Google\Google Earth\googleearth.exe "%1"
Given that, you can safely just use Process.Start together with the document file names. Should it be that the file type is not registered you will invoke the default Windows behaviour for this (asking you which program to use, and so on).
Just that... I get a string which contains a path to a file plus some arguments. How can I recognize the path? I thought about the index of the '.' in the file... but I don't like it.
What about using regular expressions? Can anyone point me in the right direction?
Regards
Edit: Theses are valid entries...
somefile.msi /a
C:\MyFolder\SomeFile.exe -i -d
I don't care much about the arguments cause once I have the path I'll assume the rest are arguments
You can use System.IO.Path, and it's static methods.
bool isPath = System.IO.Path.GetDirectoryName(#"C:\MyFolder\SomeFile.exe -i -d") != String.Empty;
if (isPath)
{
Console.WriteLine("The string contains a path");
}
The static Path class has several other methods which are useful as well, like .GetFilename, .GetExtension and .GetPathRoot.
You can also probably use System.IO.Directory and System.IO.File for additional features.
You can't unless you access the file system, because paths may contain spaces.
So you might test each possible "file" using File.Exists. A string.Split() will help you here.
For non-MSI programs, UninstallString is passed to CreateProcess, so you probably want to replicate its method of determining the filename. Read http://msdn.microsoft.com/en-us/library/ms682425.aspx, especially the notes for lpApplicationName and the second half of lpCommandLine.
Programs installed by MSI have a separate system (msi!MsiConfigureProduct or msi!MsiRemovePatches).
Well, before you tackle finding the path in the string, you need to outline a set of rules for what a path in this context
This is, for the operating system, a valid filename: a
Since no directory information is specified, the current directory will be used. The file has no extension.
But is still a filename.
Is this a path in your context? Or do you mean something that has directory information as well?
Examples of what you need to handle would be useful.
The normal way in this case is to tokenise by spaces (and use quotes for a filename with spaces in). Then use / or - for arguments. I think you'll be better off using a standard, accepted format than working for only a subset of cases.
Mmm, I believe that the only reliable way to do that is to access the filesystem, supposing it is reachable.
I would cut the string at the spaces, starting from the end, and take the longest that exist on the filesystem.
For example:
C:\My Folder\Some File.exe -i -d
=>
C:\My Folder\Some File.exe -i -d (no, although it might exist!)
C:\My Folder\Some File.exe -i (no)
C:\My Folder\Some File.exe (yes => That's this one)
You must take in account relative paths, and files in PATH (like your first example, ie. all exe files - even worse, you can write foo.exe or foo on the command line!).
Plus you can often write stuff like notepad/p, which doesn't simplify the algorithm, knowing that C:/windows/notepad.exe is a valid path in XP! :-)
If you have any control over the string I'd recommend you change the way it is represented. One way would be to use URL-style parameters - e.g. fileName=myFile;arg1=value, etc. Then it's trivial to parse on keys.
The problem with any sort of raw parsing scheme is that the trailing data is not necessarily going to be clean. Also your filename is not necessarily NOT going to have spaces, extraneous "."'s etc. So whatever you decide is liable to not be correct 100% of the time.
Have a look at SYstem.IO.Path, you probably want GetDirectoryName(string)
thanks all for the answers.. there are a couple of posts I'd like to mark as the answer... what do you do in these cases?
Just in case somebody wants to see what I'm working on, it's a small application used to uninstall software from my computer. I posted the code, so feel free to download it and take a look at it.
The reason to this post is a good way to implement the private ProcessStartInfo GetProcessInfo(string uninstallString) method.
The reason to this project is posted here...