StreamWriter path's format

mp3909

Well-known member
Joined
Apr 22, 2018
Messages
61
Location
UK
Programming Experience
3-5
This code

C#:
using System;
using System.IO;

class Program
{
    public static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Enter first number");
            int.TryParse(Console.ReadLine(), out int a);

            Console.WriteLine("Enter second number");
            int b = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine(b);

            int result = a / b;

            Console.WriteLine(result);
        }
        catch(Exception ex)
        {
            string filePath = @"‪‪‪C:\SampleFiles\log.txt";
            StreamWriter sw = new StreamWriter(filePath);
            sw.Write(ex.GetType().Name);
            sw.Write(ex.StackTrace);
            sw.Close();
            Console.WriteLine("There is a problem, please try later");
        }
    }

}

gives me an error at saying "The given path's format is not supported." Line 24.
Would anyone know what the issue is?
 
Are you on a Windows machine or a Linux box?
If the latter, I can see how that error would occur since *nix paths don't look like that.
If on Windows, then this becomes a much more interesting problem.
 
@Skydiver doesn't Windows see Path.GetPathRoot(Environment.SystemDirectory); as a system directory? And if indeed it does, doesn't this mean that the user will likely need elevated permissions to create other directories or files in that system directory?

@mp3909 Assuming someone uses this application on another computer, how is your program going to know that the directory structure exists unless you check?

I also think you could make better your path building variables. Perhaps by using string builder or like this ::

C#:
                string drive = Path.GetPathRoot(Environment.SystemDirectory); /* Gives you your C:\ */
                string subFolder = "SampleFiles";
                string fileName = "log";
                string ext = ".txt";
You can then do the following to build your paths. Path.Combine - String.Concat
C#:
                var dir = Path.Combine(drive, subFolder);
                var filePath = Path.Combine(dir, string.Concat(fileName, ext));
You also shouldn't assume a path exists, even if you create it yourself on one PC, because when your app is run on another PC, it will not find the path as the folder will not exist. Simple checking is recommended ::
C#:
                if (!(Directory.Exists(dir)))
                {
                    Directory.CreateDirectory(dir);
                }
At this point you could run your writer ::
C#:
StreamWriter sw = new StreamWriter(filePath);
                    sw.Write(ex.GetType().Name);
                    sw.Write(ex.StackTrace);
                    sw.Close();
As there is no need to check if the file exists, like we did with the directory, because the writer will create the file if it does not exist. But it won't create the directory if that does not exist. And even if your directory does not exist, you'd be getting a DirectoryNotFoundException and not a The given path's format is not supported. error. My theory is that your path is not as you posted it above, and your path is most likely the culprit.

Or your application is deprived of admin privileges. There are two ways to get around that. (These steps are only if your system has certain permission restrictions in place.) Method 1 programmatically run as admin ::
C#:
            var RunAdminMode = new ProcessStartInfo
                {
                    UseShellExecute = true,
                    WorkingDirectory = Environment.CurrentDirectory,
                    FileName = Application.ExecutablePath, Verb = "runas"
                };
            var p = Process.Start(RunAdminMode);
The other (most recommended) is to use a app.manifest file. >> Right click your project >> Add >> New item >> app.manifest.
Next, under your solution explorer project name, open up the file you just added. Now look for this line :: <requestedExecutionLevel level="asInvoker" uiAccess="false" /> and change it to this :: <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> - Then save the file and run your application.

Did this resolve your problem? - If not, put a breakpoint on line 24 and debug, then tell us what the actual path is.

As an aside note, you really should be using your app data or temp folder for this and not the root of the system drive.
 
Yes, but the error in that case would be a flavor of access denied when trying to access the system directory. The error being reported by the OP is about "unsupported format" for a fully qualified file path that looks like a normal Windows/NTFS path: "C:\SampleFiles\log.txt".
 
Yes, so @mp3909 will likely need elevated permissions after resolving the path problem. And so; if the op uses the first and second snipped of the code I posted, it will correctly build the path that they tried to use. If the path existed, it would write the file as it is. If it does not, there is something sinister going on.
 
Yes, if the permissions in the "C:\SampleFiles" directory are restricted which prevents normal users from creating or modifying files there.

