How to string with list in c#.net? [duplicate] - c#

In my application the user can enter a filename. Before processing I'd like to check if the input String is a valid filename on Windows Vista.
Whats the easiest way to do that?
By valid I'm reffering to legal and non-existing

Check whether filename.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 and !File.Exists(Path.Combine(someFolder, filename))

Check against GetInvalidFileNameChars():
var isValid = !string.IsNullOrEmpty(fileName) &&
fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
!File.Exists(Path.Combine(sourceFolder, fileName));

If the file is going to be created, You should use a file dialog to specify the directory path. There's a short list of illegal characters for file names.
The only truly reliable way to tell if a file name is acceptable is to try it. Permissions
is a morass.

I use this:
public static bool IsValidFileName(string name) {
if(string.IsNullOrWhiteSpace(name)) return false;
if(name.Length > 1 && name[1] == ':') {
if(name.Length < 4 || name.ToLower()[0] < 'a' || name.ToLower()[0] > 'z' || name[2] != '\\') return false;
name = name.Substring(3);
}
if(name.StartsWith("\\\\")) name = name.Substring(1);
if(name.EndsWith("\\") || !name.Trim().Equals(name) || name.Contains("\\\\") ||
name.IndexOfAny(Path.GetInvalidFileNameChars().Where(x=>x!='\\').ToArray()) >= 0) return false;
return true;
}
Should take care of everything but reserved names, permissions, and length restrictions. This accepts both relative and absolute filenames.

This is just an idea. One should populate the exception list:
public static bool IsValidFilename(string filename)
{
try
{
File.OpenRead(filename).Close();
}
catch (ArgumentException) { return false; }
catch (Exception) { }
return true;
}

