Service Logging not working - c#

I am trying to add some logging functionality to a service, however I want it to create a new log, copy the old log into the new one and delete the original.
Sudo for ClearLog: if log1 full create log2, delete contents of log1
Please see code below, currently the ClearLog function is not doing what I want.
Can anyone see what I'm doing wrong?
public static void WriteLog(string txt)
{
string fp = _AppPath + #"\Logging";
try
{
File.AppendAllText(fp + #"\Log1.txt", txt);
}
catch (IOException iex)
{
Debug.Print("Error writing log" + iex.ToString());
}
}
private static void ClearLog()
{
string fp = _AppPath + #"\Logging";
try
{
if (!File.Exists(fp + #"\Log1.txt"))
{
WriteErrorLog("");
}
else
{
File.AppendAllText(fp + #"\Log1.txt", fp + #"\Log2.txt");
File.Delete(fp + #"\Log1.txt");
WriteLog("");
}
}
catch (Exception ex)
{
WriteLog("Clear log failed " + ex.ToString());
}
}

Try creating a public static field of the file path, as you're opening the same file twice it seems.
IE: public static string logfp = _AppPath + #"\Logging";
Then rename everything in those two functions logfp.
Improved example (can use paths in both or declared throughout)
private static void ClearLog()
{
string logfp = _AppPath + #"\Logging";
try
{
if (File.Exists(logfp + #"\Log2.txt"))
{
File.Delete(logfp + #"\Log2.txt");
if (File.Exists(logfp + #"\Log1.txt"))
{
File.Copy(logfp + #"\Log1.txt", logfp + #"\Log2.txt");
File.Delete(logfp + #"\Log1.txt");
}
else
{
File.AppendAllText(logfp + #"\Log1.txt", "New Log created: " + DateTime.Now.ToString());//showing you when it was created
}
}
else
{
File.Copy(logfp + #"\Log1.txt", logfp + #"\Log2.txt");
File.Delete(logfp + #"\Log1.txt");
}
}
catch (Exception ex)
{
WriteErrorLog("Clear log failed " + ex.ToString());
}
}

Related

C# WUApiLib: Failing to Install Updates with 0x80240024 Even Though Updates are Found

I have followed instructions found on this site, which was found when I researched Stack Overflow and found this question. However, I can't seem to figure out why my code is hitting the catch block. I have a break at the IInstallationResult line, which the code hits but then goes to the catch, stating 0x80240024 (There are no updates), even though there are certainly updates available and I list them in the text box.
What am I missing here?
using System;
using System.Windows.Forms;
using WUApiLib;
namespace TEST.DetectWindowsUpdate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void GetUpdates(bool downloadUpdates, bool installUpdates)
{
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
UpdateCollection updatesToInstall = new UpdateCollection();
UpdateDownloader downloader = uSession.CreateUpdateDownloader();
IUpdateInstaller installer = uSession.CreateUpdateInstaller();
uSearcher.Online = true;
try
{
ISearchResult sResult = uSearcher.Search("IsInstalled=0 And Type='Software'");
lblUpdateCount.Text = sResult.Updates.Count.ToString();
foreach (IUpdate update in sResult.Updates)
{
txtUpdatesList.AppendText("Title: " + update.Title + Environment.NewLine);
txtUpdatesList.AppendText("IsInstalled: " + update.IsInstalled.ToString() + Environment.NewLine);
txtUpdatesList.AppendText("Downloaded: " + update.IsDownloaded.ToString() + Environment.NewLine);
txtUpdatesList.AppendText("IsMandatory: " + update.IsMandatory.ToString() + Environment.NewLine);
txtUpdatesList.AppendText(Environment.NewLine);
if (downloadUpdates)
{
if (update.IsDownloaded == false)
{
do
{
downloader.Updates.Add(update);
downloader.Download();
}
while (update.IsDownloaded == false);
if (update.IsDownloaded == true)
{
updatesToInstall.Add(update);
}
}
else
{
updatesToInstall.Add(update);
}
}
if (installUpdates)
{
installer.Updates = updatesToInstall;
IInstallationResult installationRes = installer.Install();
for (int i = 0; i < updatesToInstall.Count; i++)
{
txtUpdatesList.AppendText("Installing " + updatesToInstall[i].Title + "...");
if (installationRes.GetUpdateResult(i).HResult == 0)
{
txtUpdatesList.AppendText("INSTALL SUCCESS FOR " + updatesToInstall[i].Title);
}
else
{
txtUpdatesList.AppendText("INSTALL FAIL FOR " + updatesToInstall[i].Title);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message + ": " + ex.HelpLink);
}
}
private void btnGetUpdates_Click(object sender, EventArgs e)
{
base.OnLoad(e);
txtUpdatesList.Clear();
GetUpdates(false, false);
}
private void btnInstallUpdates_Click(object sender, EventArgs e)
{
base.OnLoad(e);
txtUpdatesList.Clear();
GetUpdates(true, true );
}
}
}
Turns out it was an issue with privileges. I ran as administrator and it functioned appropriately.

Form without movement when filling in DataGridView

I use a DataGridView as a console for an application, I need to fill it out every second, I use the following code for this:
public class dgView
{
public static DataGridView DataConsole;
public static void addLinha(int tipo_acao, string acao, string extra, int tipo_extra)
{
// INSERE LINHA NO CONSOLE
try
{
if (DataConsole == null) return;
var idLinha = DataConsole.Rows.Add();
using (var linha = DataConsole.Rows[idLinha])
{
//await Task.Delay(300);
if (tipo_acao == 0)
{
linha.DefaultCellStyle.ForeColor = Color.Teal;
linha.Cells[3].Style.ForeColor = Color.Gray;
}
else if (tipo_acao == 1)
{
linha.DefaultCellStyle.ForeColor = Color.Yellow;
linha.Cells[3].Style.ForeColor = Color.Orange;
}
else
{
linha.DefaultCellStyle.ForeColor = Color.Red;
linha.Cells[3].Style.ForeColor = Color.Magenta;
}
linha.Cells["dg_data"].Value = DateTime.Now;
linha.Cells["dg_mapa"].Value = "" + Config.Mapa + "";
linha.Cells["dg_acao"].Value = "" + Config.rm.GetString("" + acao + "") + "";
if (tipo_extra == 0)
{
linha.Cells["dg_extra"].Value = "" + extra + "";
}
else
{
linha.Cells["dg_extra"].Value = "" + Config.rm.GetString(extra) + "";
}
DataConsole.CurrentCell = DataConsole.Rows[idLinha].Cells[0];
//DataConsole.Refresh();
}
}
catch (Exception ex)
{
throw;
}
}
}
However, the form freezes and I can't move it to any part of the screen, would there be any way to solve this? Remembering that the DataGridView is not, and cannot be populated through the DataSource property, but by a constant verification in the system.
Example:
public static void Abrir(string metodoChamador)
{
try
{
Abrir:
dgView.addLinha(2, "config_Abrir", "config_Validando", 1);
Thread.Sleep(5000);
Atalho:
string AtalhoExiste = "" + Directory.GetCurrentDirectory() + "\\" + Config.Atalho + ".lnk";
if (!File.Exists(AtalhoExiste))
{
dgView.addLinha(2, "config_FaltaIcone", "", 0);
Thread.Sleep(5000);
goto Atalho;
}
else
{
ProcessStartInfo info = new ProcessStartInfo(#"" + Directory.GetCurrentDirectory() + "\\" + Config.Atalho + ".lnk");
Process whatever = Process.Start(info);
whatever.Dispose();
Thread.Sleep(5000);
IntPtr WinHandle = Win32.FindWindow(null, Config.Atalho);
if (WinHandle == (IntPtr)0)
{
goto Abrir;
}
}
}
catch (Exception ex)
{
throw;
}
}
It's hard to tell if you have other potential problems in the code. Basically anywhere you have Thread.Sleep(), your GUI is going to freeze.
Here's a possible refactoring of your Abrir() method, using async\await and Task.Delay() as suggested by JQSOFT:
public async static void Abrir(string metodoChamador)
{
try
{
IntPtr WinHandle = IntPtr.Zero;
do
{
dgView.addLinha(2, "config_Abrir", "config_Validando", 1);
await Task.Delay(5000);
string AtalhoExiste = "" + Directory.GetCurrentDirectory() + "\\" + Config.Atalho + ".lnk";
while (!File.Exists(AtalhoExiste))
{
dgView.addLinha(2, "config_FaltaIcone", "", 0);
await Task.Delay(5000);
}
ProcessStartInfo info = new ProcessStartInfo(#"" + Directory.GetCurrentDirectory() + "\\" + Config.Atalho + ".lnk");
Process whatever = Process.Start(info);
whatever.Dispose();
await Task.Delay(5000);
WinHandle = Win32.FindWindow(null, Config.Atalho);
}
while (WinHandle.Equals(IntPtr.Zero));
}
catch (Exception ex)
{
throw;
}
}
If you have Thread.Sleep() in other locations, they would need to be refactored.
If you have any other infinite loops using goto, those may need to be refactored as well.

Csvhelper write with windows service

I am using csvhelper with windows service which runs non stop. I want to create a new csv log file and put the header values only once until the file size grown to 1000 kb and then create another new file so the file size grow too big. At the moment csv file is created once when windows service starts but it repeats header values every time it writes into it.
Do we have some config properties in csv helper to flag size file?
Please have a look at the code and suggest if it can be done efficiently in .net 4.0.
Windows Service code
public partial class Service1 : ServiceBase
{
private Thread executeThread;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
Thread.Sleep(30000);
executeThread = new Thread(new ThreadStart(Execute));
executeThread.Start();
}
catch (Exception e)
{
Library.LogData("Error : " + DateTime.UtcNow + " " + e.Message);
OnStop();
}
}
protected override void OnStop()
{
try
{
Library.LogData("Stopped: " + DateTime.UtcNow);
executeThread.Abort();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
public void Execute()
{
try
{
Library.LogData("Started");
while (true)
{
Library.LogData("Logging Execute" + DateTime.UtcNow);
Thread.Sleep(5000);
}
}
catch (Exception e)
{
Library.LogData("Error : " + DateTime.UtcNow + " " + e.Message);
OnStop();
}
Library.LogData("Out of Execute" + DateTime.UtcNow);
}
}
Logging code called by windows service
public static class Library
{
public static void LogData(string Message)
{
StreamWriter sw = null;
GetData getData = new GetData();
var dataClasslist = new List<DataClass>
{
new DataClass {}
};
try
{
dataClasslist = getData.ReadData();
using (sw = new StreamWriter("E:\\DataLogs\\LogFile.csv", true))
using (var csv = new CsvWriter(sw))
{
csv.Configuration.RegisterClassMap<DataClassMap>();
csv.WriteHeader<DataClass>();
csv.Configuration.TrimHeaders = true;
csv.Configuration.HasHeaderRecord = false;
csv.WriteRecords(dataClasslist);
sw.Flush();
sw.Close();
}
}
catch (Exception e)
{
var err = new StreamWriter("E:\\DataLogs\\Errors", true);
err.WriteLine(DateTime.Now.ToString() + ": " + e.Message.ToString());
err.Flush();
err.Close();
}
}
}
Main windows service
public partial class Service1 : ServiceBase
{
private Thread executeThread;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
Thread.Sleep(10000);
executeThread = new Thread(new ThreadStart(Execute));
executeThread.Start();
}
catch (Exception e)
{
var err = new StreamWriter("E:\\DataLogs\\Errors", true);
err.WriteLine(DateTime.Now.ToString() + " OnStart: " + e.Message.ToString());
err.Flush();
err.Close();
OnStop();
}
}
protected override void OnStop()
{
try
{
executeThread.Abort();
}
catch (Exception e)
{
var err = new StreamWriter("E:\\DataLogs\\Errors", true);
err.WriteLine(DateTime.Now.ToString() + "OnStop exception: " + e.Message.ToString());
err.Flush();
err.Close();
}
}
public void Execute()
{
try
{
StreamWriter sw = null;
string FileNameAndPath = null;
FileNameAndPath = "E:\\DataLogs\\LogFile" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv";
using (sw = new StreamWriter(FileNameAndPath, true))
{
sw.WriteLine("TimeStamp " + "," + "col1" + "," + "col2" + "," + "col3"
+ "," + "col4" + "," + "col5" + "," + "col6" + ","
+ "col8" + "," + "col9" + "," + "col7" + "," + "col10");
sw.Flush();
sw.Close();
}
while (true)
{
Library.LogData(FileNameAndPath);
Thread.Sleep(5000);
}
}
catch (Exception e)
{
var err = new StreamWriter("E:\\DataLogs\\Errors", true);
err.WriteLine(DateTime.Now.ToString() + " Execute: " + e.Message.ToString());
err.Flush();
err.Close();
OnStop();
}
}
public void TestInConsole(string[] args)
{
Console.WriteLine("Starting.....");
this.OnStart(args);
}
So OnExecute will be called as soon as file hits 100kb and new file will be created with headers written in it only once.
public static class Library
{
public static void LogData(string FileNameAndPath)
{
StreamWriter sw = null;
GetData getData = new GetData();
var dataClasslist = new List<DataClass>
{
new DataClass {}
};
try
{
//System.Diagnostics.Debugger.Break();
dataClasslist = getData.ReadData();
//Create a file seperately
using (sw = new StreamWriter(FileNameAndPath, true))
using (var csv = new CsvWriter(sw))
{
csv.Configuration.RegisterClassMap<DataClassMap>();
//csv.WriteHeader<DataClass>();
csv.Configuration.TrimHeaders = true;
csv.Configuration.HasHeaderRecord = false;
csv.WriteRecords(dataClasslist);
sw.Flush();
sw.Close();
}
var FileSize = new FileInfo(FileNameAndPath);
//for each 1000 kb
if (FileSize.Length >= 1e+6)
{
//go back to the start to create a new file and column headers
Service1 serive1 = new Service1();
serive1.Execute();
}
}
catch (Exception e)
{
var err = new StreamWriter("E:\\DataLogs\\Errors", true);
err.WriteLine(DateTime.Now.ToString() + " LogData: " + e.Message.ToString());
err.Flush();
err.Close();
}
}
}
Im open for suggests, please let me know if you can thing of a better way to to do this.

How to use named Mutex

I'm trying to use Mutex to handle different process/application to write on same file.
This is my code
ILogTest logTest = new LogTest(new FileLog());
logTest.PerformanceTest();
public class ILogTest
{
public void PerformanceTest()
{
for (int i = 0; i < this.numberOfIterations; i++)
{
try
{
Thread threadC = Thread.CurrentThread;
threadC = new Thread(ThreadProc);
threadC.Name = i.ToString();
threadC.Start();
threadC.Suspend();
threadC.IsBackground = true;
}
catch (Exception)
{
throw new Exception("errore");
}
}
}
private void ThreadProc()
{
try
{
log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
}
catch (Exception)
{
throw new Exception("errore");
}
}
}
FileLog is an implementation of ILogTest.
Write method :
public void Write(string message)
{
try
{
rwl.WaitOne();
try
{
string tID = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.CurrentCulture);
sw.WriteLine(sev.ToString() + "\t" + DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss", CultureInfo.CurrentCulture) + "\t\t" + System.Reflection.Assembly.GetCallingAssembly().GetName().Name + "\t" + Process.GetCurrentProcess().Id.ToString(CultureInfo.CurrentCulture) + "\t" + tID + " \t " + message);
sw.WriteLine("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
catch (Exception ex)
{
throw new ArgumentException("Cannot write to file " + ex.Message);
}
finally
{
rwl.ReleaseMutex();
}
}
catch (ApplicationException)
{
}
}
FileLog main :
public FileLog()
{
try
{
rwl.WaitOne();
string filePath = Path.GetTempPath() + "Test.txt";
if (!File.Exists(filePath))
{
swa = new FileStream(filePath, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(swa);
}
}
catch (Exception ex)
{
throw new ArgumentException("Cannot open or create file " + ex.Message);
}
try
{
if (sw == null)
{
swa = new FileStream(filePath, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(swa);
}
sw.AutoFlush = true;
}
catch (Exception ex)
{
throw new ArgumentException("Cannot write to file " + ex.Message);
}
}
Trying simulate it, it doesn't write anything to file, only create it..
I don't know why.
Could anyone help me? thanks
The FileLog constructor calls rwl.WaitOne() which acquires the mutex (I'm assuming rwl is a Mutex object), but never calls rwl.ReleaseMutex().
Thus, every thread that calls Write() blocks on its call to rwl.WaitOne() because the mutex is still owned by another thread.
You will need to release the Mutex in the FileLog constructor so that other threads can acquire it.
Also, you have a call to threadC.Suspend(); in PerformanceTest; unless there is code that resumes the threads, they will never finish running.

Error logging in Windows CE C#

I'm writing a Windows CE App and want to implement error logging to a .txt file.
I've done research and saw this example:
public static void Logs(string fileName, string methodName, string message)
{
try
{
if (!string.IsNullOrEmpty(message))
{
using (FileStream file = new FileStream(Application.StartupPath + "\\Log.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
StreamWriter streamWriter = new StreamWriter(file);
streamWriter.WriteLine((((System.DateTime.Now + " - ") + fileName + " - ") + methodName + " - ") + message);
streamWriter.Close();
}
}
}
catch
{
}
}
private void button2_Click(object sender, EventArgs e)
{
try
{
int a = 10, b = 0;
int result = a / b; //runtime Exception will throw
}
catch (Exception ex)
{
Logs(this.GetType().Name, "button1_Click()", ex.Message.ToString());
}
}
That works but only in Windows Forms. I'm getting this error in Windows CE:
'System.Windows.Application' does not contain a definition for 'StartupPath'
Ok, so I know I have to use this:
Path.GetDirectoryName (Assembly.GetExecutingAssembly ().GetName ().CodeBase);
But I'm not sure how. Still learning so please don't mark this as duplicate. Can someone rather just explain to me exactly where and how to use this in Windows CE app?
Thanks in advance.
You can write a function that returns the path of the executing assembly... just like:
public static string GetCurrentApplicationPath()
{
return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
}
and use this function in place of Application.StartupPath

Categories