That is not a limitation of .NET, but of the Win32 API. Try to create one in a command shell:
c:\drop>mkdir test.
c:\drop>dir
Volume in drive C has no label.
Volume Serial Number is C0F3-338B
Directory of c:\drop
2013-04-02 17:54 <DIR> .
2013-04-02 17:54 <DIR> ..
2013-04-02 17:54 <DIR> test
See MSDN for naming reccomendations. To quote:
•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".
If you are really quite insistent on using a trailing dot, use \\?\C:\path.
.
c:\drop>mkdir \\?\c:\drop\test2.
c:\drop>dir
Volume in drive C has no label.
Volume Serial Number is C0F3-338B
Directory of c:\drop
2013-04-02 17:58 <DIR> .
2013-04-02 17:58 <DIR> ..
2013-04-02 17:54 <DIR> test
2013-04-02 17:58 <DIR> test2.
Edit: The requirement as listed in the contents is that no additional files are created, so don't use a file. You can create a "name" stream on the directory and store data there. See the following for an example:
c:\drop>mkdir "Example Company Name"
c:\drop>notepad "Example Company Name:name.txt"
c:\drop>dir
Volume in drive C has no label.
Volume Serial Number is C0F3-338B
Directory of c:\drop
2013-04-02 18:25 <DIR> .
2013-04-02 18:25 <DIR> ..
2013-04-02 18:25 <DIR> Example Company Name
0 File(s) 0 bytes
3 Dir(s) 77,336,379,392 bytes free
c:\drop>dir "Example Company Name"
Volume in drive C has no label.
Volume Serial Number is C0F3-338B
Directory of c:\drop\Example Company Name
2013-04-02 18:25 <DIR> .
2013-04-02 18:25 <DIR> ..
0 File(s) 0 bytes
2 Dir(s) 77,336,313,856 bytes free
Or in .NET:
class Program
{
static void Main(string[] args)
{
string companyName = "Example Company?*, Inc.";
//Example Company Inc
var sanitizedName = sanitize(companyName);
//Create the directory
Directory.CreateDirectory(sanitizedName);
//Create the name store
var nameStreamPath = sanitizedName + ":Name";
writeFileContent(companyName, nameStreamPath);
//Try to return the name
Console.WriteLine(getFileContent(nameStreamPath));
Console.ReadLine();
}
private static string getFileContent(string path)
{
using (var sr = new StreamReader(new FileStream(
// we have to call CreateFile directly to avoid overzealous path validation
NativeMethods.CreateFileOrFail(path, false), FileAccess.Read)))
{
return sr.ReadToEnd();
}
}
private static void writeFileContent(string companyName, string path)
{
using (var sw = new StreamWriter(new FileStream(
// We have to call CreateFile directly to avoid overzealous path validation
NativeMethods.CreateFileOrFail(path, true), FileAccess.Write)))
{
sw.Write(companyName);
}
}
private static string sanitize(string path)
{
char[] newPath = new char[path.Length];
int newPathLoc = 0;
for (int i = 0; i < path.Length; i++)
{
if (char.IsLetter(path[i]) || char.IsDigit(path[i]))
{
newPath[newPathLoc] = path[i];
newPathLoc++;
}
}
return new string(newPath, 0, newPathLoc);
}
}
class NativeMethods
{
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern SafeFileHandle CreateFile(
string fileName,
[MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
[MarshalAs(UnmanagedType.U4)] FileShare fileShare,
IntPtr securityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flags,
IntPtr template);
public static SafeFileHandle CreateFileOrFail(string path, bool write)
{
var handle = CreateFile(path,
write ? FileAccess.Write : FileAccess.Read,
write ? FileShare.None : FileShare.Read,
IntPtr.Zero,
write ? FileMode.Create : FileMode.Open,
FileAttributes.Normal,
IntPtr.Zero);
if (handle.IsInvalid)
throw new System.ComponentModel.Win32Exception();
return handle;
}
}