For first part(Valid Filename), I use all ways and a temporary file creation to check if a file can be named as expected or throws an exception.
In some cases creating a file will not raise an exception until trying to delete it(eg: CON).
I also usa removePath arg to dictate it that file is just the name of file without its path.
using System.IO;
using System.Text;
private static readonly byte[] TestFileBytes = Encoding.ASCII.GetBytes(#"X");
public bool IsFileNameValid(string file, bool removePath = false)
{
try
{
if (string.IsNullOrEmpty(file))
return false;
string fileNamePart = removePath ? Path.GetFileName(file) : file;
if (fileNamePart.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
return false;
string fileName = Path.Combine(Path.GetTempPath(), fileNamePart);
using FileStream fileStream = File.Create(fileName);
{
fileStream.Write(TestFileBytes, 0, TestFileBytes.Length);
}
File.Delete(fileName);
return true;
}
catch
{
return false;
}
}
If there is any denial of access to temp folder use a custom folder for creating test file.
This method will result false for . or .. or ... r any sequence of dot-only names in Windows, and also you can't create them manually, but those are not actually invalid names! those are uncreatable names for file or something like that ;).
And for next part(Not exists) just use: !File.Exists(yourFileNameWithPath).

If you create a DirectoryInfo for the file, it will throw an exception if there are any problems with the file/directory name, either invalid chars or length.
DirectoryInfo di = new DirectoryInfo(myFileName);
Console.WriteLine("This filename/path could be valid. The folder might not exist yet though.")
if(di.Exists)
Console.WriteLine("This file already exist.")
Not great that it is using exceptions for flow control, but you can be confident that it is right. OTOH, if you already planned to give the calling code an exception, mission accomplished.

Related

How can i identify if the string is a file or a directory? [duplicate]

I am processing a TreeView of directories and files. A user can select either a file or a directory and then do something with it. This requires me to have a method which performs different actions based on the user's selection.
At the moment I am doing something like this to determine whether the path is a file or a directory:
bool bIsFile = false;
bool bIsDirectory = false;
try
{
string[] subfolders = Directory.GetDirectories(strFilePath);
bIsDirectory = true;
bIsFile = false;
}
catch(System.IO.IOException)
{
bIsFolder = false;
bIsFile = true;
}
I cannot help to feel that there is a better way to do this! I was hoping to find a standard .NET method to handle this, but I haven't been able to do so. Does such a method exist, and if not, what is the most straightforward means to determine whether a path is a file or directory?
From How to tell if path is file or directory:
// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(#"c:\Temp");
//detect whether its a directory or file
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
MessageBox.Show("Its a directory");
else
MessageBox.Show("Its a file");
Update for .NET 4.0+
Per the comments below, if you are on .NET 4.0 or later (and maximum performance is not critical) you can write the code in a cleaner way:
// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(#"c:\Temp");
if (attr.HasFlag(FileAttributes.Directory))
MessageBox.Show("Its a directory");
else
MessageBox.Show("Its a file");
How about using this?
if(File.Exists(data.path))
{
// is file
}
else if(Directory.Exists(data.path))
{
// is Folder
}
else
{
// invalid path
}
File.Exists() will return false if it's not a file even if the directory does exist, so if it returns true, we know we got a file, if it returns false, we either have a directory or an invalid path so next we test if it's a valid directory with Directory.Exists() if that returns true, we have a directory if not it's an invalid path.
With only this line you can get if a path is a directory or a file:
File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
Here's mine:
bool IsPathDirectory(string path)
{
if (path == null) throw new ArgumentNullException("path");
path = path.Trim();
if (Directory.Exists(path))
return true;
if (File.Exists(path))
return false;
// neither file nor directory exists. guess intention
// if has trailing slash then it's a directory
if (new[] {"\\", "/"}.Any(x => path.EndsWith(x)))
return true; // ends with slash
// if has extension then its a file; directory otherwise
return string.IsNullOrWhiteSpace(Path.GetExtension(path));
}
It's similar to others' answers but not exactly the same.
As an alternative to Directory.Exists(), you can use the File.GetAttributes() method to get the attributes of a file or a directory, so you could create a helper method like this:
private static bool IsDirectory(string path)
{
System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
return (fa & FileAttributes.Directory) != 0;
}
You could also consider adding an object to the tag property of the TreeView control when populating the control that contains additional metadata for the item. For instance, you could add a FileInfo object for files and a DirectoryInfo object for directories and then test for the item type in the tag property to save making additional system calls to get that data when clicking on the item.
After combining the suggestions from the other answers, I realized I came up with about the same thing as Ronnie Overby's answer. Here are some tests to point out some things to think about:
folders can have "extensions": C:\Temp\folder_with.dot
files cannot end with a directory separator (slash)
There are technically two directory separators which are platform specific -- i.e. may or may not be slashes (Path.DirectorySeparatorChar and Path.AltDirectorySeparatorChar)
Tests (Linqpad)
var paths = new[] {
// exists
#"C:\Temp\dir_test\folder_is_a_dir",
#"C:\Temp\dir_test\is_a_dir_trailing_slash\",
#"C:\Temp\dir_test\existing_folder_with.ext",
#"C:\Temp\dir_test\file_thats_not_a_dir",
#"C:\Temp\dir_test\notadir.txt",
// doesn't exist
#"C:\Temp\dir_test\dne_folder_is_a_dir",
#"C:\Temp\dir_test\dne_folder_trailing_slash\",
#"C:\Temp\dir_test\non_existing_folder_with.ext",
#"C:\Temp\dir_test\dne_file_thats_not_a_dir",
#"C:\Temp\dir_test\dne_notadir.txt",
};
foreach(var path in paths) {
IsFolder(path/*, false*/).Dump(path);
}
Results
C:\Temp\dir_test\folder_is_a_dir
True
C:\Temp\dir_test\is_a_dir_trailing_slash\
True
C:\Temp\dir_test\existing_folder_with.ext
True
C:\Temp\dir_test\file_thats_not_a_dir
False
C:\Temp\dir_test\notadir.txt
False
C:\Temp\dir_test\dne_folder_is_a_dir
True
C:\Temp\dir_test\dne_folder_trailing_slash\
True
C:\Temp\dir_test\non_existing_folder_with.ext
False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
True
C:\Temp\dir_test\dne_notadir.txt
False
Method
/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not);
/// optionally assume that if it doesn't "look like" a file then it's a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name? As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
// https://stackoverflow.com/questions/1395205/better-way-to-check-if-path-is-a-file-or-a-directory
// turns out to be about the same as https://stackoverflow.com/a/19596821/1037948
// check in order of verisimilitude
// exists or ends with a directory separator -- files cannot end with directory separator, right?
if (Directory.Exists(path)
// use system values rather than assume slashes
|| path.EndsWith("" + Path.DirectorySeparatorChar)
|| path.EndsWith("" + Path.AltDirectorySeparatorChar))
return true;
// if we know for sure that it's an actual file...
if (File.Exists(path))
return false;
// if it has an extension it should be a file, so vice versa
// although technically directories can have extensions...
if (!Path.HasExtension(path) && assumeDneLookAlike)
return true;
// only works for existing files, kinda redundant with `.Exists` above
//if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...;
// no idea -- could return an 'indeterminate' value (nullable bool)
// or assume that if we don't know then it's not a folder
return false;
}
This was the best I could come up with given the behavior of the Exists and Attributes properties:
using System.IO;
public static class FileSystemInfoExtensions
{
/// <summary>
/// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
/// </summary>
/// <param name="fileSystemInfo"></param>
/// <returns></returns>
public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
{
if (fileSystemInfo == null)
{
return false;
}
if ((int)fileSystemInfo.Attributes != -1)
{
// if attributes are initialized check the directory flag
return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
}
// If we get here the file probably doesn't exist yet. The best we can do is
// try to judge intent. Because directories can have extensions and files
// can lack them, we can't rely on filename.
//
// We can reasonably assume that if the path doesn't exist yet and
// FileSystemInfo is a DirectoryInfo, a directory is intended. FileInfo can
// make a directory, but it would be a bizarre code path.
return fileSystemInfo is DirectoryInfo;
}
}
Here's how it tests out:
[TestMethod]
public void IsDirectoryTest()
{
// non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentFile = #"C:\TotallyFakeFile.exe";
var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());
var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());
// non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentDirectory = #"C:\FakeDirectory";
var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());
var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
Assert.IsFalse(nonExistentFileInfo.IsDirectory());
// Existing, rely on FileAttributes
const string existingDirectory = #"C:\Windows";
var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
Assert.IsTrue(existingDirectoryInfo.IsDirectory());
var existingDirectoryFileInfo = new FileInfo(existingDirectory);
Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());
// Existing, rely on FileAttributes
const string existingFile = #"C:\Windows\notepad.exe";
var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());
var existingFileFileInfo = new FileInfo(existingFile);
Assert.IsFalse(existingFileFileInfo.IsDirectory());
}
public bool IsDirectory(string path) {
return string.IsNullOrEmpty(Path.GetFileName(path)) || Directory.Exists(path);
}
Checks if the path file name is an empty string, or if the directory exists. This way you won't have the file attributes error while still providing redundancies for a possible exists failure.
Here's what we use:
using System;
using System.IO;
namespace crmachine.CommonClasses
{
public static class CRMPath
{
public static bool IsDirectory(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
string reason;
if (!IsValidPathString(path, out reason))
{
throw new ArgumentException(reason);
}
if (!(Directory.Exists(path) || File.Exists(path)))
{
throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path));
}
return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory;
}
public static bool IsValidPathString(string pathStringToTest, out string reasonForError)
{
reasonForError = "";
if (string.IsNullOrWhiteSpace(pathStringToTest))
{
reasonForError = "Path is Null or Whitespace.";
return false;
}
if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260
{
reasonForError = "Length of path exceeds MAXPATH.";
return false;
}
if (PathContainsInvalidCharacters(pathStringToTest))
{
reasonForError = "Path contains invalid path characters.";
return false;
}
if (pathStringToTest == ":")
{
reasonForError = "Path consists of only a volume designator.";
return false;
}
if (pathStringToTest[0] == ':')
{
reasonForError = "Path begins with a volume designator.";
return false;
}
if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1)
{
reasonForError = "Path contains a volume designator that is not part of a drive label.";
return false;
}
return true;
}
public static bool PathContainsInvalidCharacters(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
bool containedInvalidCharacters = false;
for (int i = 0; i < path.Length; i++)
{
int n = path[i];
if (
(n == 0x22) || // "
(n == 0x3c) || // <
(n == 0x3e) || // >
(n == 0x7c) || // |
(n < 0x20) // the control characters
)
{
containedInvalidCharacters = true;
}
}
return containedInvalidCharacters;
}
public static bool FilenameContainsInvalidCharacters(string filename)
{
if (filename == null)
{
throw new ArgumentNullException("filename");
}
bool containedInvalidCharacters = false;
for (int i = 0; i < filename.Length; i++)
{
int n = filename[i];
if (
(n == 0x22) || // "
(n == 0x3c) || // <
(n == 0x3e) || // >
(n == 0x7c) || // |
(n == 0x3a) || // :
(n == 0x2a) || // *
(n == 0x3f) || // ?
(n == 0x5c) || // \
(n == 0x2f) || // /
(n < 0x20) // the control characters
)
{
containedInvalidCharacters = true;
}
}
return containedInvalidCharacters;
}
}
}
The most accurate approach is going to be using some interop code from the shlwapi.dll
[DllImport(SHLWAPI, CharSet = CharSet.Unicode)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);
You would then call it like this:
#region IsDirectory
/// <summary>
/// Verifies that a path is a valid directory.
/// </summary>
/// <param name="path">The path to verify.</param>
/// <returns><see langword="true"/> if the path is a valid directory;
/// otherwise, <see langword="false"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <para><paramref name="path"/> is <see langword="null"/>.</para>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para>
/// </exception>
public static bool IsDirectory(string path)
{
return PathIsDirectory(path);
}
I came across this when facing a similar problem, except I needed to check if a path is for a file or folder when that file or folder may not actually exist. There were a few comments on answers above that mentioned they would not work for this scenario. I found a solution (I use VB.NET, but you can convert if you need) that seems to work well for me:
Dim path As String = "myFakeFolder\ThisDoesNotExist\"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns True
Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns False
Hopefully this can be helpful to someone!
soooo late in the game i know, but thought i'd share this anyway. If you are solely working with the paths as strings, figuring this out is easy as pie:
private bool IsFolder(string ThePath)
{
string BS = Path.DirectorySeparatorChar.ToString();
return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}
for example:
ThePath == "C:\SomeFolder\File1.txt" would end up being this:
return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)
Another example:
ThePath == "C:\SomeFolder\" would end up being this:
return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)
And this would also work without the trailing backslash:
ThePath == "C:\SomeFolder" would end up being this:
return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)
Keep in mind here that this only works with the paths themselves, and not the relationship between the path and the "physical disk"... so it can't tell you if the path/file exists or anything like that, but it sure can tell you if the path is a folder or a file...
If you want to find directories, including those that are marked "hidden" and "system", try this (requires .NET V4):
FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory))
I needed this, the posts helped, this gets it down to one line, and if the path isn't a path at all, it just returns and exits the method. It addresses all of the above concerns, doesn't need the trailing slash either.
if (!Directory.Exists(#"C:\folderName")) return;
I see, I'm 10 years too late to the party.
I was facing the situation, where from some property I can receive either a file name or a full file path. If there is no path provided, I have to check the file-existence by attaching a "global" directory-path provided by another property.
In my case
var isFileName = System.IO.Path.GetFileName (str) == str;
did the trick.
Ok, it's not magic, but perhaps this could save someone a few minutes of figuring out.
Since this is merely a string-parsing, so Dir-names with dots may give false positives...
I use the following, it also tests the extension which means it can be used for testing if the path supplied is a file but a file that doesn't exist.
private static bool isDirectory(string path)
{
bool result = true;
System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
if (fileTest.Exists == true)
{
result = false;
}
else
{
if (fileTest.Extension != "")
{
result = false;
}
}
return result;
}
using System;
using System.IO;
namespace FileOrDirectory
{
class Program
{
public static string FileOrDirectory(string path)
{
if (File.Exists(path))
return "File";
if (Directory.Exists(path))
return "Directory";
return "Path Not Exists";
}
static void Main()
{
Console.WriteLine("Enter The Path:");
string path = Console.ReadLine();
Console.WriteLine(FileOrDirectory(path));
}
}
}
Using the selected answer on this post, I looked at the comments and give credence to
#ŞafakGür, #Anthony and #Quinn Wilson for their info bits that lead me to this improved answer which I wrote and tested:
/// <summary>
/// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool? IsDirFile(this string path)
{
bool? result = null;
if(Directory.Exists(path) || File.Exists(path))
{
// get the file attributes for file or directory
var fileAttr = File.GetAttributes(path);
if (fileAttr.HasFlag(FileAttributes.Directory))
result = true;
else
result = false;
}
return result;
}
Maybe for UWP C#
public static async Task<IStorageItem> AsIStorageItemAsync(this string iStorageItemPath)
{
if (string.IsNullOrEmpty(iStorageItemPath)) return null;
IStorageItem storageItem = null;
try
{
storageItem = await StorageFolder.GetFolderFromPathAsync(iStorageItemPath);
if (storageItem != null) return storageItem;
} catch { }
try
{
storageItem = await StorageFile.GetFileFromPathAsync(iStorageItemPath);
if (storageItem != null) return storageItem;
} catch { }
return storageItem;
}
Very late to the party here but I've found the Nullable<Boolean> return value to be quite ugly - IsDirectory(string path) returning null doesn't equate to a non-existent path without verbose commenting, so I've come up with the following:
public static class PathHelper
{
/// <summary>
/// Determines whether the given path refers to an existing file or directory on disk.
/// </summary>
/// <param name="path">The path to test.</param>
/// <param name="isDirectory">When this method returns, contains true if the path was found to be an existing directory, false in all other scenarios.</param>
/// <returns>true if the path exists; otherwise, false.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="path"/> is null.</exception>
/// <exception cref="ArgumentException">If <paramref name="path"/> equals <see cref="string.Empty"/></exception>
public static bool PathExists(string path, out bool isDirectory)
{
if (path == null) throw new ArgumentNullException(nameof(path));
if (path == string.Empty) throw new ArgumentException("Value cannot be empty.", nameof(path));
isDirectory = Directory.Exists(path);
return isDirectory || File.Exists(path);
}
}
This helper method is written to be verbose and concise enough to understand the intent the first time you read it.
/// <summary>
/// Example usage of <see cref="PathExists(string, out bool)"/>
/// </summary>
public static void Usage()
{
const string path = #"C:\dev";
if (!PathHelper.PathExists(path, out var isDirectory))
return;
if (isDirectory)
{
// Do something with your directory
}
else
{
// Do something with your file
}
}
Just adding a fringe case - "Folder Selection." in path
In my app I get recently opened paths passed to me, some of which have "Folder Selection." at the end.
Some FileOpenDialogs and WinMerge add "Folder Selection." to paths (it's true).
But under Windows OS "Folder Selection." is not an advised file or folder name (as in don't do it, ever - shakes fist).
As said here: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".
So whilst "Folder Selection." shouldn't be used, it can be. (awesome).
Enough explanation - my code (I like enums a lot):
public static class Utility
{
public enum ePathType
{
ePathType_Unknown = 0,
ePathType_ExistingFile = 1,
ePathType_ExistingFolder = 2,
ePathType_ExistingFolder_FolderSelectionAdded = 3,
}
public static ePathType GetPathType(string path)
{
if (File.Exists(path) == true) { return ePathType.ePathType_ExistingFile; }
if (Directory.Exists(path) == true) { return ePathType.ePathType_ExistingFolder; }
if (path.EndsWith("Folder Selection.") == true)
{
// Test the path again without "Folder Selection."
path = path.Replace("\\Folder Selection.", "");
if (Directory.Exists(path) == true)
{
// Could return ePathType_ExistingFolder, but prefer to let the caller known their path has text to remove...
return ePathType.ePathType_ExistingFolder_FolderSelectionAdded;
}
}
return ePathType.ePathType_Unknown;
}
}
This is my solution, beware that i was looking for a function that strictly avoid any unnecessary file system access at all, but only string manipulations are allowed here (paths may not exist):
public static bool IsFolder(string path)
{
if (string.IsNullOrEmpty(path)) return false;
if (path.EndsWith("\\")) return true;
return (path.Contains("\\") && string.IsNullOrEmpty(Path.GetExtension(path)));
}
Wouldn't this work?
var isFile = Regex.IsMatch(path, #"\w{1,}\.\w{1,}$");

SSIS Script Task Check if a folder is empty

Within a SSIS Script Task, I have the below code that checks if a folder is empty. I then want to pass if it is or not into the variable 'Dim_File_Count' and use a Precedence constraint to move onto the next task if successful. However my code keeps stating the folder is empty, even when it's not:
public void Main()
{
//string FolderName = Dts.Variables["User::Tech_Dim"].Value.ToString();
if (File.Exists(Dts.Variables["User::Tech_Dim"].Value.ToString())==false)
{
Dts.Variables["User::Dim_File_Count"].Value = 0;
MessageBox.Show("folder empty");
}
else
{
Dts.Variables["User::Dim_File_Count"].Value = 1;
MessageBox.Show("folder is not empty");
}
Dts.TaskResult = (int)ScriptResults.Success;
}
You can use the Length property of the GetFiles method of the Directory class to check if there are any files in the specified folder. The optional third SearchOption parameter of GetFiles can be used if searching sub-directories is necessary, i.e. SearchOption.AllDirectories, with the default checking only the parent folder.
if (Directory.GetFiles(Dts.Variables["User::Tech_Dim"].Value.ToString(), "*").Length > 0)
{
Dts.Variables["User::Dim_File_Count"].Value = 0;
MessageBox.Show("folder empty");
}
else
{
Dts.Variables["User::Dim_File_Count"].Value = 1;
MessageBox.Show("folder is not empty");
}

Check if can create folder/file in specific path

I need to check if the current user has write permissions inside the path. Here an example:
string save_path = #"C:\Windows\somefolder";
string my_dir = Path.DirectorySeparatorChar + "foobar";
//check if specific path are valid
if (!Directory.Exists(save_path)) { return; }
if (Directory.Exists(save_path + my_dir)) { return; }
if (canWriteOnPath(save_path)) {
Directory.CreateDirectory(save_path + my_dir);
} else {
//You are not allowed to save here OR not are launching this application as "administrator"
Directory.CreateDirectory(#"C:\Users\contoso\Documents\foobar");
}
solved in this question:
CurrentUserSecurity cus = new CurrentUserSecurity();
bool flag = cus.HasAccess(new DirectoryInfo(#"C:\Windows"), FileSystemRights.Write);
if (flag) {
//yes create that folder
Directory.CreateDirectory(Path.Combine(save_path, my_dir));
} else {
//NO YOU CANT
Directory.CreateDirectory(#"C:\Users\contoso\Documents\foobar");
}
The robust method would be to Try to create the directory and Catch any resulting exception.
The documentation for Directory.CreateDirectory lists the possible exceptions: IOException, UnauthorizedAccessException, ArgumentException, ArgumentNullException, PathTooLongException, DirectoryNotFoundException.
Although unlikely, it is possible that the permissions changed between your code checking that access is allowed and actually trying to create the directory.

Check if directory is accessible in C#? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
.NET - Check if directory is accessible without exception handling
Im making a small file explorer in Visual Studio 2010 with NET 3.5 and C#, and I have this function to check if a directory is accessible:
RealPath=#"c:\System Volume Information";
public bool IsAccessible()
{
//get directory info
DirectoryInfo realpath = new DirectoryInfo(RealPath);
try
{
//if GetDirectories works then is accessible
realpath.GetDirectories();
return true;
}
catch (Exception)
{
//if exception is not accesible
return false;
}
}
But I think with big directories it could be slow trying to get all sub directories to check if directory is accesible.
Im using this function to prevent errors when trying to explore protected folders or cd/dvd drives without disc ("Device Not Ready" error).
Is there a better way (faster) to check if directory is accessible by the application (preferably in NET 3.5)?
According to MSDN, Directory.Exists should return false if you don't have read access to the directory. However, you can use Directory.GetAccessControl for this. Example:
public static bool CanRead(string path)
{
try
{
var readAllow = false;
var readDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if(accessControlList == null)
return false;
//get the access rules that pertain to a valid SID/NTAccount.
var accessRules = accessControlList.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
if(accessRules ==null)
return false;
//we want to go over these rules to ensure a valid SID has access
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) != FileSystemRights.Read) continue;
if (rule.AccessControlType == AccessControlType.Allow)
readAllow = true;
else if (rule.AccessControlType == AccessControlType.Deny)
readDeny = true;
}
return readAllow && !readDeny;
}
catch(UnauthorizedAccessException ex)
{
return false;
}
}
Update
As mentioned in some comments, this may return an incorrect value in a case where a valid SID in an external DOMAIN has access. In order to check if the current user has access, you need something like:
foreach...
if (WindowsIdentity.GetCurrent().User.Value.equals(rule.IdentityReference.Value))
This will confirm if the SID of the current user matches the access rule identity reference but may throw a SecurityException as well.
I think you are looking for the GetAccessControl method, the System.IO.File.GetAccessControl method returns a FileSecurity object that encapsulates the access control for a file.

In C# check that filename is *possibly* valid (not that it exists) [duplicate]

This question already has answers here:
How do I check if a given string is a legal/valid file name under Windows?
(27 answers)
Closed 7 years ago.
Is there a method in the System.IO namespace that checks the validity of a filename?
For example, C:\foo\bar would validate and :"~-* would not
Or a little trickier, X:\foo\bar would validate is there is an X: drive on the system, but wouldn't otherwise.
I suppose I could write such a method myself, but I'm more interested in a built-in one.
Just do;
System.IO.FileInfo fi = null;
try {
fi = new System.IO.FileInfo(fileName);
}
catch (ArgumentException) { }
catch (System.IO.PathTooLongException) { }
catch (NotSupportedException) { }
if (ReferenceEquals(fi, null)) {
// file name is not valid
} else {
// file name is valid... May check for existence by calling fi.Exists.
}
For creating a FileInfo instance the file does not need to exist.
You can get a list of invalid characters from Path.GetInvalidPathChars and GetInvalidFileNameChars as discussed in this question.
As noted by jberger, there some other characters which are not included in the response from this method. For much more details of the windows platform, take a look at Naming Files, Paths and Namespaces on MSDN.
As Micah points out, there is Directory.GetLogicalDrives to get a list of valid drives.
You could make use the System.Uri class. The Uri class isn't just useful for web URLs, it also handles file system paths as well. Use the Uri.TryCreate method to find if the path is rooted then use the IsLoopback property to determine if the Uri references the local machine.
Here is a simple method which determines if a string is a valid, local, and rooted file path.
public bool IsPathValidRootedLocal(String pathString) {
Uri pathUri;
Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
return isValidUri && pathUri != null && pathUri.IsLoopback;
}
I am confident this will work.
There are several methods you could use that exist in the System.IO namespace:
Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.
As suggested you could then do this:
bool IsValidFilename(string testName) {
string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
Regex containsABadCharacter = new Regex(regexString);
if (containsABadCharacter.IsMatch(testName)) {
return false;
}
// Check for drive
string pathRoot = Path.GetPathRoot(testName);
if (Directory.GetLogicalDrives().Contains(pathRoot)) {
// etc
}
// other checks for UNC, drive-path format, etc
return true;
}
Thought I would post a solution I cobbled together from bits of answers I found after searching for a robust solution to the same problem. Hopefully it helps someone else.
using System;
using System.IO;
//..
public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
if (string.IsNullOrEmpty(path)) { return false; }
string root = null;
string directory = null;
string filename = null;
try
{
// throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
root = Path.GetPathRoot(path);
// throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
// -or- String.Empty was passed to path.
directory = Path.GetDirectoryName(path);
// path contains one or more of the invalid characters defined in GetInvalidPathChars
if (IncludeFileName) { filename = Path.GetFileName(path); }
}
catch (ArgumentException)
{
return false;
}
// null if path is null, or an empty string if path does not contain root directory information
if (String.IsNullOrEmpty(root)) { return false; }
// null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
if (String.IsNullOrEmpty(directory)) { return false; }
if (RequireFileName)
{
// if the last character of path is a directory or volume separator character, this method returns String.Empty
if (String.IsNullOrEmpty(filename)) { return false; }
// check for illegal chars in filename
if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
}
return true;
}
Even if the filename is valid, you may still want to touch it to be sure the user has permission to write.
If you won't be thrashing the disk with hundreds of files in a short period of time, I think creating an empty file is a reasonable approach.
If you really want something lighter, like just checking for invalid chars, then compare your filename against Path.GetInvalidFileNameChars().
Several of the System.IO.Path methods will throw exceptions if the path or filename is invalid:
Path.IsPathRooted()
Path.GetFileName()
http://msdn.microsoft.com/en-us/library/system.io.path_methods.aspx
I've had luck using regular expressions as others have shown.
One thing to keep in mind is that Windows at least prohibits some filenames that otherwise containlegal characters. A few come to mind: com, nul, prn.
I don't have it with me now, but I have a regex that takes these filename into consideration. If you want I can post it, otherwise I'm sure you can find it the same way I did: Google.
-Jay
Use the static GetInvalidFileNameChars method on the Path class in the System.IO namespace to determine what characters are illegal in a file name.
To do so in a path, call the static GetInvalidPathChars method on the same class.
To determine if the root of a path is valid, you would call the static GetPathRoot method on the Path class to get the root, then use the Directory class to determine if it is valid. Then you can validate the rest of the path normally.
Try out this method which would try to cover for all the possible Exceptions scenarios. It would work for almost all the Windows related Paths.
/// <summary>
/// Validate the Path. If path is relative append the path to the project directory by default.
/// </summary>
/// <param name="path">Path to validate</param>
/// <param name="RelativePath">Relative path</param>
/// <param name="Extension">If want to check for File Path</param>
/// <returns></returns>
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "") {
// Check if it contains any Invalid Characters.
if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1) {
try {
// If path is relative take %IGXLROOT% as the base directory
if (!Path.IsPathRooted(path)) {
if (string.IsNullOrEmpty(RelativePath)) {
// Exceptions handled by Path.GetFullPath
// ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
//
// SecurityException The caller does not have the required permissions.
//
// ArgumentNullException path is null.
//
// NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\").
// PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.
// RelativePath is not passed so we would take the project path
path = Path.GetFullPath(RelativePath);
} else {
// Make sure the path is relative to the RelativePath and not our project directory
path = Path.Combine(RelativePath, path);
}
}
// Exceptions from FileInfo Constructor:
// System.ArgumentNullException:
// fileName is null.
//
// System.Security.SecurityException:
// The caller does not have the required permission.
//
// System.ArgumentException:
// The file name is empty, contains only white spaces, or contains invalid characters.
//
// System.IO.PathTooLongException:
// The specified path, file name, or both exceed the system-defined maximum
// length. For example, on Windows-based platforms, paths must be less than
// 248 characters, and file names must be less than 260 characters.
//
// System.NotSupportedException:
// fileName contains a colon (:) in the middle of the string.
FileInfo fileInfo = new FileInfo(path);
// Exceptions using FileInfo.Length:
// System.IO.IOException:
// System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
// directory.
//
// System.IO.FileNotFoundException:
// The file does not exist.-or- The Length property is called for a directory.
bool throwEx = fileInfo.Length == -1;
// Exceptions using FileInfo.IsReadOnly:
// System.UnauthorizedAccessException:
// Access to fileName is denied.
// The file described by the current System.IO.FileInfo object is read-only.-or-
// This operation is not supported on the current platform.-or- The caller does
// not have the required permission.
throwEx = fileInfo.IsReadOnly;
if (!string.IsNullOrEmpty(Extension)) {
// Validate the Extension of the file.
if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase)) {
// Trim the Library Path
path = path.Trim();
return true;
} else {
return false;
}
} else {
return true;
}
} catch (ArgumentNullException) {
// System.ArgumentNullException:
// fileName is null.
} catch (System.Security.SecurityException) {
// System.Security.SecurityException:
// The caller does not have the required permission.
} catch (ArgumentException) {
// System.ArgumentException:
// The file name is empty, contains only white spaces, or contains invalid characters.
} catch (UnauthorizedAccessException) {
// System.UnauthorizedAccessException:
// Access to fileName is denied.
} catch (PathTooLongException) {
// System.IO.PathTooLongException:
// The specified path, file name, or both exceed the system-defined maximum
// length. For example, on Windows-based platforms, paths must be less than
// 248 characters, and file names must be less than 260 characters.
} catch (NotSupportedException) {
// System.NotSupportedException:
// fileName contains a colon (:) in the middle of the string.
} catch (FileNotFoundException) {
// System.FileNotFoundException
// The exception that is thrown when an attempt to access a file that does not
// exist on disk fails.
} catch (IOException) {
// System.IO.IOException:
// An I/O error occurred while opening the file.
} catch (Exception) {
// Unknown Exception. Might be due to wrong case or nulll checks.
}
} else {
// Path contains invalid characters
}
return false;
}
I don't know of anything out of the box that can just validate all of that for you, however the Path class in .NET can help you out tremendously.
For starters, it has:
char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters
or:
Path.GetPathRoot(string); // will return the root.
Probably the bast way is to build a custom method mixing a combination of regex and small look up on your file system (to see the drives, for example)
This will get you the drives on the machine:
System.IO.DriveInfo.GetDrives()
These two methods will get you the bad characters to check:
System.IO.Path.GetInvalidFileNameChars();
System.IO.Path.GetInvalidPathChars();
Think it's too late to answer but... :)
in case of path with volume name you could write something like this:
using System;
using System.Linq;
using System.IO;
// ...
var drives = Environment.GetLogicalDrives();
var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\\/]", "");
var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
if (drive != null) {
var fileDirPath = filePath.Substring(drive.Length);
if (0 < fileDirPath.Length) {
if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
if (Path.Combine(drive, fileDirPath) != drive) {
// path correct and we can proceed
}
}
}
}

Categories