Directory.CreateDirectory does not create a folder - c#

I am trying to create a new directory using Directory.CreateDirectory(), but I am unable to understand why it does not create a new directory when I use the following code.
var directory = Path.Combine(Environment.CurrentDirectory, "Status" + "-" + "Test" + Guid.NewGuid() + "\\");
Directory.CreateDirectory(directory);
But when I manually feed the file path it creates the directory (works well).
Directory.CreateDirectory(#"F:\Code\Help\");
Am I doing it wrong?
Any comments or feedback is greatly appreciated. TIA.

There is nothing wrong with your code per-se
My suspicion is you are creating a directory (somewhere)
try
{
var directory = Path.Combine(Environment.CurrentDirectory, $#"Status-Test{Guid.NewGuid()}");
Console.WriteLine(directory);
var di = Directory.CreateDirectory(directory);
Console.WriteLine($"The directory was created successfully at {Directory.GetCreationTime(directory)}.");
Console.WriteLine($"==> { di.FullName}");
}
catch (Exception e)
{
Console.WriteLine("Oh NOES!: {0}", e);
}
Environment.CurrentDirectory Property
By definition, if this process starts in the root directory of a local
or network drive, the value of this property is the drive name
followed by a trailing slash (for example, "C:\"). If this process
starts in a subdirectory, the value of this property is the drive and
subdirectory path, without a trailing slash (for example,
"C:\mySubDirectory").

Related

How can I fix this DirectoryNotFoundException?

I have a DirectoryNotFoundException on a .txt file if I use the full path it's working but I don't want to use the full path because I want the program work no matter where it is placed (compatibilty with the maximum of computer)
Here's my code
private void SaveClose_Click(object sender, RoutedEventArgs e)
{
if (Windowed.IsChecked == true)
windowed = true;
else
windowed = false;
string textWriteWindowed;
if (windowed == true)
{
textWriteWindowed = "-screen-fullscreen 0" + Environment.NewLine;
}
else
{
textWriteWindowed = "-screen-fullscreen 1" + Environment.NewLine;
}
var selectedResolution = ResolutionBox.SelectedItem.ToString();
var split = selectedResolution.Split('x');
widthChoose = Int32.Parse(split[0]);
heightChoose = Int32.Parse(split[1]);
string textWriteWidth;
textWriteWidth = "-screen-width " + widthChoose + Environment.NewLine;
string textWriteHeight;
textWriteHeight = "-screen-height " + heightChoose + Environment.NewLine;
File.WriteAllText(#"\Resources\arguments.txt", textWriteWindowed);
File.AppendAllText(#"\Resources\arguments.txt", textWriteWidth);
File.AppendAllText(#"\Resources\arguments.txt", textWriteHeight);
this.Close();
}
The first argument of File.WriteAllText takes a path as input. Whatever you have mentioned is not the absolute path but it is just the relative path of the file. WriteAllText creates the file but doesn't create the directory by itself. So something like:
File.WriteAllText(#"\arguments.txt", textWriteWindowed);
shall work (and create the file in the respective drive), but
File.WriteAllText(#"\Resources\arguments.txt", textWriteWindowed);
shall not work. Hence, if you want to create a file in the path where the application resides, you can do something like:
string folder=Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
File.WriteAllText(#"\arguments2.txt", "ABC");
If you want to create a directory, then you could do something like:
System.IO.FileInfo file = new System.IO.FileInfo(filePath);
file.Directory.Create();// If the directory already exists, this method does nothing.
System.IO.File.WriteAllText(file.FullName, textWriteWindowed);
Hope this answers your query.
you have to check whether the folder is exist before save the file,
if folder not exist create it using
Directory.CreateDirectory(...)
Directory.Exists(..)
you can use to check folder existence
IF you wanted to get the local path of the file you are executing use this:
var fInfo = new FileInfo(System.Reflection.Assembly.GetCallingAssembly().Location);
From there, you would do the following:
var parentDir = new DirectoryInfo(fInfo.DirectoryName);
var subDir = new DirectoryInfo(parentDir.FullName + "Resource");
if(!subDir.Exists)
subDir.Create();
This would ensure that you always have a folder in the directory of your executable. But just so you know, this is absolutely horrible code and should never ever be implemented in a production like environment. What if some knucklehead sysAdmin decides to place your program/folder in an area that the current user does not have access/writes too? The best place to write to is %APPDATA%, this will ensure the user always has read/write permissions to what you are trying to accomplish.
I don't know how but doing that worked for me :
File.WriteAllText(#"./arguments.txt", textWriteWindowed);
File.AppendAllText(#"./arguments.txt", textWriteWidth);
File.AppendAllText(#"./arguments.txt", textWriteHeight);

How do I get the folder for the currently open file in c#

I am writing a wizard that pulls information from a database like file. This wizard doesn't get compiled, it just runs on command. I am not sure the correct term for that.
The issue is, I need to enter more information which will manipulate the database, and I want to store the values into a csv file that I use to manipulate the database.
So the question is: How do I get the folder for the currently open file in a c# application so that I can save a csv file to that folder?
edit: The path needs to be dynamic. Each database file is stored in a separate folder. I need the wizard to save to which ever folder I just opened the file from.
edit2 :
I am not opening the file programmatically. The file is being open by the user in the application. So, the user opens a file, and a bunch of database information is displayed. He then runs a wizard on that data where he can enter some coefficients, etc .. and that will change the information in the database file. I need to be able to store the coefficients he enters into the folder that contains the database file that he opened. I cannot access / change the application code, only the wizard code.
Thanks
Something like this?
var file = "C:\\Users\\Me\\Desktop\\Test.txt";
var fileLocation = file.Substring(0, file.LastIndexOf("\\"));
You can use this:
string path = Path.GetFullPath(Directory.GetCurrentDirectory()).TrimEnd(Path.DirectorySeparatorChar);
string directoryName = Path.GetFileName(path);
I found this solution in this thread
Get the (last part of) current directory name in C#
Try
//Or where ever the database returns the file is stored
var filename = "C:\\Temp\\File\\Test.txt";
var path = System.IO.Path.GetDirectoryName(filename);
Should return C:\Temp\File
Source : https://msdn.microsoft.com/en-us/library/system.io.path.getdirectoryname(v=vs.110).aspx
Try using DirectoryInfo to get information about any directory:
using System;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
if (di != null)
{
FileInfo[] subFiles = di.GetFiles();
if (subFiles.Length > 0)
{
Console.WriteLine("Files:");
foreach (FileInfo subFile in subFiles)
{
Console.WriteLine(" " + subFile.Name + " (" + subFile.Length + " bytes) " + "Directory name: "
+ di.Name + " Directory full name: " + di.FullName);
}
}
Console.ReadKey();
}
}
}
}

Upload file to subdirectory with specific name when subdirectories don't exist?

Maybe this is a four-part question:
Upload to subdirectory/ies
Subdirectories don't exist
Use different remote filename than local file
Subdirectories should have explicit permissions (similar to root problem in WinSCP .NET assembly - How to set folder permissions after creating directory?)
Attempted:
var localPath = Path.GetTempFileName();
var remoteFolder = "/some/directory/beneath/root";
var slash = "/"; // maybe given as '/' or '\'...
var remotePath = remoteFolder + slash + "destination.ext1.ext2.txt";
var session = new Session(sessionOptions);
var result = session.PutFiles(localPath, remotePath, false, new FileTransferOptions { FilePermissions = new FilePermissions { Octal = "700" }, KeepTimestamp..., etc });
result.Check();
throws exception Cannot create remote file '/some/directory/beneath/root/destination.ext1.ext2.txt'. ---> WinSCP.SessionRemoteException: No such file or directory.
I was finally able to make the subdirectories with the correct permissions via the crazy workaround indicated here by creating the subdirectory structure in my temp path and using PutFiles on the first folder:
var tempRoot = Path.GetTempPath();
var tempPath = Path.Combine(tempRoot, remoteFolder);
Directory.CreateDirectory(tempPath);
// only need to upload the first segment, PutFiles will magically grab the subfolders too...
var segment = remoteFolder.Substring(0, remoteFolder.IndexOf(slash, StringComparison.Ordinal));
if( !this.DoesFolderExist(segment) )
{
// here's the workaround...
try
{
this._session.PutFiles(Path.Combine(tempRoot, segment), segment, false, new TransferOptions { FilePermissions = this._transferOptions.FilePermissions }).Check();
}
catch (InvalidOperationException)
{
// workaround for bug in .NET assembly prior to 5.5.5/5.6.1 beta
// although I never hit this catch, maybe I've got a new enough version?
}
}
Directory.Delete(tempPath); // finish workaround
but this was way too unintuitive.
ad 1) WinSCP does not (generally) create the target directory of the upload. It must exist prior to the upload. You can test the existence using the Session.FileExists and create the directory using the Session.CreateDirectory, if not. WinSCP, of course, creates the directories you are uploading, if needed.
ad 3) You specify different target name in the remotePath argument of the Session.PutFiles:
session.PutFiles(#"C:\path\original.txt", "/home/user/newname.txt");
ad 4) You specify permissions of uploaded file/directory using the TransferOptions.FilePermissions. Note that WinSCP implicitly adds x permission to directories for every group, where r permission is granted. So when you specify 600 permissions for batch upload, the 600 is used for files, while 700 is used for directories. If you need to use different permissions for different files/directories, you need to upload them one by one.

rename directory(error Could not find a part of the path.)

string sourceDir = #"E:\Images\3\2\1";
string destDir = #"E:\Images\33\22\11";
Directory.Move(sourceDir, destinationDir);
I have to rename directory I use Directory.Move() but gives me error:
Could not find a part of the path.
Folder, to which you are moving, should exist before you move.
Call Directory.Create([path to target folder]) before Directory.Move
It seems that in string destDir = #"E:\Images\33\22\11"; Images\33\22\ does not exist. You cannot create new subdirectories using Directory.Move, so E:\Images\33\22\ must already exist.
See MSDN.
You will need to make sure that the location you are moving the folder to aleady exists. To make it easy you could do something like the following.
Basically you need to make sure that the path where you are moving the file to exists.
string sourceDir = #"E:\Images\3\2\1";
string destName = "1";
string destDir = #"E:\Images\33\22\";
Directory.CreateDirectory(destDir); // Create the location path
Directory.Move(sourceDir, Path.Combine(destDir + destName));
Edit: Added basic error handling.
This is an example with basic error handling to make sure that both the source and destination directory exists.
string sourceDir = #"E:\Images\3\2\1";
string destName = "1";
string destDir = #"E:\Images\33\22\";
if (!Directory.Exists(sourceDir))
{
Console.WriteLine("Source Directory does not exist.");
Console.Read();
//return; // Handle issue where Source Dir does not exist.
}
if (!Directory.Exists(destDir))
{
Console.WriteLine("Destination Directory does exist. Created.");
Directory.CreateDirectory(destDir);
}
if (Directory.Exists(Path.Combine(destDir + destName)))
{
Console.WriteLine("Target Destination already exist.");
Console.Read();
return;
}
Directory.Move(sourceDir, Path.Combine(destDir + destName));
Console.Read();

Checking File Path When Deleting A File

If I have a web method that deletes a file when called and it accepts three parameters (cNum, year, and fileName). Do I need to be worried about exploits of this method. The only thing I could think of would be using ..\..\..\ to drive the delete further up the folder structure. that should be pretty easy to remove that. But is there anything else that I should be worried about?
[WebMethod(EnableSession = true,
Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
try
{
if (String.IsNullOrEmpty(cNum)
|| String.IsNullOrEmpty(year)
|| String.IsNullOrEmpty(fileName))
throw new Exception();
string path = Server.MapPath(#"~\docs\custFiles\"
+ year + #"\"
+ cNum + #"\" + fileName);
File.Delete(path);
}
catch
{
throw new Exception("Unable to delete file");
}
return true;
}
I would recommend using the GetFileName method on the Path class to cleanse the filename parameter, like so:
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
// Cleanse fileName.
fileName = Path.GetFileName(fileName);
The GetFileName method strips all directory information from a path, which is exactly what you want to do here.
With input like:
..\..\..\filename.ext
You would get:
filename.ext
In return, you don't have to worry about someone injecting a path which would escape the directory that you are targeting (assuming that this filename is user-input or from an open endpoint where someone could enter any input they want).
This then allows you to then append your custom path to fileName.
This only works of course if all of your files are in a pre-defined directory, which it seems it is.
This does not however, do anything to handle deleting files that a user doesn't have access to. If the files belong to another user in that directory, then there's no check here to see if that's the case (but if all users have rights to delete these files, then it's ok).
Also, you might want to use the Combine method on the Path class to combine your paths, like so:
string path = Server.MapPath(#"~\docs\custFiles\")
path = Path.Combine(path, year);
path = Path.Combine(path, cNum);
path = Path.Combine(path, fileName);
If you're using .NET 4.0 or above, you can use the overload of the Combine method that takes the parts of the path as a parameter array:
string path = Path.Combine(
Server.MapPath(#"~\docs\custFiles\"),
year, cNum, fileName);
Finally, as Shai points out, if possible (for a complete solution), to make this even more secure you should be enabling permissions on the file-system level.
If you are impersonating the user or using a constrained user account to handle all of the requests, then you should grant that user access to just the ~\docs\custFiles\ directory (and any sub directories).
Anything above that directory the user account should have no access to.
It is a good idea to check the file names and directory names if they are valid file names or not, check them against this char array:
Path.GetInvalidFileNameChars
EDIT:
And you should probably also validate the year and number like this:
bool valid = int.TryParse(num, out temp);
You may also want to consider using built in security on the file system to prevent users from deleting files in unwanted directories. If the web app is running under a specific user that has rights to delete files in only one directory, no matter what the user tries, the app will not have the rights to perform the delete.
In addition, this would make maintenance (ie: adding new directories) pretty easy without redeploying the app.
You could then catch the attempt to access the invalid access attempt and do something with it if you so desire.
[WebMethod(EnableSession = true,
Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
try
{
if (String.IsNullOrEmpty(cNum) || String.IsNullOrEmpty(year) ||
String.IsNullOrEmpty(fileName))
throw new Exception();
string path =
Server.MapPath(#"~\docs\custFiles\" + year + #"\" + cNum +
#"\" + fileName);
File.Delete(path);
}
catch (System.Security.SecurityException e)
{
throw new Exception("Unauthorized attempt to delete file");
}
catch
{
throw new Exception("Unable to delete file");
}
return true;
}

Categories

Resources