In general, though, most modern Windows programmers have now learned to use minimal rights, unlike the 80's, 90's and early 2000's. I recall it took years for internal Microsoft developers/users to stop automatically running as admin. Yes, it is worth trying to see if things succeed of running elevated, but fail when running as normally. If such a situation arises, it is usually worth the effort to figure out why instead of just automatically going with "gotta run as admin when running my code".
 
Yes, but if I can remember right. Allowing anyone to write to the root drive system directory was considered a security risk and in later versions of Windows, it was made so elevated permissions would be required when developers wanted access to the root directory. I should also point out; if the path is non-existent, you will also get the error "System.NotSupportedException: 'The given path's format is not supported.'" See here

549


One of the things the OP might be overlooking is that they may be aware that a streamwriter will create a file if it does not exist, but it won't create a directory if it does not exist. If the path is non existent, the above error will be thrown when accessing that path.
 
Bingo! The directory doesn't even exist! Good find.
 
One other thing I would recommend is the use of using blocks around your streamwriter.
C#:
using (StreamWriter sw = new StreamWriter(filePath))
        {
            sw.Write("your text here");
        }
This way, the resources you use are correctly disposed of once the writer is done writing.

Hope you found this helpful.

Reply via mobile
 
This is pretty strange as the below code works fine (it manages to write to the log.txt file saved on my desktop)

C#:
using System;
using System.IO;

class Program
{

    public static void Main(string[] args)
    {
        if (Directory.Exists(@"C:\Users\mp88_\OneDrive\Desktop"))
        {
            StreamWriter sw = new StreamWriter(@"C:\Users\mp88_\OneDrive\Desktop\log.txt");
            sw.Write("Hello");
            sw.Close();
            Console.WriteLine("Path exists");
        }
        else
        {
            Console.WriteLine("Path does not exist");
        }
    }
}


but for some bizarre reason it is not liking the below:

C#:
using System;
using System.IO;

class Program
{

    public static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Enter first number");
            int.TryParse(Console.ReadLine(), out int fn);

            Console.WriteLine("Enter second number");
            int sn = Convert.ToInt32(Console.ReadLine());

            int result = fn / sn;
        }
        catch(Exception ex)
        {
            StreamWriter sw = new StreamWriter(@"‪C:\Users\mp88_\OneDrive\Desktop\log.txt");
            sw.Write("Hello");
            sw.Close();
        }
    }

}
 
@Skydiver doesn't Windows see Path.GetPathRoot(Environment.SystemDirectory); as a system directory? And if indeed it does, doesn't this mean that the user will likely need elevated permissions to create other directories or files in that system directory?

@mp3909 Assuming someone uses this application on another computer, how is your program going to know that the directory structure exists unless you check?

I also think you could make better your path building variables. Perhaps by using string builder or like this ::

C#:
                string drive = Path.GetPathRoot(Environment.SystemDirectory); /* Gives you your C:\ */
                string subFolder = "SampleFiles";
                string fileName = "log";
                string ext = ".txt";
You can then do the following to build your paths. Path.Combine - String.Concat
C#:
                var dir = Path.Combine(drive, subFolder);
                var filePath = Path.Combine(dir, string.Concat(fileName, ext));
You also shouldn't assume a path exists, even if you create it yourself on one PC, because when your app is run on another PC, it will not find the path as the folder will not exist. Simple checking is recommended ::
C#:
                if (!(Directory.Exists(dir)))
                {
                    Directory.CreateDirectory(dir);
                }
At this point you could run your writer ::
C#:
StreamWriter sw = new StreamWriter(filePath);
                    sw.Write(ex.GetType().Name);
                    sw.Write(ex.StackTrace);
                    sw.Close();
As there is no need to check if the file exists, like we did with the directory, because the writer will create the file if it does not exist. But it won't create the directory if that does not exist. And even if your directory does not exist, you'd be getting a DirectoryNotFoundException and not a The given path's format is not supported. error. My theory is that your path is not as you posted it above, and your path is most likely the culprit.

Or your application is deprived of admin privileges. There are two ways to get around that. (These steps are only if your system has certain permission restrictions in place.) Method 1 programmatically run as admin ::
C#:
            var RunAdminMode = new ProcessStartInfo
                {
                    UseShellExecute = true,
                    WorkingDirectory = Environment.CurrentDirectory,
                    FileName = Application.ExecutablePath, Verb = "runas"
                };
            var p = Process.Start(RunAdminMode);
