In my WinForm I would like to copy/overwrite files.
When the destination file does not exist, the file gets created OK. When the file already exists, it never gets overwriten. Path is on my local computer.
There are no exceptions thrown, and I gave full access to "Everyone". Same issue with FileInfo. Only when I delete the file first it gets created!
My Code:
//File.Delete(path + "gauche.png");
try
{
// FileInfo fi = new FileInfo(Path.Combine(path, Num_Gauche.Value + ".png"));
//fi.CopyTo(Path.Combine(path, "gauche.png"), true);
File.Copy(Path.Combine(path, Num_Gauche.Value + ".png"), Path.Combine(path, "gauche.png"), true);
}
catch (Exception ex )
{
Console.WriteLine(ex.Message);
throw;
}
It could be an ownership issue. If the file was created by another user, your process may not be able to overwrite it. Usually like if the file was created by a installer/MSI that you may have issue to overwrite it by another process.
I will just enable that piece of code to delete the file prior to create it if that works.
Related
As a short summary, I have a string constant for a file location that includes the file name and extension such as #"C:\foldername\subfolder\filename.json. When calling File.Create from System.IO, it's creating a directory rather than the file maybe 5% of the time.
Does anyone have any insight as to what needs done different to prevent this?
if (File.Exists(fileName))
{
return File.GetLastWriteTime(fileName);
}
else
{
try
{
File.Create(fileName).Close();
return File.GetLastWriteTime(fileName);
}
catch (Exception ex)
{
Logging.sharedLogging.Log(SharedLogging.LoggingLevel.Error, "[CacheDirectoryLogic.GetOverridesLastWriteTime] Failed to create Override.json. Reason: " + ex.Message);
return null;
}
}
where fileName is #"C:\WD\Data\Cache\Override.json";
I think there should be some exception thrown, but your catch block will just log somewhere and ignore the error, so you may want to check your logger to see any exception mentioned. It will be helpful for us to understand the issue.
There are few possible root causes for the issue.
1. Permission issue
I notice the file path is in C drive. If the directory requires admin privilege to write files in the folder, it may throw access denied exception.
Tried to change the file path to D drive, which less likely has admin privilege restriction.
2. Directory is not fully created
Better practice for file creation with a full path -- check for directory existence before creating the file.
File.Create() does not create directory automatically. And it will throw error if directory is not found.
Code sample:
var directory = #"C:\WD\Data\Cache\";
var fileName = Path.Combine(directory, "Override.json");
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (File.Exists(fileName))
...
file.CopyTo(destinationFullName , true);
if (destinationFullName == file.FullName) {
logTrace(TraceEventType.Information, "Overwritten file " + file.FullName + " with " + destinationFullName);
}
Is there a good way to detect if a file is being overwritten instead of manually comparing file name of source and destination. I was like to log a message if CopyTo overwrites a file.
If you don't want to check if the file exists before you try to copy, you could use the File.Copy() method where it says right in the documentation that overwriting a file is not allowed:
Copies an existing file to a new file. Overwriting a file of the same name is not allowed.
...
IOException
destFileName exists.
So you could put the Copy in a try, and then catch an IOException that would indicate that the file already exists. See the link I pasted for more information.
I am sure you have a good reason for not wanting to check for the existence of the file in advance. I don't normally recommend using a try catch block like this though.
I have done a ton of research on MSDN and SO but there seem to be a lot of mixed reviews on this topic and no straightforward answer. My UWP app needs to download some items for the user. It seems only logical that this goes into the "downloads" folder instead of Documents or Pictures.
What I gather from my reading is that an application is allowed to access the downloads folder and create files and sub folders within the downloads folder. However, it cannot access other files and folder (not created from your app) without the use of a picker. In this case, I should not need to use a picker because my app is using the and creating the folder for itself. I have also read, there is not need for special capabilities in the Manifest for this to work.
I can confirm that this does in fact work by creating a folder and a file in the downloads folder
StorageFile destinationFile;
StorageFolder downloadsFolder;
try
{
//Create a sub folder in downloads
try
{
downloadsFolder = await DownloadsFolder.CreateFolderAsync("AppFiles");
}
catch (Exception ex)
{
//HERE IS THE ISSUE. I get in here if the folder exists but how do i get it?
}
destinationFile = await downloadsFolder.CreateFileAsync(destination,CreationCollisionOption.GenerateUniqueName);
}
catch (FileNotFoundException ex)
{
rootPage.NotifyUser("Error while creating file: " + ex.Message, NotifyType.ErrorMessage);
return;
}
However, here is the major issue. This code works fine the first time through because the folder does not already exist and it creates it along with the file. Subsequent times through, it fails and throws an exception:
Cannot create a file when that file already exists. (Exception from HRESULT: 0x800700B7)
It does this on the line to create the folder in Downloads folder:
downloadsFolder = await DownloadsFolder.CreateFolderAsync("AppFiles");
The problem is that MSDN states that I cannot use the Collision options of "OpenIfExists" or "ReplaceExisting" which are the two collision options I would need to solve this problem. The two remaining options do no good for me. So, no matter what, it is going to throw an exception if the folder exists.
Then, the thought is that I could just catch the exception, like I am already doing in my snippet above and open the folder if it exists. The problem with this is that the "DownloadsFolder" class does not give any options to get or open a folder, only to create a folder.
So, it seems I can create the folder from my app but I cannot open or get the folder that my app created?
Thanks!
The problem with this is that the "DownloadsFolder" class does not give any options to get or open a folder, only to create a folder.
Actually, When you first run your code, you could create your folder successfully and get the folder instance to create file in this folder. But why you could not get it when it's existed, it's by design.
I believe you have checked the document:
Because the app can only access folders in the Downloads folder that it created, you can't specify OpenIfExists or ReplaceExisting for this parameter.
So, How to get the folder that you created? I will tell you in the following:)
In this case, I should not need to use a picker because my app is using the and creating the folder for itself.
As you said, the first option is to use a picker, but you've said that you do not want to use a picker. Then, I will give you another option.
When you first create the folder successfully, you could add this folder to the FutureAccessList. Then, you could get this folder directly in your code.
I've made a simple code sample for your reference:
StorageFile destinationFile;
StorageFolder downloadsFolder;
try
{
try
{
downloadsFolder = await DownloadsFolder.CreateFolderAsync("AppFiles");
string folderToken = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(downloadsFolder);
ApplicationData.Current.LocalSettings.Values["folderToken"] = folderToken;
destinationFile = await downloadsFolder.CreateFileAsync("destination.txt", CreationCollisionOption.GenerateUniqueName);
}
catch (Exception ex)
{
if (ApplicationData.Current.LocalSettings.Values["folderToken"] != null)
{
string token = ApplicationData.Current.LocalSettings.Values["folderToken"].ToString();
downloadsFolder = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFolderAsync(token);
destinationFile = await downloadsFolder.CreateFileAsync("destination.txt", CreationCollisionOption.GenerateUniqueName);
}
}
}
catch (FileNotFoundException ex)
{
rootPage.NotifyUser("Error while creating file: " + ex.Message, NotifyType.ErrorMessage);
return;
}
I'm trying to write a small console app tool that unzips an archive containing multiple files/folders/other archives and arrange it's contents in another way.
I unzip the root file with ZipFile.ExtractToDirectory method from System.IO.Compression.FileSystem library:
public static void UnzipPackage(string packagePath, string targetPath)
{
try
{
ZipFile.ExtractToDirectory(packagePath, targetLocation);
Console.WriteLine("Unzipping file {0} complete.", packagePath);
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("Directory was not found.");
}
catch (FileNotFoundException)
{
Console.WriteLine("File was not found.");
}
}
After running this method on my package, I want to copy a file which was in this package in a subfolder.
According to MSDN I do this:
if (!Directory.Exists(targetLocation + #"READY\PHOTO"))
{
Directory.CreateDirectory(targetLocation + #"\READY\PHOTO");
}
if (Directory.Exists(targetLocation + #"\MAIN\PHOTO"))
{
string[] files = Directory.GetFiles(targetLocation + #"\MAIN\PHOTO");
foreach (var file in files)
{
string fileName = Path.GetFileName(file);
string destFile = Path.Combine(targetLocation + #"\MAIN\PHOTO", fileName);
File.Copy(file, destFile, true);
}
}
Both MAIN and READY are my subdirectories where whole package goes ("main") and sorted files go ("ready").
However, when running this, the zip file is not yet unzipped - an exception occurs showing it can't access the file specified even though it grabbed it's name from Directory.GetFiles(). The folder created when unzipping the zip file shows only after I terminate my console app (no wonder it can't access it).
So the big question is - how can I wait for the unzipped folder to show up? I tried using Thread.Sleep(), but it doesn't affect the flow anyhow - an exception still occurs, and the folder shows only after I terminate the app.
Your error is here:
string destFile = Path.Combine(targetLocation + #"\MAIN\PHOTO", fileName);
Should be:
string destFile = Path.Combine(targetLocation + #"\READY\PHOTO", fileName);
You're attempting to copy the file to the same location.
I'm assuming your getting an IOException something like "The process cannot access the file...because it is being used by another process."
It looks to me that there is a problem in your copy method. It looks like your from and to paths are essentially the same. So the system cannot overwrite the file, because you currently have it open for reading.
Just to be clear - the issue is not related to unzipping! In the example you have written the variable file and destFile are going to be the same - and they need to be different.
During the execution of this script it is not detected any error, but the file isn't modified. Reading works, writing strangely not.
My script for writing:
private void firstLaunch(){
try {
StreamWriter outfile = new StreamWriter("Path/something.txt");
outfile.WriteLine("somethingElse");
outfile.Close();
}
catch (IOException ex){
MessageBox.Show(ex.Message);
}
}
The file already exists and has already been included in the project with visual studio. At the moment it is completely empty.
Could you help me?
You can use something like this:
var res = App.GetResourceStream(new Uri("test.txt", UriKind.Relative));
var txt = new StreamReader(res.Stream).ReadToEnd();
Just make sure that the file has the Build Action set to Content.
If the file is empty, I would recommend creating one in the folder of your app using IsolatedStorage. That way you can check with IsoStoreSpy the contents of your file.