Retrieve Date Information from a .txt file using c# - c#

namespace SimpleLicense
{
class Program
{
static void Main(string[] args)
{
string fileName = #"C:\\Temp\\test.txt";
try
{
// Check if file already exists. If yes, delete it.
if (File.Exists(fileName))
{
File.Delete(fileName);
}
// Create a new file
Directory.CreateDirectory(Path.GetDirectoryName(fileName));
using (StreamWriter sw = File.CreateText(fileName))
{
sw.WriteLine("Thermo Licensing System file");
sw.WriteLine("------------------------------------");
sw.WriteLine("Installed Date: {0}", DateTime.Now.ToString());
DateTime newDate = DateTime.Now.AddDays(31);
sw.WriteLine("License Expires After"+" "+newDate);
sw.WriteLine("Number of Days Remaining ");
sw.Close();
// sw.WriteLine("Add ");
// sw.WriteLine("Done! ");
}
// Write file contents on console.
using (StreamReader sr = File.OpenText(fileName))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
catch (Exception Ex)
{
Console.WriteLine(Ex.ToString());
}
}
}
}
Contents of .txt File
Thermo Licensing System file
------------------------------------
Installed Date: 20-05-2014 16:01:42
License Expires After 20-06-2014 16:01:42
Number Of Days Remaining
Hi Everyone,
I have written the above code to store date and time information to a .txt file as given above.I want that the information about the remaining days be stored in .txt file.As you can see today's date is 20-5-2014 and the license expires on 20-6-2014.So 30 should be printed next to Number Of Days Remaining.
If the user changes the system clock,and changes the date to say 21-5-2014, then 29Days should be printed next to Number of Days remaining
I also want that when the application is executed on a particular date, the date should be set to that date ie at installed date and should not change and the remaining days be calculated on the basis of Installed date
Can anyone help me to figure this out?
Thanks

This code will give you the number of days:
int numberOfDays = newDate.Subtract(DateTime.Now).Days;
sw.WriteLine("Number of Days Remaining: " + numberOfDays.ToString());

you can used below menioned code
var Remainingdays=(LicenseExpires-InstalledDate).TotalDays
and if you want in int days then
var Remainingdays=(LicenseExpires-InstalledDate).Days

I assume you want to do time limited version of software?
While code posted in previous answers is technically correct, you probably shouldn't use DateTime.Now as user can tamper with system clock and circumvent your measure. Get current date from another source, like:
http://www.worldtimeserver.com/
This has its disadvantages though, like increased startup time and what if a page or user's connection is down?
Better and easier solution would be to forget about time limitation and limit amount of times application can be started instead. Then you simply load number on opening program and write decreased one on closing.
Also, storing relevant values as plaintext (with helpful user-friendly descriptions no less!) is probably not a good idea as any halfway savvy user may just snoop through files and edit them in any text editor. You may want to use some kind of encryption algorithm like AES:
http://msdn.microsoft.com/pl-pl/library/system.security.cryptography.aes%28v=vs.110%29.aspx

Related

Store Date to a .txt file only once using c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have written code that stores the date to a .txt file as shown. I am able to store the current date and time. I want that the date should be set only once when the application is executed for the first time.
Installed Date: Set to the date when the application is executed the first time and should not change irrespective of how many time the application is executed
I am trying to implement 30Days licensing. I want that when the application is executed for the very first time, the date when he executed the application should be stored into the .txt file and should not change, so that the remaining days could be calculated on the basis of that. My main aim is to stop the user from using my application after 30 days
class Program
{
static void Main(string[] args)
{
string fileName = #"C:\\Temp\\test.txt";
try
{
// Create a new file
Directory.CreateDirectory(Path.GetDirectoryName(fileName));
using (StreamWriter sw = File.CreateText(fileName))
{
sw.WriteLine("Thermo Licensing System file");
sw.WriteLine("------------------------------------");
sw.WriteLine("Installed Date: {0}", DateTime.Now.ToString());
DateTime newDate = DateTime.Now.AddDays(30);
DateTime date = DateTime.Now;
sw.WriteLine("License Expires After"+" "+newDate);
int numberOfDays = newDate.Subtract(date).Days;
sw.WriteLine("Number of Days Remaining: " + " " + numberOfDays.ToString());
sw.Close();
}
// Write file contents on console.
using (StreamReader sr = File.OpenText(fileName))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
catch (Exception Ex)
{
Console.WriteLine(Ex.ToString());
}
}
}
Output (.txt file)
Thermo Licensing System file
------------------------------------
Installed Date: 20-05-2014 16:01:42
License Expires After 20-06-2014 16:01:42
Number Of Days Remaining
You're already checking to see if the file exists, so there's no need for a variable.
if (File.Exists(fileName)) {
// Test to make sure the contents of the file are something you
// created, and not another file with the same name.
}
else {
// Continue on with your logic to create the file and add the dates.
}

C# Time Stamp Issue

I am writing program events to a txt file as a log but the time stamps are not updating at each point. I have declared the following string:
string timeStamp = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff");
string taskComplete = (timeStamp) + " Task Complete";
which i am calling at different points through the program:
using (StreamWriter w_Log = new StreamWriter(file_Log, true))
{
w_Log.WriteLine(taskComplete);
w_Log.Close();
}
There are several more strings declared using timeStamp though the program as well. Here is an example of the log file:
2014/02/22 10:07:26.71 Process started
2014/02/22 10:07:26.71 Task Complete
2014/02/22 10:07:26.71 Task Complete
2014/02/22 10:07:26.71 Process complete, time elapsed: 0.496 seconds
As you can see, the time seems to be static even though it has taken 49ms to complete. When the program is run again, the time has changed to the current time but the same issue, the time written is the same throughout.
Do I need to use a different method or am I using this one incorrectly?
So, at step 1 you're defining a string as being DateTime.Now with a particular format
At each point, you're just showing the same string. The string is fixed, it's not going to invoke DateTime.Now each time you run it.
So if you want it to change - you're going to need to call DateTime.Now each time.
w_Log.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff") + " Task Complete ");
You are defining taskComplete as a string once and using it over and over again. It doesn't update regardless of how you define it. You could set it once now and leave your the method running for 10 years and it will still contain the same value.
You actually need to update the timestamp value each time you want to update it. If you were trying to limit the code in this method, you could do is change taskComplete to a method that returns a string with the updated timestamp
void SomeMethod()
{
//doing other stuff
using (StreamWriter w_Log = new StreamWriter(file_Log, true))
{
w_Log.WriteLine(GetTaskCompleteMessage());
w_Log.Close();
}
//doing other stuff
}
String GetTaskCompleteMessage()
{
string timeStamp = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff");
return = (timeStamp) + " Task Complete";
}
you should redefine your string each time you want to update your log as you are doing now the variable timeStamp was fixed during the lifetime of your class's instance
string timeStamp = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff");
string taskComplete = (timeStamp) + " Task Complete";
//here when you call the log method
using (StreamWriter w_Log = new StreamWriter(file_Log, true))
{
timeStamp = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff");
taskComplete = (timeStamp) + " Task Complete";
w_Log.WriteLine(taskComplete);
w_Log.Close();
}

if statements to evaluate multiple file dates

I am new to C# (less than a week), I have the following code that deletes a file on a volume. It is a back up file for an SQL database. And it keeps growing so periodically I have to rename the file and then delete it after a new file is backed up. I need to evaluate if the backup ran and then it is okay to delete the file.
using System;
using System.IO;
class Program
{
static void Main()
{
//
// Delete a file found on the D:\ volume.
// If the file is not found (File doesn't exist),
// then you will get an exception.
//
try
{
File.Delete(#"\\Fabtrol-2\Program Files (x86)\FabTrolBackUp\FT_Trans_Log_Appendedold.BAK"); // Try to delete
Console.WriteLine("Deleted"); // Success
}
catch (IOException ex)
{
Console.WriteLine(ex); // Write error
}
}
}
This is the logic. If I'm asking too much let me know:
If todays date is = Monday and file FT_FabTrol_Sun_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Tuesday and file FT_FabTrol_Mon_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Wednesday and file FT_FabTrol_Tues_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Thursday and file FT_FabTrol_Wed_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Friday and file FT_FabTrol_Thurs_Full.BAK ‘s date is less then 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Saturday and file FT_FabTrol_Fri_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
Else If todays date is = Sunday and file FT_FabTrol_Sat_Full.BAK ‘s date is less than 2 days old then it is okay to delete the file named FT_Trans_Log_Appendedold.BAK
You can simplify that logic greatly with: -
FileInfo info = new FileInfo(#"\\Fabtrol-2\Program Files (x86)\FabTrolBackUp\FT_Trans_Log_Appendedold.BAK");
if(DateTime.Now.AddDays(-2) > info.LastWriteTime.Date)
{
//Delete
}
All you need to do is iterate over all the files in your folder and delete the ones that are older than two days, right (that seems to be what your giant conditional statement comes down to)?
So, use the following line to get all the files in the folder:
string[] files = Directory.GetFiles(<folder name>);
Then, in a loop, iterate over all the file names in files and check, whether they are old enough.
To get the timestamp of the file, use FileInfo and LastWriteTime like this:
if(DateTime.Today - someFileInfoObject.LastWriteTime.Date > new TimeSpan(2,0,0,0))
{
File.Delete();
}
This code 1st checks if the file based on the day is less than 2 days old, then if it is it deletes the file FT_Trans_Log_Appendedold.BAK.
string dir = #"\\Fabtrol-2\Program Files (x86)\FabTrolBackUp\";
string fileName = dir;
switch (DateTime.Now.DayOfWeek)
{
case DayOfWeek.Monday:
fileName += "FT_FabTrol_Sun_Full.BAK";
break;
case DayOfWeek.Tuesday:
fileName += "FT_FabTrol_Mon_Full.BAK";
break;
case DayOfWeek.Wednesday:
fileName += "FT_FabTrol_Tues_Full.BAK";
break;
case DayOfWeek.Thursday:
fileName += "FT_FabTrol_Wed_Full.BAK";
break;
case DayOfWeek.Friday:
fileName += "FT_FabTrol_Thurs_Full.BAK";
break;
case DayOfWeek.Saturday:
fileName += "FT_FabTrol_Fri_Full.BAK";
break;
case DayOfWeek.Sunday:
fileName += "FT_FabTrol_Sat_Full.BAK";
break;
}
FileInfo fi = new FileInfo(fileName);
if (fi.Exists && DateTime.Now.AddDays(-2) > fi.LastWriteTime.Date)
{
(new FileInfo(dir + "FT_Trans_Log_Appendedold.BAK")).Delete();
Console.WriteLine("Deleted");
}
Personally for one weeks experience I would say you've jumped into the deep end.
I'm not going to provide code, rather direct you to improve your learning, this is referred to psuedo code
Look into streamwriter/reader and filewriter and fileinfo.
From this you can then read files, delete/rename/whatever you want really.
You then need to try and understand how could I validate what I'm doing.
Unfortunately for a beginner this is harder than you may think, possibly harder than the first two points for some people. Think from simple onwards, we developers usually over complicate things. This part is actually rather easy so long your file stuff is correct!
You may want to look into unit testing as this may help your validation.
Building on what #Gray commented, the FileInfo object will also let you know if it .Exists or not, alleviating the need to depend on the try/catch to know if a file is still there.
Consider the following:
static void Main()
{
FileInfo fi = new FileInfo(#"\\path\\to\\file.bak");
if(fi.Exists)
{
try
{
//because we can still get errors based on permissions etc.
fi.Delete();
Console.WriteLine("Deleted"); // Success
}
catch (IOException ex)
{
Console.WriteLine(ex); // Write error
}
}
}
Try below code.
string backupFile = #"\\Fabtrol-2\Program Files (x86)\FabTrolBackUp\FT_Trans_Log_Appendedold.BAK";
FileInfo fi = new FileInfo(backupFile);
DateTime fileCreatedDate = File.GetCreationTime(backupFile);
DateTime today = DateTime.Now;
if (today.DayOfWeek != DayOfWeek.Monday && fileCreatedDate > today.AddDays(-2))
{
fi.Delete();
}
Updated my answer to meet your requirements. Kinda weird, but I was bored. May be helpful if just to read.
//2 days
TimeSpan daysToKeep = new TimeSpan(2,0,0,0);
//The folder where the files are kept
DirectoryInfo backupFolder = new DirectoryInfo(#"\\Fabtrol-2\Program Files (x86)\FabTrolBackUp\");
//the Appendold.BAK file
FileInfo backupLog = new FileInfo(backupFolder.FullName + #"\FT_Trans_Log_Appendedold.BAK");
//the base name for the log files
string logName = "FT_FabTrol_{0}_Full.BAK";
//an array for the days of week that are part of the logname
string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
//get yesterday's log file name
string yesterdayLog = String.Format(logName, days[(int)DateTime.Today.AddDays(-1).DayOfWeek]);
//create file info
FileInfo logFile = new FileInfo(backupFolder.FullName + yesterdayLog);
//if the file exists, and it is less than 2 days old
try
{
if (logFile.Exists && (DateTime.Today - logFile.LastWriteTime < daysToKeep))
{
backupLog.Delete();
Console.WriteLine("success");
}
else
{
Console.WriteLine("log file either did not exist or is not ready to delete");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}

Search String takes a long time the first time only?

No shortage of search for string performance questions out there yet I still can not make heads or tails out of what the best approach is.
Long story short, I have committed to moving from 4NT to PowerShell. In leaving the 4NT I am going to miss the console super quick string searching utility that came with it called FFIND. I have decided to use my rudimentary C# programming skills to try an create my own utility to use in PowerShell that is just as quick.
So far search results on a string search in 100's of directories across a few 1000 files, some of which are quite large, are FFIND 2.4 seconds and my utility 4.4 seconds..... after I have ran mine at least once????
The first time I run them FFIND does it near the same time but mine takes over a minute? What is this? Loading of libraries? File indexing? Am I doing something wrong in my code? I do not mind waiting a little longer but the difference is extreme enough that if there is a better language or approach I would rather start down that path now before I get too invested.
Do I need to pick another language to write a string search that will be lighting fast
I have the need to use this utility to search through 1000 of files for strings in web code, C# code, and another propitiatory language that uses text files. I also need to be able to use this utility to find strings in very large log files, MB size.
class Program
{
public static int linecounter;
public static int filecounter;
static void Main(string[] args)
{
//
//INIT
//
filecounter = 0;
linecounter = 0;
string word;
// Read properties from application settings.
string filelocation = Properties.Settings.Default.FavOne;
// Set Args from console.
word = args[0];
//
//Recursive search for sub folders and files
//
string startDIR;
string filename;
startDIR = Environment.CurrentDirectory;
//startDIR = "c:\\SearchStringTestDIR\\";
filename = args[1];
DirSearch(startDIR, word, filename);
Console.WriteLine(filecounter + " " + "Files found");
Console.WriteLine(linecounter + " " + "Lines found");
Console.ReadKey();
}
static void DirSearch(string dir, string word, string filename)
{
string fileline;
string ColorOne = Properties.Settings.Default.ColorOne;
string ColorTwo = Properties.Settings.Default.ColorTwo;
ConsoleColor valuecolorone = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorOne);
ConsoleColor valuecolortwo = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorTwo);
try
{
foreach (string f in Directory.GetFiles(dir, filename))
{
StreamReader file = new StreamReader(f);
bool t = true;
int counter = 1;
while ((fileline = file.ReadLine()) != null)
{
if (fileline.Contains(word))
{
if (t)
{
t = false;
filecounter++;
Console.ForegroundColor = valuecolorone;
Console.WriteLine(" ");
Console.WriteLine(f);
Console.ForegroundColor = valuecolortwo;
}
linecounter++;
Console.WriteLine(counter.ToString() + ". " + fileline);
}
counter++;
}
file.Close();
file = null;
}
foreach (string d in Directory.GetDirectories(dir))
{
//Console.WriteLine(d);
DirSearch(d,word,filename);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
If you want to speed up your code run a performance analysis and see what is taking the most time. I can almost guaruntee the longest step here will be
fileline.Contains(word)
This function is called on every line of the file, on every file. Naively searching for a word in a string can taken len(string) * len(word) comparisons.
You could code your own Contains method, that uses a faster string comparison algorithm. Google for "fast string exact matching". You could try using a regex and seeing if that gives you a performance enhancement. But I think the simplest optimization you can try is :
Don't read every line. Make a large string of all the content of the file.
StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
string text = streamReader.ReadToEnd();
Run contains on this.
If you need all the matches in a file, then you need to use something like Regex.Matches(string,string).
After you have used regex to get all the matches for a single file, you can iterate over this match collection (if there are any matches). For each match, you can recover the line of the original file by writing a function that reads forward and backward from the match object index attribute, to where you find the '\n' character. Then output that string between those two newlines, to get your line.
This will be much faster, I guarantee it.
If you want to go even further, some things I've noticed are :
Remove the try catch statement from outside the loop. Only use it exactly where you need it. I would not use it at all.
Also make sure your system is running, ngen. Most setups usually have this, but sometimes ngen is not running. You can see the process in process explorer. Ngen generates a native image of the C# managed bytecode so the code does not have to be interpreted each time, but can be run natively. This speeds up C# a lot.
EDIT
Other points:
Why is there a difference between first and subsequent run times? Seems like caching. The OS could have cached the requests for the directories, for the files, for running and loading programs. Usually one sees speedups after a first run. Ngen could also be playing a part here, too, in generating the native image after compilation on the first run, then storing that in the native image cache.
In general, I find C# performance too variable for my liking. If the optimizations suggested are not satisfactory and you want more consistent performance results, try another language -- one that is not 'managed'. C is probably the best for your needs.

Reading and writing dates to the registry for trial version purposes

Here's what I want to do, I want to store the date the first time the program is installed and also store a date when was the program was last run. I want the code to check to see if it was more than 30 days since the installation so I can turn off features. I also want to check if the system date is less than the last opened date and if so write the installed date to 1/1/1901 to prevent the program from running.
Keeping in mind that this is not a consumer program but a business program I don't expect hackers to crack it, they may do but that is fine I simply want to give potential customers a reason to consider purchasing the program and the end of the trial will prompt this.
Q1: Does this sound reasonable?
Q2: How should I hide the fact these are dates so it's not easily identified and changed?
Many thanks
Lee
The Microsoft.Win32 namespace is what you need. You will want to look at the two following classes: Registry and RegistryKey.
You could store the hash code of your date within the registry key you will use.
Except that I would neither place it in the registry. The AppData folder is a better place, in addition to your local installation folder. Perhaps will you want to to use binaries with the System.IO namespace so that you can write binary data. The BinaryWriter and BinaryReader classes are probably what you will need to do this.
I would suggest the hidden common application data directory instead of the registry. And write the dates in binary format:
static string appDataFile;
static void Main(string[] args)
{
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
appDataPath = System.IO.Path.Combine(appDataPath, "MyApplication");
if (!System.IO.Directory.Exists(appDataPath))
System.IO.Directory.CreateDirectory(appDataPath);
appDataFile = System.IO.Path.Combine(appDataPath, "History.dat");
DateTime[] dates;
if (System.IO.File.Exists(appDataFile))
dates = ReadDates();
else
dates = new DateTime[] {DateTime.Now, DateTime.Now};
Console.WriteLine("First: {0}\r\nLast: {1}", dates[0], dates[1]);
dates[1] = DateTime.Now;
WriteDates(dates);
}
static DateTime[] ReadDates()
{
System.IO.FileStream appData = new System.IO.FileStream(
appDataFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);
List<DateTime> result = new List<DateTime>();
using (System.IO.BinaryReader br = new System.IO.BinaryReader(appData))
{
while (br.PeekChar() > 0)
{
result.Add(new DateTime(br.ReadInt64()));
}
br.Close();
}
return result.ToArray();
}
static void WriteDates(IEnumerable<DateTime> dates)
{
System.IO.FileStream appData = new System.IO.FileStream(
appDataFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
List<DateTime> result = new List<DateTime>();
using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(appData))
{
foreach(DateTime date in dates)
bw.Write(date.Ticks);
bw.Close();
}
}
I would not store this in the registry because it's really easy to change (at least in the places you can write). I would write it in the Local Data folder in a little file and encrypt it. Probably store it in a couple of places in case someone deletes the file.

Categories

Resources