I am trying to use DirectoryInfo.MoveTo() to rename a directory that I have just extracted a Zip archive to. Most of the time the operation throws an IOException with the error Access to the path '...' is denied.. Occasionally, the operation works, but I haven't been able to correlate any condition that supports this. I've checked many forum posts and StackOverflow questions about this same error but I still cannot get this working. I'm sure its not computer permissions. All of these files and folders have full read/write permissions and I have tried running the program as an administrator.
Here is my code:
// Compute directory names
string directoryPathWithPrefix = Path.Combine(this.OutputDirectory.FullName,
"TEMP_ " + Path.GetFileNameWithoutExtension(compressedData.FullName));
string directoryPathWithoutPrefix = Path.Combine(this.OutputDirectory.FullName,
Path.GetFileNameWithoutExtension(compressedData.FullName));
// Extract file to new directory
ZipFile.ExtractToDirectory(compressedData.FullName, directoryPathWithPrefix);
// Add tag for UploadId
File.Create(Path.Combine(directoryPathWithPrefix,
upload.UploadId.ToString() + ".UPLOADID")).Close();
// Rename file
DirectoryInfo oldDir = new DirectoryInfo(directoryPathWithPrefix);
oldDir.MoveTo(directoryPathWithoutPrefix);
I've tried using Process Explorer to monitor the handle for the directory, but haven't been able to find any useful data from it. Using Directory.Move() or creating a ZipArchive object inside a using block still raise the error as well.
I'm really stumped on this one. Please help.
Clarification:
I'm running Windows 7 and this program is built under .NET 4.5
Here is the error I am receiving:
System.IO.IOException occurred
HResult=-2146232800
Message=Access to the path '{PATH}' is denied.
Source=mscorlib
StackTrace:
at System.IO.DirectoryInfo.MoveTo(String destDirName)
at DataImporter.ImportFDUU(FileSystemInfo uploadToImport, Message& reportMessage) in {CODE FILE}:line 380
InnerException:
Running cacls on the directory returns this information:
BUILTIN\Administrators:(OI)(CI)F
{MY USER}:(OI)(CI)F
I finally figured out the issue. Some strange glitch exists with ZipFile.ExtractToDirectory() that doesn't release access to a file in the directory when it is finished extracting. To get around this I changed my code as follows:
Extract the files to a temporary directory.
Copy the files from the temporary directory to the destination directory
Delete the temporary directory
// Compute directory names
string directoryPathWithPrefix = Path.Combine(this.SeparatorInputDirectory.FullName,
"TEMP_ " + Path.GetFileNameWithoutExtension(compressedFlightData.FullName));
string directoryPathWithoutPrefix = Path.Combine(this.SeparatorInputDirectory.FullName,
Path.GetFileNameWithoutExtension(compressedFlightData.FullName));
string tempDirectoryPath = Path.Combine(TempDirectoryPath, Path.GetDirectoryName(directoryPathWithoutPrefix));
// Extract file to new directory in the separator input directory
ZipFile.ExtractToDirectory(compressedFlightData.FullName, tempDirectoryPath);
// Add tag for UploadId
File.Create(Path.Combine(tempDirectoryPath,
upload.UploadId.ToString() + ".UPLOADID")).Close();
// Rename file to trigger separation
DirectoryCopy(tempDirectoryPath, directoryPathWithPrefix);
Directory.Move(directoryPathWithPrefix, directoryPathWithoutPrefix);
public static void DirectoryCopy(string sourceDirName, string destDirName)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string tempPath = Path.Combine(destDirName, file.Name);
file.CopyTo(tempPath, false);
}
// Copy subdirectories and their contents to new location.
foreach (DirectoryInfo subDir in dirs)
{
string tempPath = Path.Combine(destDirName, subDir.Name);
DirectoryCopy(subDir.FullName, tempPath);
}
}
Related
Using .NET Core 3.1 and C#, I'm trying to move a directory (including all subdirectories and files) to another directory. The destination directory may contain folders and files that already exist with the same name as the source directory, for example "source/folder/file.txt" may already exist in "destination/folder/file.txt" but I would like to overwrite everything in the destination directory.
The error I am getting is "System.IO.IOException: Cannot create a file when that file already exists.", however I am deleting the file that already exists in the destination before moving the file from the source (File.Delete before File.Move), so I don't understand why I am getting this error. Also to add, I am not able to reproduce this error 100% of the time for some reason.
This is the code I am using to move a directory (lines 137 - 155):
public static void MoveDirectory(string source, string target)
{
var sourcePath = source.TrimEnd('\\', ' ');
var targetPath = target.TrimEnd('\\', ' ');
var files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories)
.GroupBy(s => Path.GetDirectoryName(s));
foreach (var folder in files)
{
var targetFolder = folder.Key.Replace(sourcePath, targetPath);
Directory.CreateDirectory(targetFolder);
foreach (var file in folder)
{
var targetFile = Path.Combine(targetFolder, Path.GetFileName(file));
if (File.Exists(targetFile)) File.Delete(targetFile);
File.Move(file, targetFile);
}
}
Directory.Delete(source, true);
}
This is the stack trace of my error:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.IOException: Cannot create a file when that file already exists.
at System.IO.FileSystem.MoveFile(String sourceFullPath, String destFullPath, Boolean overwrite)
at Module_Installer.Classes.Bitbucket.MoveDirectory(String source, String target) in F:\git\module-installer\module-installer\Module Installer\Classes\Bitbucket.cs:line 147
at Module_Installer.Classes.Bitbucket.DownloadModuleFiles(Module module, String username, String password, String workspace, String repository, String commitHash, String versionNumber, String downloadDirectory, String installDirectory) in F:\git\module-installer\module-installer\Module Installer\Classes\Bitbucket.cs:line 113
at Module_Installer.Classes.OvernightInstall.ProcessInstalledModule(TenantModule tenantModule, Boolean skipBackup) in F:\git\module-installer\module-installer\Module Installer\Classes\OvernightInstall.cs:line 393
at Module_Installer.Classes.OvernightInstall.Run(Boolean skipBackup) in F:\git\module-installer\module-installer\Module Installer\Classes\OvernightInstall.cs:line 75
at Module_Installer.Program.Main(String[] args) in F:\git\module-installer\module-installer\Module Installer\Program.cs:line 40
This error is happening when I am running the application via Windows Task Scheduler, which I have set to run at 03:30am every day, I have specified that the task should "Start In" the same folder as where the EXE is located.
Any suggestions would be appreciated, thanks!
Instead of deleting existing files in the target directory try to overwrite them using File.Move(file, targetFile, overwrite: true).
By the way there is an MSDN example on how to copy directories. It's not exactly your use case, but could be helpful anyway.
I fetch a path from the Web.config file:
<appSettings>
<add key="Server" value="http://admin.xxxxxxx.com/1upload/*All File And Folder Copy this directory *"/>
<add key="Local" value="C:\\Users\\IND_COM\\Desktop\\xxxx\\1upload\\paste The Copyed File"/>
</appSettings>
In the button click event I pass the source and destination path:
protected void btnUpdate_Click(object sender, EventArgs e)
{
string Source_path = ConfigurationManager.AppSettings["server"].ToString();
string Detination_Path = "#" + ConfigurationManager.AppSettings["Local"].ToString();
DirectoryCopy(Source_path, Detination_Path, true);
}
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
DirectoryInfo dir = new DirectoryInfo(sourceDirName);//Exception Through In this Section..
if (!dir.Exists)
{
throw new DirectoryNotFoundException("Source directory does not exist or could not be found: "+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
On my hosting server, I have a folder and all images and XML saved in different folders. For example, I have 1 directory named 1Upload. Inside this directory I have 3 sub-directories and each has different files. I try to copy all 3 directories and files from the Server. This piece of code gives an exception
URI is not supported
HTTP is not a file system.
What you're looking to do is not to perform a file system copy operation, but rather to download the content from the web and save it to your file system. For this, you want something like the WebClient.DownloadFile() method.
For example:
var client = new WebClient();
client.DownloadFile(sourceURL, destinationFile);
Each file would be a separate request. You're currently trying to list directory contents of a website, which clearly won't work (because HTTP isn't a file system). However you build your list of files, once you have that list you can loop over it and call DownloadFile(source, destination) for each file.
If you need the website to provide a list of files, you have to add that functionality to the website (if it's not already there, we don't know). If you need to download all of the files in one operation, then the website would need to provide them in a single file (such as a .zip file).
Trying to copy all files/directories inside a directory to a new location that I create.
Users select the 'backup drive' to work with to in a combobox, then when they click the backup desktop button it simply creates a backup directory on that drive and copies all the files into that directory.
The backup directory gets created on the drive appropriately - but the first file it hits it kicks off an error.
private void backupDesktopButton_Click(object sender, EventArgs e)
{
//set the destionationLocation to the selectedDrive
string selectedDrive = backupDriveCombo.SelectedItem.ToString();
string destinationLocation = selectedDrive+"Backups-" + DateTime.Now.Month.ToString()+"-"+DateTime.Now.Year.ToString()+"\\Desktop\\";
if (!Directory.Exists(destinationLocation))
{
Directory.CreateDirectory(destinationLocation);
}
string desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
string[] fileList = Directory.GetFiles(desktopFolder);
foreach (string file in fileList)
{
//move the file
File.Copy(file, destinationLocation);
}
}
I get the error:
IOException was unhandled.
The filename, directory name, or volume label syntax is incorrect.
In the 'Autos' window (VS2010) I see the locations are set correctly:
destinationLocation = the appropriate directory (C:\Backups-8-2016\Desktop\)
file = the appropriate first file (C:\Users\myusername\Desktop\myshortcut.url)
What am I missing? I have all rights to be able to copy/paste/create things and the directory to store it gets created - just a problem moving the file.
From the documentation https://msdn.microsoft.com/en-us/library/c6cfw35a(v=vs.110).aspx
the second parameter:
The name of the destination file. This cannot be a directory or an existing file.
you need to concat the filename to the folder.
Try something like this
string[] fileList = Directory.GetFiles(desktopFolder);
foreach (string file in fileList)
{
string targetFile = Path.Combine(destinationLocation, Path.GetFileName(file));
if (File.Exists(targetFile)) File.Delete(targetFile);
File.Copy(file, targetFile);
}
I'm making a small application that have to take all the files from a shared folder and copy them in the current folder(the once from where the application it's runned).
One month ago this code was fine:
string seprin_address = #"\\PC-SEPRIN\2port\";
SimpleCopy(seprin_address);
public void SimpleCopy(string sourcePath){
try{
string fileName = "";
string targetPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
bool path = false;
string real_target = "";
for(int i = 0; i < targetPath.Length; i++){
if(targetPath[i] == 'C'){
path = true;
}
if(path){
real_target += targetPath[i];
}
}
// Use Path class to manipulate file and directory paths.
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath, fileName);
// To copy a folder's contents to a new location:
// Create a new target folder, if necessary.
/*if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
}*/
// To copy a file to another location and
// overwrite the destination file if it already exists.
//System.IO.File.Copy(sourceFile, destFile, true);
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
else
{
MessageBox.Show("Error");
}
// Keep console window open in debug mode.
}
catch(Exception e_p){
lbabel.Text = e_p.Message;
}
}
Now i get the "URI not supported error" when the file.copy it's called.
I think its supernatural but if you have any other ideas i'm all ears.
I would find out if the URI not supported is complaining about source or destination. I would also check to make sure the user that this is running as has permission to the directories in question. Could the users permissions have changed? I have had occasion where I had jobs in scheduled tasks where the user was set and later the password was changed for the user but not on the scheduled task. The same could be true if this is written as a service with a specific user.
as you are saying it was working fine one month ago, there can be two possibilities which is restricting you from accessing the Path.
1.Remote PC Hostname PC-SEPRIN might havebeen changed.Please check the remote pc hostname.
2.check the Shared Folder 2port path properly.
if somebody changes shared folder name or deletes it, you can not access it.
and also please check whether you have permissions to access it or not.
I am trying to create a directory and subdirectories and copy files from on one location to another location. The following code works but it doesn't create a parent directory(10_new) if there are sub directories. I am trying to copy all the contents(including subdirectories) from "c:\\sourceLoc\\10" to "c:\\destLoc\\10_new" folder. If "10_new" doesn't exist then I should create this folder. Please assist.
string sourceLoc = "c:\\sourceLoc\\10";
string destLoc = "c:\\destLoc\\10_new";
foreach (string dirPath in Directory.GetDirectories(sourceLoc, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourceLoc, destLoc));
if (Directory.Exists(sourceLoc))
{
//Copy all the files
foreach (string newPath in Directory.GetFiles(sourceLoc, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(sourceLoc, destLoc));
}
}
From looking at your code, you never check for the existence of the parent folders. You jump to getting all the child folders first.
if (!Directory.Exists(#"C:\my\dir")) Directory.CreateDirectory(#"C:\my\dir");
Here is how to copy all files in a directory to another directory
This is taken from http://msdn.microsoft.com/en-us/library/cc148994.aspx
string sourcePath = "c:\\sourceLoc\\10";
string targetPath = "c:\\destLoc\\10_new";
string fileName = string.Empty;
string destFile = string.Empty;
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
else
{
Console.WriteLine("Source path does not exist!");
}
Recursive Directory/Sub-directory
public class RecursiveFileSearch
{
static System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection();
static void Main()
{
// Start with drives if you have to search the entire computer.
string[] drives = System.Environment.GetLogicalDrives();
foreach (string dr in drives)
{
System.IO.DriveInfo di = new System.IO.DriveInfo(dr);
// Here we skip the drive if it is not ready to be read. This
// is not necessarily the appropriate action in all scenarios.
if (!di.IsReady)
{
Console.WriteLine("The drive {0} could not be read", di.Name);
continue;
}
System.IO.DirectoryInfo rootDir = di.RootDirectory;
WalkDirectoryTree(rootDir);
}
// Write out all the files that could not be processed.
Console.WriteLine("Files with restricted access:");
foreach (string s in log)
{
Console.WriteLine(s);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key");
Console.ReadKey();
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
// First, process all the files directly under this folder
try
{
files = root.GetFiles("*.*");
}
// This is thrown if even one of the files requires permissions greater
// than the application provides.
catch (UnauthorizedAccessException e)
{
// This code just writes out the message and continues to recurse.
// You may decide to do something different here. For example, you
// can try to elevate your privileges and access the file again.
log.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
foreach (System.IO.FileInfo fi in files)
{
// In this example, we only access the existing FileInfo object. If we
// want to open, delete or modify the file, then
// a try-catch block is required here to handle the case
// where the file has been deleted since the call to TraverseTree().
Console.WriteLine(fi.FullName);
}
// Now find all the subdirectories under this directory.
subDirs = root.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
// Resursive call for each subdirectory.
WalkDirectoryTree(dirInfo);
}
}
}
}
Before doing File.Copy, check to make sure the folder exists. If it doesn't create it.
This function will check if a path exists, if it doesnt, it will create it. If it fails to create it, for what ever reason, it will return false. Otherwise, true.
Private Function checkDir(ByVal path As String) As Boolean
Dim dir As New DirectoryInfo(path)
Dim exist As Boolean = True
If Not dir.Exists Then
Try
dir.Create()
Catch ex As Exception
exist = False
End Try
End If
Return exist
End Function
Remember, all .Net languages compile down to the CLR (common language runtime) so it does not matter if this is in VB.Net or C#. A good way to convert between the two is: http://converter.telerik.com/
It is impossible to copy or move files with C# in windows 7.
It will instead create a file of zero bytes.