I have the following piece of code to write data to an XML file.
private void WriteResidentData()
{
int count = 1;
status = "Writing XML files";
foreach (Site site in sites)
{
try
{
//Create the XML file
StreamWriter writer = new StreamWriter(path + "\\sites\\" + site.title + ".xml");
writer.WriteLine("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>");
writer.WriteLine("<customer_list>");
foreach (Resident res in site.GetCustomers())
{
bw.ReportProgress((count / customers) * 100);
writer.WriteLine("\t<customer>");
writer.WriteLine("\t\t<customer_reference>" + res.reference + "</customer_reference>");
writer.WriteLine("\t\t<customer_name>" + res.name + "</customer_name>");
writer.WriteLine("\t\t<customer_address>" + res.address + "</customer_address>");
writer.WriteLine("\t\t<payment_method>" + res.method + "</payment_method>");
writer.WriteLine("\t\t<payment_cycle>" + res.cycle + "</payment_cycle>");
writer.WriteLine("\t\t<registered>" + CheckWebStatus(res.reference) + "</registered>");
writer.WriteLine("\t</customer>");
count++;
}
writer.WriteLine("</customer_list>");
writer.Close();
}
catch (Exception ex)
{
lastException = ex;
}
}
}
It's using the same BackgroundWorker that gets the data from the database. My progress bar properly displays the progress whilst it is reading from the database. However, after zeroing the progress bar for the XML writing it simply sits at 0 even though the process is completing correctly.
Can anyone suggest why?
Could it be that (count / customers) is truncated to zero (division between two integers)?
I think that should be (count*100)/customers, assuming you wanted a percentage complete.
This has to do with threading. Because you are updating your GUI in the same thread as your work is being done.
Does the progressbar fill up when the task is fully complete?
Hmmmzz, you are using a bw in there... so that might be your backgroundworker-process.
Related
The task I have is to insert the content of a cover page word document into a set of existing word documents. The existing documents all sit within a ToBeProcessed folder with the covering page stored in it's own folder. The process I have created is to store the contents of the covering page in a string then iterate through the list of existing files opening each one, selecting the start of the document using a range, inserting the text then adding a page break.
So far, everything works as expected except the fact that the page break is being inserted ahead of the covering page content. Can someone please advise how to achieve this? I've included the full content of my program in case anyone has experience of achieving the same result in a more efficient manner but from my research, the use of range seems to be best practice.
const string COVERING_FOLDER = #"C:\Users\alex.grimsley1\Documents\DocmanLetters\CoveringPage";
const string COMPLETE_FOLDER = #"C:\Users\alex.grimsley1\Documents\DocmanLetters\Complete";
const string LOG_FOLDER = #"C:\Users\alex.grimsley1\Documents\DocmanLetters\Log";
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss"));
StreamWriter logfile = new StreamWriter(LOG_FOLDER + #"\Log_" + DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + #".txt");
//Returns an array of strings which contains the list of filenames to be edited
var files = Directory.GetFiles(PROCESSING_FOLDER);
//Creates a new Application wrapper
Application ap = new Application();
//Open the Covering Page document
var cp = ap.Documents.Open(COVERING_FOLDER + "\\CoveringPage.docx");
//Copy the Covering Page contents to a variable for later use
var cpContent = cp.Content.Text;
//Close the Covering Page document
cp.Close(WdSaveOptions.wdDoNotSaveChanges);
//Loop through the file list
foreach(var file in files)
{
if(file.Substring(0, PROCESSING_FOLDER.Length + 1) == PROCESSING_FOLDER + "~")
{
Console.WriteLine("Skipping temporary file: " + file);
} else
{
try
{
object missing = System.Type.Missing;
//Open each file using the Application wrapper
var d = ap.Documents.Open(file);
ap.Visible = true;
var dName = d.Name;
//Select a range at the very start of the Document
var rng = d.Range(0, 0);
d.Unprotect();
d.Protect(WdProtectionType.wdNoProtection);
//Add covering page text to the Document
rng.Text = cpContent;
rng.Collapse(WdCollapseDirection.wdCollapseEnd);
rng.InsertBreak(WdBreakType.wdPageBreak);
//Write the Document name to the Console
Console.WriteLine(d.Name);
//Save the document in place
d.Save();
//Close the document
d.Close(WdSaveOptions.wdDoNotSaveChanges);
//Move the file to the Complete folder
File.Move(file, COMPLETE_FOLDER + "\\" + dName);
//Log the completion of the letter
logfile.WriteLine("Complete " + DateTime.Now.ToString() + " - " + d.Name);
}
catch(Exception e)
{
Console.WriteLine("There was an error: " + e.Message);
//Log the completion of the letter
logfile.WriteLine("Error " + DateTime.Now.ToString() + " - " + e.Message);
}
finally
{
// Close Word application
ap.Quit();
Marshal.ReleaseComObject(ap);
ap = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
Console.WriteLine("Processing complete...");
Console.ReadLine();
}```
I am working on a home project that needs to execute some commands via SSH, read back the responses and display them on a web page. A lot of the time it does work, but now and then i get some inconsistent behavior, for example certain lines of output are missed that would instruct on what to do next, this results in a hung session, and a requirement to restore IIS.
I have included the code below, like I said I am not a full time developer, so its gonna be a mess, but hopefully someone can point me in the right direction to understand what i got so wrong, and what i need to change, i wont learn if you just past code snippets up, id much rather attempt to try and fix what i have.
using (SshClient ssh = new SshClient("192.168.0.119", "x", "x."))
{
ssh.Connect();
ShellStream shell = ssh.CreateShellStream("Tail", 0, 0, 0, 0, 1024);
StreamWriter wr = new StreamWriter(shell);
StreamReader rd = new StreamReader(shell);
wr.AutoFlush = true;
if (extract)
{
Console.WriteLine("Downloading DataZIP");
ssh.RunCommand("wget " + zipURL);
}
bool reading = shell.CanRead;
wr.WriteLine("cd " + remoteFilePath + packagename + " && docker build -t dockerfile .");
while (reading)
{
Clients.Caller.builderOut(shell.ReadLine().ToString());
if (shell.ReadLine().ToString().Contains("Successfully"))
{
Clients.Caller.builderOut("Build Complete");
reading = false;
}
if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
{
goto end;
}
}
if (data.Type == TemplateType.Data)
{
wr.WriteLine("cd " + remoteFilePath + packagename + " && docker tag dockerfile " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
wr.WriteLine("cd " + remoteFilePath + packagename + " && docker push " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
}
reading = shell.CanRead;
while (reading)
{
Clients.Caller.builderOut("Pushing this will take a moment");
if (shell.ReadLine().ToString().Contains("digest:"))
{
Clients.Caller.builderOut("Pushed");
reading = false;
}
}
Clients.Caller.builderOut("End");
ssh.Disconnect();
ssh.Dispose();
}
What I think I got wrong
I think I get these errors due to the way I'm reading the console output. I think that that data changes so fast we miss some:
while (reading)
{
Clients.Caller.builderOut(shell.ReadLine().ToString());
if (shell.ReadLine().ToString().Contains("Successfully"))
{
Clients.Caller.builderOut("Build Complete");
reading = false;
}
if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
{
goto end;
}
}
So using that each of the 3 checks on the output could I think be be missing some of the lines, as the output is quite speedy, while its reading the value changes so the next check has different init data to check, and thus we skip over what would otherwise be the exit lines or next job lines.
You have to store the line that you read into a variable and do the checks against the stored value:
while (reading)
{
string line = shell.ReadLine();
Clients.Caller.builderOut(line);
if (line.Contains("Successfully"))
{
Clients.Caller.builderOut("Build Complete");
reading = false;
}
if (line.Contains("returned a non-zero code: "))
{
goto end;
}
}
I'm getting an error with StreamWriter that the file is in use by another process, but I believe it may be down to the speed at which I'm writing the file or more specifically the speed of it being opened/closed.
The code is as follows:
public static void writeLog(string msg)
{
StreamWriter log;
string currentMonth = DateTime.Now.ToString("MMM");
string currentYear = DateTime.Now.ToString("yyyy");
string directoryName = currentMonth + "-" + currentYear;
if (!Directory.Exists(#"C:\AutoSkill\LogFiles\" + directoryName + #"\"))
{
Directory.CreateDirectory(#"C:\AutoSkill\LogFiles\" + directoryName + #"\");
}
DateTime dt = DateTime.Now;
string date = dt.ToString("dd-MM-yy");
if (!File.Exists(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt"))
{
log = new StreamWriter(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt");
}
else
{
log = File.AppendText(#"C:\AutoSkill\LogFiles\" + directoryName + #"\" + date + ".txt");
}
try
{
log.WriteLine(msg);
}
catch (Exception err)
{
Console.WriteLine("There was an error writing to the log file.");
Console.WriteLine(err.Message);
}
log.Close();
}
So I'm closing the log each time I'm done writing to it, but I'm writing all out my output from the console screen to the file to keep track of what actually happened; sometimes the lines are only a few milliseconds apart if the action that was taken was quick or just returned null.
Am i getting this error due to speed of writing to the file? Is there a better way to handle writing a log file?
Disregard this, I'm dumb.
I've not had this problem for the last 2 years, I'm getting the error because I'm writing to the same file from a different thread, which is where the overlap is.
The file actually is in use by another process, the same one just a different thread.
Good Day! I need help. I want to loop my StreamWriter to write every string from checkListBox in the notepad and make it as batchfile to execute the SQL Script.
Situation:
every checkLISTbox is an SQL, then I need to save it one by one by StreamWriter then execute it on batch file using SQLCMD. yet I need to loop it again. Let's say a matter of 2 or 2.5 seconds (thats why i use Thread.Sleep(2000)) before run the next batch file containing the another line of the text which is the next checkbox
StreamWriter SaveFile = new StreamWriter(file_name);
try
{ for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)
{
foreach (Object item in checkedListBox1.CheckedItems)
{
SaveFile.WriteLine(":r \"" + textBox1.Text + "\\" + item + "\"");
SaveFile.Close();
//Create a batchfile for execution of consolidated script
string execute = "\\Script_Runner.bat";
execute = textBox1.Text + execute;
StreamWriter SaveFile2 = new StreamWriter(execute);
SaveFile2.WriteLine("sqlcmd -S localhost -E -i " + textBox1.Text + "\\" + "test1.sql");
SaveFile2.Close();
//running the batchfile
string ScriptRun = "\\Script_Runner.bat";
ScriptRun = textBox1.Text + ScriptRun;
Process.Start(ScriptRun);
}
this.Refresh();
Thread.Sleep(2000);
i++;
}
}
catch
{
//error message every script
}
}
catch
{
//error message
}
richTextBox2.Text += "\nData Patch Completed.";
}
catch (Exception)
{
// error message upon clicking execute
}
since you did not clearly express the need for two loops i consider one as defect..
Closing the stream on the first item in the loop may be what you did not want..
i moved Streamwriter-instantiation inside the loop.
maybe it works for you - try.
try
{
foreach (Object item in checkedListBox1.CheckedItems)
{
StreamWriter SaveFile = new StreamWriter(file_name);
SaveFile.WriteLine(":r \"" + textBox1.Text + "\\" + item + "\"");
SaveFile.Close();
//Create a batchfile for execution of consolidated script
string execute = "\\Script_Runner.bat";
execute = textBox1.Text + execute;
StreamWriter SaveFile2 = new StreamWriter(execute);
SaveFile2.WriteLine("sqlcmd -S localhost -E -i " + textBox1.Text + "\\" + "test1.sql");
SaveFile2.Close();
//running the batchfile
string ScriptRun = "\\Script_Runner.bat";
ScriptRun = textBox1.Text + ScriptRun;
Process.Start(ScriptRun);
Thread.Sleep(2000);
}
this.Refresh();
}
catch
{
//error message every script
}
}
catch
{
//error message
}
richTextBox2.Text += "\nData Patch Completed.";
}
catch (Exception)
{
// error message upon clicking execute
I'm programming a video player in C# (the video works fine) and what I need now is to get the libvlc logs as well as my custom logs to print them in a file.
I use NLog which handles the libvlc logs (with nVLC) and I raise an event for my custom logs, and in buth cases this function is called :
private static void tracerlogs(string erreur, VLCControl.ControleUtilisateurVLC.LogLevels LvLog)
{
string path = "logs.txt";//Sera redéfini dans l'appli
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
else
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
Console.WriteLine(erreur + " " + LvLog.ToString());
}
The problem is that I'm getting at random times a System.IO.IOException telling that "the process cannot access the file because it is being used by another process". Although I do close my StreamWriter (which should normally not be useful in a using block)... This makes my app crash. Does anyone have any idea why it does this ?
I finally solved it by adding a resource : as there was a conflict between different threads trying to access this function, I wrapped this :
private static void tracerlogs(string erreur, VLCControl.ControleUtilisateurVLC.LogLevels LvLog)
{
lock (LockLog) {
string path = "logs.txt";//Sera redéfini dans l'appli
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
else
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
Console.WriteLine(erreur + " " + LvLog.ToString());
}
}
And I declare a public static readonly object LockLog = new Object(); in my class. This works just fine ! Thanks to those who told me that this had to see with threading.