I have the following class which writes new line to a text file.
using System;
using System.Text;
using System.IO;
namespace TextStreamer
{
class TextWriter
{
private string _FilePath;
private string _TextToAdd;
// Constructor will assign file Path variable and check if file is valid
public TextWriter(string filePath)
{
this._FilePath = filePath;
ValidateFile();
}
// Validate if the text file exist
private void ValidateFile()
{
// If file does not exist show error message
// and create new text file
if(!File.Exists(_FilePath))
{
Console.WriteLine("File not found");
File.Create(_FilePath);
Console.WriteLine("Created new file {0}", _FilePath);
}
}
// Write new line to the text file
public void WriteNewLine(string text)
{
this._TextToAdd = text + Environment.NewLine;
File.AppendAllText(_FilePath, _TextToAdd);
}
}
}
Right now if the file does not exist it will write a message to the console and then it will create the text file, but what if i used say WPF application, in this case i prefer showing a message box with the same message, how can i achieve that.
I tried throwing exception FileNotFoundException but that just crashes the program and exit.
A simple way to achieve this is by using a public variable to change the option to console log or show message.
Add the namespace for the generic message box:
using System.Windows;
And add a public variable in your class that will let you programmatically change the logging method, such as:
public bool UseMsgBox = false;
You could improve this by using things like using an int or enum to have more logging methods, though a bool is fine for only 2 options.
Add a logging method such as:
private void LogMsg(string msg)
{
if(UseNsgBox) MessageBox.Show(msg);
else Console.WriteLine(msg);
}
And replace your Console.WriteLine's with LogMsg instead.
Make sure to change the option when you create your class:
TextWriter textWriter = new TextWriter("SomeFile.txt");
textWriter.UseMsgBox = true; // or false
Actually, this might not work as you instantly call the LogMsg when your class is created, so perhaps add it as an initialization parameter as well:
public TextWriter(string filePath, bool useMsgBox = false)
{
UseMsgBox = useMsgBox;
// ...
}
Related
I’m trying to use the File class to work with a text file in a console and winforms desktop app and getting the following exception:
The type initializer for '_Library.Logging' threw an exception
From what I’ve read here this error is typically caused by a problem in App.config for Winfoms apps but the Exception details seem to point elsewhere:
System.ArgumentNullException: Value cannot be null. Parameter name: path
at System.IO.File.AppendAllText(String path, String contents)
The MSDN examples for file manipulation all hard code the path parameter without any reference to using an App.confiig file so my presumption was it is possible to do this without involving ConfigurationManager.
This is the code I'm trying to use
// in calling method
class Program_Console
{
private static StringBuilder SB4log = new StringBuilder();
public static void Main(string[] tsArgs)
{
// Conditionals dealing with argumentts from Task Scheduler
Save2Log("Calling _UI.exe via \"Process.Start()\"", true);
// try-catch-finally for Process.Start
}
private static void Save2Log(string msgTxt, bool noTS)
{
SB4log.AppendLine($"{msgTxt}");
if (noTS) Logging.SaveLog(SB4log);
else Logging.SaveLog_TimeStamp(SB4log);
SB4log.Clear();
}
}
// saving app progression messages to a single log txt file
public static class Logging
{
private static String filePath = Connections.LogPath();
private static StringBuilder SB4log = new StringBuilder();
public static void SaveLog(StringBuilder logTxt)
{
File.AppendAllText(filePath, logTxt.ToString());
logTxt.Clear();
}
}
// class for DB connection and file paths
public static class Connections
{
private static StringBuilder SB4log = new StringBuilder();
public static string AppPath()
{
string appRoot;
try
{
string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
SaveLog($"->App Path: {appDir}", true); // culprit
int loc = appDir.IndexOf("BURS");
appRoot = appDir.Substring(0, loc + 5);
}
catch (Exception ex)
{
// Exception response and MessageBox
}
return appRoot;
}
public static string ConsolePath() {}
public static string UIPath() {}
public static string LogPath()
{
string appRoot = AppPath();
string wrkDir = #"_Library\Data\BURS_Log.Txt";
string fullDir = $"{appRoot}{wrkDir}";
SaveLog($"->Log Path: {fullDir}\n", true); // culprit
return fullDir;
}
}
In stepping through the code the code the variable containing the path -- filePath -- has the expected value: "D:\BURS_Library\Data\BURS_Log.Txt" (quotes used to show there re no unintended spaces needing to be trimmed). Acordinng to MSDN if it's a malformed path an exception will be thrown but the path looks valid to me.
Why isn’t the Path variable utilized?
Any help will be appreciated.
Edit: expanded code to show start-to-finish flow since the original abridged version seemed to be confusing. Have added the text "//culprit" to the two lines which caused the error as pointed out by the responders.
It's not clear what Connections is, but given Connections.LogPath(); it seems that you're calling LogPath(); to set the value for filePath which is a problem because that calls AppPath which has the following statement SaveLog($"->App Path: {appDir}", true);.
You haven't included a version of SaveLog that has 2 parameters, but assuming it's similar to the one you've posted, you're attempting to use filePath when the value hasn't been set yet - which causes an issue.
I am currently using the Microsoft.Practices.EnterpriseLibrary.Logging but I can't find a way to control where the file is written to except through pre-runtime configuration.
I am looking at System.IO.Log, but it only seems to create a binary file that cannot be viewed by a simple text editor.
Is there a way to produce a flat text file with System.IO.Log?
or
Is there a way to control the location of the log file at runtime using Microsoft.Practices.EnterpriseLibrary.Logging
I do not know if this helps but here goes.
public class Logger
{
public void WriteToLog(string messageText)
{
// echo message to console
Console.WriteLine(messageText);
string strLogFile = "C:\\Users\\gandalf\\Documents\\Visual Studio 2000\\Projects\\fasterTest_Log.txt";
string strLogText = messageText;
// Create a writer and open the file:
StreamWriter log;
if (!File.Exists(strLogFile))
{
log = new StreamWriter(strLogFile);
}
else
{
log = File.AppendText(strLogFile);
}
// Write to the file:
log.WriteLine(DateTime.Now + " : " + strLogText);
// Close the stream:
log.Close();
}
}
My C# console program copies 2 folders into 1. It works but I am new to C#. I cant figure out how I make the program skip the alert window "are you sure you want to overwrite the files".
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualBasic.FileIO;
using System.Diagnostics;
namespace MirrorSystem {
class Program {
static void Main(string[] args)
{
string source1 = #"folder1";
string source2 = #"folder2";
string destination = #"destination";
try
{
Console.WriteLine("Starting..");
FileSystem.CopyDirectory(source1, destination, UIOption.AllDialogs);
FileSystem.CopyDirectory(source2, destination, UIOption.AllDialogs);
Console.WriteLine("Success!");
System.Threading.Thread.Sleep(5000);
Environment.Exit(0);
Console.ReadKey();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
Console.ReadKey();
}
}
}
}
You can pass the value true as the third (overwrite) parameter. Here is the official documentation for the method:
public static void CopyDirectory(
string sourceDirectoryName,
string destinationDirectoryName,
bool overwrite
)
The description of the overwrite parameter:
overwrite
Type: System.Boolean
True to overwrite existing files;
otherwise False. Default is False.
Source.
You can use method File.Copy --> https://msdn.microsoft.com/es-es/library/9706cfs5(v=vs.110).aspx
The third parameter allows you to specify whether you should or should not overwrite existing files with the same name in the destination folder.
This question already has answers here:
How can I save application settings in a Windows Forms application?
(14 answers)
Closed 7 years ago.
I would like to ask you if anyone of you knows how can I save changes in the progrem so when It will be restarted, the changes would remain?
for example, I have a boolean variable which his defualt value is "false".
I want after the inital start, change the value to "true" so when I'll close and start the program, the boolean variable value would be true.
That's what we have databases for...
or config files
or file systems
You need to retain data, which cant be in memory it has to be on disk
Read about various data persisting strategies try out things and let us know if you are stuck
Choose format you want to use for persisting you data. On Application starts - read file and deserialize it to your model. On Close - serialize it and save to file. Take a look at next question: Best practice to save application settings in a Windows Forms Application
Next sample was taken from the above link:
using System;
using System.IO;
using System.Web.Script.Serialization;
namespace MiscConsole
{
class Program
{
static void Main(string[] args)
{
MySettings settings = MySettings.Load();
Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
Console.WriteLine("Incrementing 'myInteger'...");
settings.myInteger++;
Console.WriteLine("Saving settings...");
settings.Save();
Console.WriteLine("Done.");
Console.ReadKey();
}
class MySettings : AppSettings<MySettings>
{
public string myString = "Hello World";
public int myInteger = 1;
}
}
public class AppSettings<T> where T : new()
{
private const string DEFAULT_FILENAME = "settings.jsn";
public void Save(string fileName = DEFAULT_FILENAME)
{
File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
}
public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
{
File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
}
public static T Load(string fileName = DEFAULT_FILENAME)
{
T t = new T();
if(File.Exists(fileName))
t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
return t;
}
}
}
I searched pretty much everywhere on google, but I didn't find anything useable. I want to know how to get the current cache and save it on a string. This string will get processed and afterwards replace the current cache.
I am talking about our ordinary copy cache (CTRL + C) on Windows.
Use the System.Windows.Forms.Clipboard.GetText()
http://msdn.microsoft.com/en-us/library/kz40084e.aspx
Example from MSDN:
// Demonstrates SetText, ContainsText, and GetText.
public String SwapClipboardHtmlText(String replacementHtmlText)
{
String returnHtmlText = null;
if (Clipboard.ContainsText(TextDataFormat.Html))
{
returnHtmlText = Clipboard.GetText(TextDataFormat.Html);
Clipboard.SetText(replacementHtmlText, TextDataFormat.Html);
}
return returnHtmlText;
}
First in your console application add reference to System.Windows.Forms.dll via the Solution Explorer window. Then you should be able to add using System.Windows.Forms.
Here is some sample code to read clipboard text from your console application (important : you need the [STAThread] attribute added to your Main as shown below; else there will be a ThreadStateException thrown)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SampleConsole
{
class Program
{
[STAThread]
static void Main(string[] args)
{
if (Clipboard.ContainsText(TextDataFormat.Text))
{
string clipBoardText = Clipboard.GetText(TextDataFormat.Text);
Console.WriteLine("TEXT in ClipBoard : " + clipBoardText);
Console.WriteLine("Type text to replace (and press Enter key) :");
string replaceText = Console.ReadLine();
Clipboard.SetText(replaceText);
Console.WriteLine("REPLACED ClipBoard Text : " + Clipboard.GetText(TextDataFormat.Text));
}
else
{
Console.WriteLine("No text in clipboard, please type now (and press Enter key) :");
string newText = Console.ReadLine();
Clipboard.SetText(newText);
Console.WriteLine("NEW ClipBoard Text : " + Clipboard.GetText(TextDataFormat.Text));
}
Console.Read();
}
}
}