The other (most recommended) is to use a app.manifest file. >> Right click your project >> Add >> New item >> app.manifest.
Next, under your solution explorer project name, open up the file you just added. Now look for this line :: <requestedExecutionLevel level="asInvoker" uiAccess="false" /> and change it to this :: <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> - Then save the file and run your application.

Did this resolve your problem? - If not, put a breakpoint on line 24 and debug, then tell us what the actual path is.

As an aside note, you really should be using your app data or temp folder for this and not the root of the system drive.


Tried this did not work
 
Define "did not work"?

Show what you tried? Show me where you took on board where I suggested path building to you? If you did; you wouldn't still be using manually wrote-out paths. "‪C:\Users\mp88_\OneDrive\Desktop\log.txt" Microsoft have developed ways for us to determine the correct paths providing we understand what directory structure we are looking to build. That's why I gave you this ::
C#:
                string drive = Path.GetPathRoot(Environment.SystemDirectory); /* Gives you your C:\ */
                string subFolder = "SampleFiles";
                string fileName = "log";
                string ext = ".txt";
                var dir = Path.Combine(drive, subFolder); //This combines the two paths together.
                var filePath = Path.Combine(dir, string.Concat(fileName, ext));
drive is a variable that gets the system base directory of the system where your application runs. While subfolder is the name of your folder you're using. Path.Combine combines these paths for you into one complete path, so you don't need to add backslashes etc. String.Concat appends your fileName with the extension, thus completing your path building. On post 13 you should be using the system namespaces Environment.GetFolderPath to retrieve the desktop location via Environment.SpecialFolder.Desktop. There is a right and a wrong way to do things, and I am only trying to get you to do things the correct way.

Since you haven't told or shown us what you have tried since post 3, its a little hard to help you any further. For example, did you get any additional errors when using the code I supplied? If so what where they? If not, what happened when you ran the code? Did you check to see if the path folder exists prior to executing your code? Did you take on board what I said about the path folder not being able to be created by the streamwriter? Did you also take notes that if you're on a limited user account on Windows, your application will likely need elevated permissions to write to any folders or files in the system directory, and that includes creating of folders programmatically in the root directory. In which case, I've supplied you with an answer to fix that already.

I know what I gave you works, because I wrote it from scratch and tested it myself as I do with all my replies regardless how trivial or simple they may be. I've outlined the possible causes for you above in post 3. I suggest reading over the whole topic again, to ensure you didn't miss anything.
 
Define "did not work"?

Show what you tried? Show me where you took on board where I suggested path building to you? If you did; you wouldn't still be using manually wrote-out paths. "‪C:\Users\mp88_\OneDrive\Desktop\log.txt" Microsoft have developed ways for us to determine the correct paths providing we understand what directory structure we are looking to build. That's why I gave you this ::
C#:
                string drive = Path.GetPathRoot(Environment.SystemDirectory); /* Gives you your C:\ */
                string subFolder = "SampleFiles";
                string fileName = "log";
                string ext = ".txt";
                var dir = Path.Combine(drive, subFolder); //This combines the two paths together.
                var filePath = Path.Combine(dir, string.Concat(fileName, ext));
drive is a variable that gets the system base directory of the system where your application runs. While subfolder is the name of your folder you're using. Path.Combine combines these paths for you into one complete path, so you don't need to add backslashes etc. String.Concat appends your fileName with the extension, thus completing your path building. On post 13 you should be using the system namespaces Environment.GetFolderPath to retrieve the desktop location via Environment.SpecialFolder.Desktop. There is a right and a wrong way to do things, and I am only trying to get you to do things the correct way.

Since you haven't told or shown us what you have tried since post 3, its a little hard to help you any further. For example, did you get any additional errors when using the code I supplied? If so what where they? If not, what happened when you ran the code? Did you check to see if the path folder exists prior to executing your code? Did you take on board what I said about the path folder not being able to be created by the streamwriter? Did you also take notes that if you're on a limited user account on Windows, your application will likely need elevated permissions to write to any folders or files in the system directory, and that includes creating of folders programmatically in the root directory. In which case, I've supplied you with an answer to fix that already.

I know what I gave you works, because I wrote it from scratch and tested it myself as I do with all my replies regardless how trivial or simple they may be. I've outlined the possible causes for you above in post 3. I suggest reading over the whole topic again, to ensure you didn't miss anything.

Carefully reread all of your suggested solution again and it works like a treat!
thanks
 
Back
Top Bottom