I'm trying to extract an ISO to a folder with the same name without .iso on the end.
I'm having a problem with winrar as it will not start the extract when I start up with the seach starting in the folder with the ISO.
UPDATED with answer code
private void ExtractISO(string toExtract, string folderName)
{
// reads the ISO
CDReader Reader = new CDReader(File.Open(toExtract, FileMode.Open), true);
// passes the root directory the folder name and the folder to extract
ExtractDirectory(Reader.Root, folderName /*+ Path.GetFileNameWithoutExtension(toExtract)*/ + "\\", "");
// clears reader and frees memory
Reader.Dispose();
}
private void ExtractDirectory(DiscDirectoryInfo Dinfo, string RootPath, string PathinISO)
{
if (!string.IsNullOrWhiteSpace(PathinISO))
{
PathinISO += "\\" + Dinfo.Name;
}
RootPath += "\\" + Dinfo.Name;
AppendDirectory(RootPath);
foreach (DiscDirectoryInfo dinfo in Dinfo.GetDirectories())
{
ExtractDirectory(dinfo, RootPath, PathinISO);
}
foreach (DiscFileInfo finfo in Dinfo.GetFiles())
{
using (Stream FileStr = finfo.OpenRead())
{
using (FileStream Fs = File.Create(RootPath + "\\" + finfo.Name)) // Here you can Set the BufferSize Also e.g. File.Create(RootPath + "\\" + finfo.Name, 4 * 1024)
{
FileStr.CopyTo(Fs, 4 * 1024); // Buffer Size is 4 * 1024 but you can modify it in your code as per your need
}
}
}
}
static void AppendDirectory(string path)
{
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
catch (DirectoryNotFoundException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
catch (PathTooLongException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
}
The user selects the folder to extract (.ISO) toExtract. I then use it in the Process.Start() in the background worker. That just seems to open the mounting software and doesn't extract the ISO to the desired folder name.
Thanks in advance for your help.
Or if anyone could give me a batch to extract the ISO instead and to call it from c# passing toExtract and the folder name that would be helpful too.
Thanks
If external Class Libraries are OK!
Then use SevenZipSharp or .NET DiscUtils to extract ISO's...
These two ClassLibraries can manage ISO and Extract them!
For DiscUtils you can find some codes for ISO Management [CDReader Class] at the Link I provided.
But For SevenZipSharp, Please Explore the ClassLibrary source and find the Code to Extract or Google to find it!
To get the Name of the folder just use Path.GetFileNameWithoutExtension((string)ISOFileName) which will return "ISOFile" for an iso named "ISOFile.iso". And then you can use it with your desired path.
UPDATE
Code To Extract ISO Image with DiscUtils :
using DiscUtils;
using DiscUtils.Iso9660;
void ExtractISO(string ISOName, string ExtractionPath)
{
using (FileStream ISOStream = File.Open(ISOName, FileMode.Open))
{
CDReader Reader = new CDReader(ISOStream, true, true);
ExtractDirectory(Reader.Root, ExtractionPath + Path.GetFileNameWithoutExtension(ISOName) + "\\", "");
Reader.Dispose();
}
}
void ExtractDirectory(DiscDirectoryInfo Dinfo, string RootPath, string PathinISO)
{
if (!string.IsNullOrWhiteSpace(PathinISO))
{
PathinISO += "\\" + Dinfo.Name;
}
RootPath += "\\" + Dinfo.Name;
AppendDirectory(RootPath);
foreach (DiscDirectoryInfo dinfo in Dinfo.GetDirectories())
{
ExtractDirectory(dinfo, RootPath, PathinISO);
}
foreach (DiscFileInfo finfo in Dinfo.GetFiles())
{
using (Stream FileStr = finfo.OpenRead())
{
using (FileStream Fs = File.Create(RootPath + "\\" + finfo.Name)) // Here you can Set the BufferSize Also e.g. File.Create(RootPath + "\\" + finfo.Name, 4 * 1024)
{
FileStr.CopyTo(Fs, 4 * 1024); // Buffer Size is 4 * 1024 but you can modify it in your code as per your need
}
}
}
}
static void AppendDirectory(string path)
{
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
catch (DirectoryNotFoundException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
catch (PathTooLongException Exx)
{
AppendDirectory(Path.GetDirectoryName(path));
}
}
Use It with Like This :
ExtractISO(ISOFileName, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\");
Working! Tested By Me!
And Of Course You can always add more Optimization to the code...
This Code is Just a Basic One!
For UDF or for making Windows ISO Files after servicing(DISM) with out needs the above accepted answer is not working for me so i tried this working method with DiscUtils
using DiscUtils;
public static void ReadIsoFile(string sIsoFile, string sDestinationRootPath)
{
Stream streamIsoFile = null;
try
{
streamIsoFile = new FileStream(sIsoFile, FileMode.Open);
DiscUtils.FileSystemInfo[] fsia = FileSystemManager.DetectDefaultFileSystems(streamIsoFile);
if (fsia.Length < 1)
{
MessageBox.Show("No valid disc file system detected.");
}
else
{
DiscFileSystem dfs = fsia[0].Open(streamIsoFile);
ReadIsoFolder(dfs, #"", sDestinationRootPath);
return;
}
}
finally
{
if (streamIsoFile != null)
{
streamIsoFile.Close();
}
}
}
public static void ReadIsoFolder(DiscFileSystem cdReader, string sIsoPath, string sDestinationRootPath)
{
try
{
string[] saFiles = cdReader.GetFiles(sIsoPath);
foreach (string sFile in saFiles)
{
DiscFileInfo dfiIso = cdReader.GetFileInfo(sFile);
string sDestinationPath = Path.Combine(sDestinationRootPath, dfiIso.DirectoryName.Substring(0, dfiIso.DirectoryName.Length - 1));
if (!Directory.Exists(sDestinationPath))
{
Directory.CreateDirectory(sDestinationPath);
}
string sDestinationFile = Path.Combine(sDestinationPath, dfiIso.Name);
SparseStream streamIsoFile = cdReader.OpenFile(sFile, FileMode.Open);
FileStream fsDest = new FileStream(sDestinationFile, FileMode.Create);
byte[] baData = new byte[0x4000];
while (true)
{
int nReadCount = streamIsoFile.Read(baData, 0, baData.Length);
if (nReadCount < 1)
{
break;
}
else
{
fsDest.Write(baData, 0, nReadCount);
}
}
streamIsoFile.Close();
fsDest.Close();
}
string[] saDirectories = cdReader.GetDirectories(sIsoPath);
foreach (string sDirectory in saDirectories)
{
ReadIsoFolder(cdReader, sDirectory, sDestinationRootPath);
}
return;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
it has extracted from a application source ISOReader but modified for my requirements
total source is available at http://www.java2s.com/Open-Source/CSharp_Free_CodeDownload/i/isoreader.zip
Try this:
string Desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
Process.Start("Winrar.exe", string.Format("x {0} {1}",
Desktop + "\\test.rar",
Desktop + "\\SomeFolder"));
That would extract the file test.rar to the folder SomeFolder. You can change the .rar extention to .iso, it'll work the same.
As far as I can see in your current code, there is no command given to extract a file, and no path to the file that has to be extracted. Try this example and let me know if it works =]
P.S. If you'd like to hide the extracting screen, you can set the YourProcessInfo.WindowStyle to ProcessWindowStyle.Hidden.
I hace confrunted recently with this kind of .iso extraction issue. After trying several methods, 7zip did the job for me, you just have to make sure that the latest version of 7zip is installed on your system. Maybe it will help
try
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = false;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
cmd.Start();
cmd.StandardInput.WriteLine("C:");
//Console.WriteLine(cmd.StandardOutput.Read());
cmd.StandardInput.Flush();
cmd.StandardInput.WriteLine("cd C:\\\"Program Files\"\\7-Zip\\");
//Console.WriteLine(cmd.StandardOutput.ReadToEnd());
cmd.StandardInput.Flush();
cmd.StandardInput.WriteLine(string.Format("7z x -y -o{0} {1}", source, copyISOLocation.TempIsoPath));
//Console.WriteLine(cmd.StandardOutput.ReadToEnd());
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
catch (Exception e)
{
Console.WriteLine(e.Message + "\n" + e.StackTrace);
if (e.InnerException != null)
{
Console.WriteLine(e.InnerException.Message + "\n" + e.InnerException.StackTrace);
}
}
Related
I know there are a lot of similar topics on this website, but I think that I went through most of them and still cannot debug this piece of code. I really need to get this working. I'm newbie to C# and programming. Tho, I did this same assignment in Java, but for some reason, I can't make it work here. If some could please pitch in...
So I have some objects, which I am keeping in .txt file, one line = data for one object. First data of the line is an Id of an object, primary key basically. Right now I am implementing CRUD operations, that is, an Update. This edit function is supposed to contribute to that functionality.
If a user edit some of the selected object properties, that change needs to be reflected in .txt file. So, I will go through every object/line in the file, write them to some temp.txt file, once I hit object which has same Id as the passed object o, that means I need to write that edited object to temp.txt. After that I need to rename temp.txt to original file and delete temp.txt.
I have tried bunch of options and combinations, but none worked.
I really make sure that GetTxtPath returns correct absolute path from within my project.
Version 1:
public static void edit(Transformable o, string fileName)
{
try
{
if (!File.Exists(FileUtils.GetTxtPath("temp.txt")))
{
File.Create(FileUtils.GetTxtPath("temp.txt"));
}
using (FileStream stream = File.OpenRead(FileUtils.GetTxtPath(fileName)))
using (FileStream writeStream = File.OpenWrite(FileUtils.GetTxtPath("temp.txt")))
{
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(writeStream);
String line;
while ((line = reader.ReadLine()) != null)
{
if (!line.Equals(""))
{
if (o.GetId() == getIdFromString(line))
{
writer.Write(o.WriteToFile());
}
else
{
writer.Write(line + "\n");
}
}
else
{
continue;
}
}
}
}
catch (FileNotFoundException e)
{
Console.WriteLine($"The file was not found: '{e}'");
}
catch (DirectoryNotFoundException e)
{
Console.WriteLine($"The directory was not found: '{e}'");
}
catch (IOException e)
{
Console.WriteLine($"The file could not be opened: '{e}'");
}
}
public static string GetTxtPath(string fileName)
{
var startDirectory =
Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;
var absPath = startDirectory + #"\data\" + fileName;
return absPath;
}
private static int getIdFromString(string line)
{
return Int32.Parse(line.Split('|')[0]);
}
Version 2:
public static void Edit(Transformable o, string fileName)
{
try
{
if (!File.Exists(FileUtils.GetTxtPath("temp.txt")))
{
File.Create(FileUtils.GetTxtPath("temp.txt"));
}
using (StreamReader reader = FileUtils.GetTxtReader(fileName))
using (StreamWriter writer = FileUtils.GetTxtWriter("temp.txt"))
{
String line;
while ((line = reader.ReadLine()) != null)
{
if (!line.Equals(""))
{
if (o.GetId() == getIdFromString(line))
{
writer.Write(o.WriteToFile());
}
else
{
writer.Write(line + "\n");
}
}
else
{
continue;
}
}
}
File.Move(FileUtils.GetTxtPath("temp.txt"), FileUtils.GetTxtPath(fileName));
File.Delete(FileUtils.GetTxtPath("temp.txt"));
//Here I tied many differenet options but nonthing worked
//Here is Java code which did the job of renaming and deleting
//------------------------------------------------------------
// File original = FileUtils.getFileForName(fileName);
// File backUpFile = new File("backUp");
// Files.move(original.toPath(), backUpFile.toPath(),
// StandardCopyOption.REPLACE_EXISTING);
// File temporary = FileUtils.getFileForName(temporaryFilePath);
// temporary.renameTo(original);
// backUpFile.delete();
// File original = FileUtils.getFileForName(path);
//--------------------------------------------------------
//public static File getFileForName(String name)
//{
// String dir = System.getProperty("user.dir");
// String sP = System.getProperty("file.separator");
// File dirData = new File(dir + sP + "src" + sP + "data");
// File file = new File(dirData.getAbsolutePath() + sP + name);
// return file;
//}
//---------------------------------------------------------------------
}
catch (FileNotFoundException e)
{
Console.WriteLine($"The file was not found: '{e}'");
}
catch (DirectoryNotFoundException e)
{
Console.WriteLine($"The directory was not found: '{e}'");
}
catch (IOException e)
{
Console.WriteLine($"The file could not be opened: '{e}'");
}
public static StreamReader GetTxtReader(string fileName)
{
var fileStream = new FileStream(GetTxtPath(fileName), FileMode.Open, FileAccess.Read);
return new StreamReader(fileStream, Encoding.UTF8);
}
public static StreamWriter GetTxtWriter(string fileName)
{
FileStream fileStream = new FileStream(GetTxtPath(fileName), FileMode.Append);
return new StreamWriter(fileStream, Encoding.UTF8);
}
public static void Edit(Transformable o, string fileName)
{
try
{
string tempName = "temp.txt"; // create here correct path
using (var readStream = File.OpenRead(fileName))
using (var writeStream = File.OpenWrite(tempName))
using (var reader = new StreamReader(readStream))
using (var writer = new StreamWriter(writeStream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (!line.Equals(""))
{
if (o.GetId() == GetId(line))
{
writer.WriteLine(o.ToWriteableString());
}
else
{
writer.WriteLine(line);
}
}
}
}
File.Delete(fileName);
File.Move(tempName, fileName);
}
catch ...
}
File.OpenWrite method opens an existing or creates a new file for writing. So there is no need to manually check and create the file.
You have wrapped FileStreams in a using statement quite correctly. However, StreamReader and StreamWriter also must to be released after use.
I renamed some methods, giving them names that conform to the naming rules in C#: Edit, GetId, ToWriteableString.
The else branch with the continue statement is not needed.
In the end, just use the File.Delete and File.Move methods.
Note: the int.Parse method can throw exceptions that also need to be handled.
I am using Renci.SSH and C# to connect to my Unix server from a Windows machine. My code works as expected when the directory contents are only files, but if the directory contains a folder, I get this
Renci.SshNet.Common.SshException: 'Failure'
This is my code, how can I update this to also download a directory (if exists)
private static void DownloadFile(string arc, string username, string password)
{
string fullpath;
string fp;
var options = new ProgressBarOptions
{
ProgressCharacter = '.',
ProgressBarOnBottom = true
};
using (var sftp = new SftpClient(Host, username, password))
{
sftp.Connect();
fp = RemoteDir + "/" + arc;
if (sftp.Exists(fp))
fullpath = fp;
else
fullpath = SecondaryRemoteDir + d + "/" + arc;
if (sftp.Exists(fullpath))
{
var files = sftp.ListDirectory(fullpath);
foreach (var file in files)
{
if (file.Name.ToLower().Substring(0, 1) != ".")
{
Console.WriteLine("Downloading file from the server...");
Console.WriteLine();
using (var pbar = new ProgressBar(100, "Downloading " + file.Name + "....", options))
{
SftpFileAttributes att = sftp.GetAttributes(fullpath + "/" + file.Name);
var fileSize = att.Size;
var ms = new MemoryStream();
IAsyncResult asyncr = sftp.BeginDownloadFile(fullpath + "/" + file.Name, ms);
SftpDownloadAsyncResult sftpAsyncr = (SftpDownloadAsyncResult)asyncr;
int lastpct = 0;
while (!sftpAsyncr.IsCompleted)
{
int pct = (int)((long)sftpAsyncr.DownloadedBytes / fileSize) * 100;
if (pct > lastpct)
for (int i = 1; i < pct - lastpct; i++)
pbar.Tick();
}
sftp.EndDownloadFile(asyncr);
Console.WriteLine("Writing File to disk...");
Console.WriteLine();
string localFilePath = "C:\" + file.Name;
var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
ms.WriteTo(fs);
fs.Close();
ms.Close();
}
}
}
}
else
{
Console.WriteLine("The arc " + arc + " does not exist");
Console.WriteLine();
Console.WriteLine("Please press any key to close this window");
Console.ReadKey();
}
}
}
BeginDownloadFile downloads a file. You cannot use it to download a folder. For that you need to download contained files one by one.
The following example uses synchronous download (DownloadFile instead of BeginDownloadFile) for simplicity. After all, you are synchronously waiting for asynchronous download to complete anyway. To implement a progress bar with synchronous download, see Displaying progress of file download in a ProgressBar with SSH.NET.
public static void DownloadDirectory(
SftpClient sftpClient, string sourceRemotePath, string destLocalPath)
{
Directory.CreateDirectory(destLocalPath);
IEnumerable<SftpFile> files = sftpClient.ListDirectory(sourceRemotePath);
foreach (SftpFile file in files)
{
if ((file.Name != ".") && (file.Name != ".."))
{
string sourceFilePath = sourceRemotePath + "/" + file.Name;
string destFilePath = Path.Combine(destLocalPath, file.Name);
if (file.IsDirectory)
{
DownloadDirectory(sftpClient, sourceFilePath, destFilePath);
}
else
{
using (Stream fileStream = File.Create(destFilePath))
{
sftpClient.DownloadFile(sourceFilePath, fileStream);
}
}
}
}
}
The process cannot access the file because it is being used by another process
private void DeleteReport()
{
int invid = Convert.ToInt32(Session["InvId"]);
string FileName = invid + "_Report" + ".pdf";
string path1 = Server.MapPath("~/Report/" + FileName);
if (File.Exists(path1))
{
File.Delete(path1);
}
}
The error tells you, that the file is used and can't be deleted. So nothing wrong. As you did not formulate a
real question, lets try to help you in following way.
I guess that only your program is using the report, so good possible, you block the report
somewhere else.
E.g., the following code
string path = "C:\\Temp\\test.txt";
FileStream file = File.Open(path, FileMode.OpenOrCreate);
if (File.Exists(path))
File.Delete(path);
raises the same error. It does not necessarily mean that the process is another process.
What you can do is for example, for testing purpose, install SysInternal
http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx and add following code around your
File.Delete statement. Then you will see, what process uses the file:
try
{
File.Delete(path);
}
catch (Exception)
{
using (Process tool = new Process())
{
tool.StartInfo.FileName = #"C:\Program Files (x86)\SysinternalsSuite\handle.exe"; //Your path
tool.StartInfo.Arguments = path + " /accepteula";
tool.StartInfo.UseShellExecute = false;
tool.StartInfo.RedirectStandardOutput = true;
tool.Start();
tool.WaitForExit();
string outputTool = tool.StandardOutput.ReadToEnd();
string matchPattern = #"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
foreach (Match match in Regex.Matches(outputTool, matchPattern))
{
Process p = Process.GetProcessById(int.Parse(match.Value));
MessageBox.Show(p.ProcessName); // OR LOG IT
}
}
throw;
}
Credit for handle.exe call to https://stackoverflow.com/a/1263609/2707156
How would I write a log file in c#?
Currently i have a timer with this statement which ticks every 20 secs:
File.WriteAllText(filePath+"log.txt", log);
For everything that i want logged i do this:
log += "stringToBeLogged";
As you can assume the string log just grows and grows as the program runs. (I don't even know if there is a maximum chars per string?)
I assume that there must be better ways of doing this. i just thought that it would be heavy to write the whole file again and again for every time something is added to the log.
From the performance point of view your solution is not optimal. Every time you add another log entry with +=, the whole string is copied to another place in memory. I would recommend using StringBuilder instead:
StringBuilder sb = new StringBuilder();
...
sb.Append("log something");
...
// flush every 20 seconds as you do it
File.AppendAllText(filePath+"log.txt", sb.ToString());
sb.Clear();
By the way your timer event is probably executed on another thread. So you may want to use a mutex when accessing your sb object.
Another thing to consider is what happens to the log entries that were added within the last 20 seconds of the execution. You probably want to flush your string to the file right before the app exits.
create a class create a object globally and call this
using System.IO;
using System.Reflection;
public class LogWriter
{
private string m_exePath = string.Empty;
public LogWriter(string logMessage)
{
LogWrite(logMessage);
}
public void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
}
}
public void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
Use File.AppendAllText instead:
File.AppendAllText(filePath + "log.txt", log);
public static void WriteLog(string strLog)
{
StreamWriter log;
FileStream fileStream = null;
DirectoryInfo logDirInfo = null;
FileInfo logFileInfo;
string logFilePath = "C:\\Logs\\";
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
if (!logFileInfo.Exists)
{
fileStream = logFileInfo.Create();
}
else
{
fileStream = new FileStream(logFilePath, FileMode.Append);
}
log = new StreamWriter(fileStream);
log.WriteLine(strLog);
log.Close();
}
Refer Link:
blogspot.in
as posted by #randymohan, with using statements instead
public static void WriteLog(string strLog)
{
string logFilePath = #"C:\Logs\Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
FileInfo logFileInfo = new FileInfo(logFilePath);
DirectoryInfo logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
using (FileStream fileStream = new FileStream(logFilePath, FileMode.Append))
{
using (StreamWriter log = new StreamWriter(fileStream))
{
log.WriteLine(strLog);
}
}
}
Very convenient tool for logging is http://logging.apache.org/log4net/
You can also make something of themselves less (more) powerful. You can use http://msdn.microsoft.com/ru-ru/library/system.io.filestream (v = vs.110). Aspx
Add log to file with Static Class
public static class LogWriter
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!File.Exists(m_exePath + "\\" + "log.txt"))
File.Create(m_exePath + "\\" + "log.txt");
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
if(!File.Exists(filename)) //No File? Create
{
fs = File.Create(filename);
fs.Close();
}
if(File.ReadAllBytes().Length >= 100*1024*1024) // (100mB) File to big? Create new
{
string filenamebase = "myLogFile"; //Insert the base form of the log file, the same as the 1st filename without .log at the end
if(filename.contains("-")) //Check if older log contained -x
{
int lognumber = Int32.Parse(filename.substring(filename.lastIndexOf("-")+1, filename.Length-4); //Get old number, Can cause exception if the last digits aren't numbers
lognumber++; //Increment lognumber by 1
filename = filenamebase + "-" + lognumber + ".log"; //Override filename
}
else
{
filename = filenamebase + "-1.log"; //Override filename
}
fs = File.Create(filename);
fs.Close();
}
Refer link:
http://www.codeproject.com/Questions/163337/How-to-write-in-log-Files-in-C
This is add new string in the file
using (var file = new StreamWriter(filePath + "log.txt", true))
{
file.WriteLine(log);
file.Close();
}
There are 2 easy ways
StreamWriter - http://www.dotnetperls.com/streamwriter
Log4Net like Log4j(Java) - http://www.codeproject.com/Articles/140911/log4net-Tutorial
If your application is multithreaded then in some environments file.appendalltext could give error like file already in use and if you skip that then you could lose important logs .
For that you can use
Lock object technique with file.append.. in that case it will wait for existing process to close and the write your log
This can also save you from adding other libraries in your source
Above code will throw: Process can't access the file because it is being used by another process error because of File.Create(m_exePath + "\" + "log.txt"); if you will comment out this it will work as expected
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SolutionLogWriter
{
public static class LogWriterClass
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string fullpath = m_exePath + "\\" + "log.txt";
if (File.Exists(fullpath))
{
File.Delete(fullpath);
}
// File.Create(fullpath);
try
{
FileStream fs = new FileStream(fullpath, FileMode.OpenOrCreate);
using (StreamWriter w = new StreamWriter(fs))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
AppendLog(ex.ToString());
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter=null)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
txtWriter.Write(ex.Message);
}
}
}
}
Solved
I figured out that the GetNewFolderNameBasedOnDate method internally didn't close the file. I have that method fixed and it working normal now
I am trying to move selected files from one folder to another using BackgroundWorker process in C#. Here is my DoWork() method that determine whether to move the files or just copy. My File.Move() throws an exception that "The process cannot access the file because it is being used by another process". I tried different methods as mentioned in the threads here in stackoverflow.
private void FileProcessor_DoWork(object sender, DoWorkEventArgs e)
{
// Copy files
long bytes = 0;
string destSubFolder = String.Empty;
string destFile = string.Empty;
foreach (FileInfo file in oSettings.SourceFiles)
{
try
{
this.BeginInvoke(OnChange, new object[] { new UIProgress(file.Name, bytes, oSettings.MaxBytes) });
destSubFolder = GetNewFolderNameBasedOnDate(file);
//Create a new subfolder under the current active folder
string newPath = Path.Combine(oSettings.TargetFolder, destSubFolder);
// Create a new target folder, if necessary.
if (!System.IO.Directory.Exists(newPath))
{
System.IO.Directory.CreateDirectory(newPath);
}
destFile = Path.Combine(oSettings.TargetFolder, destSubFolder, file.Name);
if (chkDeleteSourceFiles.Checked)
{
FileInfo f = new FileInfo(file.FullName);
if (f.Exists)
{
File.Move(file.FullName, destFile);
}
}
else
{
File.Copy(file.FullName, destFile, true);
}
//Thread.Sleep(2000);
}
catch (Exception ex)
{
UIError err = new UIError(ex, file.FullName);
this.Invoke(OnError, new object[] { err });
if (err.result == DialogResult.Cancel) break;
}
bytes += file.Length;
}
}
I tried to delete the files in "RunWorkerCompleted" method too. But didn't resolve the problem. This fails when it tries to delete the last file in the list.
private void FileProcessor_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Operation completed, update UI
ChangeUI(false);
foreach (FileInfo file in oSettings.SourceFiles)
{
File.Delete(file.FullName);
}
}
GetNewFolderNameBasedOnDate() calls GetDateTaken() which was the culprit. Earlier I didn't use FileStream object but used Image myImage = Image.FromFile(filename); I didn't know that Image.FromFile locks the file.
private DateTime GetDateTaken(string fileName)
{
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
Image myImage = Image.FromStream(fs);
PropertyItem propItem = myImage.GetPropertyItem(36867);
DateTime dtaken;
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
return dtaken;
}
}
catch (Exception ex)
{
return DateTime.Now;
}
}
Instead of creating new FileInfo objects, keep it simple and re-use the same one. I suspect the problem is that you have multiple references to the same file in your code, which prevents it from being removed. Try something like this to move it:
if (chkDeleteSourceFiles.Checked)
{
if (file.Exists)
{
file.MoveTo(destFile);
}
}
My guess is that it is the BeginInvoke call to OnChange and the new UIProgress() object that is holding onto the file. Does UIProgress open the file? You could try just using Invoke() and see if that helps.