Accessing and Querying Event Log in Windows - c#

I was wondering how I could reach event Log entries. I have a client server application and it executes without problems. What i am looking for is all instances of log with the id of 1149. This log is of the remote connection entries. I have taken a piece of code, here it is.
string logType = "System";
string str = "";
EventLog ev = new EventLog(logType, System.Environment.MachineName);
int LastLogToShow = ev.Entries.Count;
if (LastLogToShow <= 0)
Console.WriteLine("No Event Logs in the Log :" + logType);
// Read the last 2 records in the specified log.
int i;
for (i = ev.Entries.Count; i >= LastLogToShow - 1000 ; i--)
{
EventLogEntry CurrentEntry = ev.Entries[i];
if (CurrentEntry.InstanceId == 1149)
{
str += "Event type: " + CurrentEntry.EntryType.ToString() + "\n" +
"Event Message: " + CurrentEntry.Message + CurrentEntry + "\n" +
"Event Time: " + CurrentEntry.TimeGenerated.ToShortTimeString() + "\n" +
"Event : " + CurrentEntry.UserName +"\n" +"\n";
}
}
ev.Close();
return str;
The thing is I get the 42567 index is out of bounds exception everytime. I also dont know if it will work after that, so questions may follow.
EDIT:
Indeed, the problem was me reaching out of the eventlog with my index like you guys said. Using this line for the loop solved my problem here and I am able to reach the eventlog now, if anyone is looking around, this solution worked for me, so thank you all so much.
for (i = ev.Entries.Count - 1; i >= 0; i--)

This for (i = ev.Entries.Count; i >= LastLogToShow - 1000 ; i--) is causing your error. I don't really get what you're trying to do here. For one if you have less than 1000 entries, your i can be negative. When you use a negative value as the index of an array you will get "index is out of bounds exception". When you are trying to process only the last 2 records (as your commentary above the for-loop suggests) you should just use this:
for (i = ev.Entries.Count - 1; i >= ev.Entries.Count - 2; i--)
Of course you will still have to check if there is more than 2 entries because if there are 0 entries, the code will still go into the for-loop and try to access the array with negative indexes:
if(ev.Entries.Count < 2)
return str;
for (i = ev.Entries.Count - 1; i >= ev.Entries.Count - 2; i--)
Edit: Also just noticed even if there are more than 1000 records, when you go into the for-loop for the first time you will have ev.Entries[ev.Entries.Count]. Since array-indexes are zero-based you have to substract 1 from the count to get the last element of an array.

I highly suggest you use C# Linq for this.
Add this namespace
using System.Linq;
Linq is very similar to SQL in how it works with the data. In your case:
List<string> stringLogs =
ev.Entries
.Where(t => t.InstanceId == 1149)
.Select(t => GenerateLogString(t))
.ToList();
public string GenerateLogString(EventLogEntry CurrentEntry)
{
return
string.Format("Event type: {0}\nEvent Message: {1}\nEvent Time: {2}\nEvent: {3}\n",
CurrentEntry.EntryType.ToString(),
CurrentEntry.Message + CurrentEntry,
CurrentEntry.TimeGenerated.ToShortTimeString(),
CurrentEntry.UserName)
}
You can then convert the string logs into a single string, like you have there.
string str = string.Join("/n", stringLogs);
If you want to select the top 2 logs (as your commentary suggests), add a .Take(2) to the query, like below.
List<string> stringLogs =
ev.Entries
.Where(t => t.InstanceId == 1149)
.Take(2)
.Select(t => GenerateLogString(t))
.ToList();

You just need to equal i to ev.Entries.Count -1.
i = (ev.Entries.Count -1)

Related

Grouping results from for-loop C#

First time asking a question on Stackoverflow, fingers crossed! I'm new to programming and I'm struggeling to solve an issue. I got this foor loop:
for (int i = 0; i < antal.Count(); i++)
{
tbxResultat.AppendText(namnLista.ElementAt(i) + " \t");
tbxResultat.AppendText(personnummerLista.ElementAt(i).ToString() + " \t");
tbxResultat.AppendText(distriktLista.ElementAt(i) + " \t");
tbxResultat.AppendText(antal.ElementAt(i).ToString() + newLine);
}
I want to group the results from the loop into 4 sections: first values 0-49, second 50-99, third 100-199 and fourth 199. I'm interested in seeing how many is in each section and having it printed right each section, like:
23
37
---------------------------------
Total count of 2 in first section.
I've tried putting the for-loop in if statments but with no success. The sortment of the list is done with bubble sort which i modified to take a List instead of array. Any tips in the right direction would be much appriciated!
/Drone
This code should be what you asked for. Note the while in there. It's not if because there may be groups with zero elements, so you have to handle those as well.
int groupLimit = 50;
int elementsInGroup = 0;
for (int i = 0; i < antal.Count(); i++, elementsInGroup++)
{
while (antal[i] >= groupLimit)
{
// Write summary here. Use elementsInGroup..
groupLimit += 50;
elementsInGroup = 0;
}
// Write one row here. I suggest building the string and calling only one AppendText..
}

How to append the suffix to be unique if there is a record with the same name in the database?

I'm in trouble with a little problem.
products are listed in the database. In the code column, the data is kept as follows:
"F-01, F-02, F-03, ..., X-99"
Customers may want to add external data to the system, but sometimes they want to add the same record.
To avoid these duplicates, I need to put a distinctive suffix like "-01" at the end of the line of code column.
I am developing this system in c # and I have developed such a logic:
int counter = 1;
var code = "F-" + productEntity.Code;
​
while (await uow.Repository<Product>().Query().AnyAsync(a => a.Code == code) == true)
{
code = code + "-" + counter;
counter++;
}
But what I noticed is that a record I added in the form of F-01-1 will turn into F-01-1-1 when it comes back to me.
I think I missed a very small point, but I can not reach my goal.
The expression code + "-" + counter; appends 3 strings together and return the result.
Say:
code is "F-01"
counter is 1
Then the expression above will be evaluated as such:
"F-01" + "-" + "1", that is "F-01-1"
If you reexecute your method, then the expression will be:
"F-01-1" + "-" + "1" that is "F-01-1-1"
And so on.
The solution is to split the code to extract the last part, which corresponds to the value of the counter. It is done with string[] parts = "F-01-1".Split('-'):
parts[0] = "F"
parts[1] = "01"
parts[2] = "1" which corresponds to the counter
So now int counter = int.Parse(parts[2]) + 1 will return the next value for counter 2.
And you can have your full code "F-01-2" returned by code = $"{parts[0]}-{parts[1]}-{counter}"

How can i make the FOR to loop backward ? Getting some errors

for (int i = uids.Count; i > 0; i--)
{
counting += 1;
if (counting == 30)
break;
string currentUidOnServer = uids[i - 1];
if (!seenUids.Contains(currentUidOnServer))
{
OpenPop.Mime.Message unseenMessage = client.GetMessage(i + 1);
newMessages.Add(unseenMessage);
seenUids.Add(currentUidOnServer);
allMessages.Add(unseenMessage);
int nProgress = (uids.Count - i + 1) * 100 / uids.Count;
backgroundWorker1.ReportProgress(nProgress, client.GetMessageCount().ToString() + "/" + i);
}
}
The variable uids contain 7038 items.
I want to report to the backgroundworker progresschanged event.
And it does reporting but it did backward started from 7038 and 100%
And i want it to report from 0% to 100% so i changed the FOR to
for (int i = uids.Count; i > 0; i--)
It was
for (int i = 0; i < uids.Count; i++)
The first error out of index exception was on the line
string currentUidOnServer = uids[i - 1];
So i changed it to [i - 1]
Now i'm getting exception on the line
OpenPop.Mime.Message unseenMessage = client.GetMessage(i + 1);
Since 7038 + 1 not exist.
So i messed it all.
How this two lines i have/had the exceptions should be ?
This is the typical way to do this:
for (int i = uids.Count - 1; i >= 0; i--)
Then, use uids[i] and maybe client.GetMessage(i), however I have no idea, what "client" is in your code
Arrays in C# (and all the other C-like languages) are zero-indexed, which means that the first item in the array is at position 0. Attempting to access an array index that is less than 0 or greater than or equal to the number of elements in the array will result in an error as you have seen.
The first form of your loop:
for (int i = uids.Count; i > 0; i--)
...produces a sequence of numbers (on your 7038-item array) from 7038 down to 1. Since 7038 is an invalid array index (1 past the end of the array) and the sequence doesn't include 0, the array access expressions in the loop all use i -1 to shift the entire sequence down by 1.
To properly reverse the for without changing any other code you need to produce a sequence from 1 up to 7038, like this:
for (int i = 1; i <= uids.Count; i++)
This is the direct opposite form of your original.
Personally I would prefer that the loop variable be the array index most of the time, and my first instinct when I see a > 0 condition in a for statement is that someone forgot to put the = in.
You could just reverse your array with Array.reverse() and then iterate over it using i++ as per your original approach
Oops I thought this was JavaScript question lol, o well the approach I said can conceptually be applied to any language, just need to find the array reverse for your language
If I understood correctly, originally i went from 0 to uids.Count - 1. If you can get back to that situation, then your formula for nProgress should be
int nProgress = (i + 1) * 100 / uids.Count;

Sorting and summation over a set of words gives incorrect result

I am having trouble with Project Euler's Problem 22
Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.
For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
What is the total of all the name scores in the file?
So far this is the first Euler problem I haven't been able to solve on my own, and I don't get what I'm doing wrong here. I'm coming up short by 1532 with this solution.
This is my code:
using (WebClient client = new WebClient())
{
try
{
tempString = client
.DownloadString("http://projecteuler.net/project/resources/p022_names.txt")
.Replace("\"", "");
}
catch (Exception)
{
MessageBox.Show("Error, check your internet connection!");
}
}
string[] names = tempString.Split(',');
Array.Sort(names);
int total = 0;
for (int i = 0; i < names.Length; i++)
{
int namescore = 0;
foreach (char c in names[i]) { namescore += (int)c - 64; }
total += namescore * (i + 1);
}
return total.ToString();
I think it might be a C# specific bug or quirk ?
As you noted, you cannot set the CurrentCulture, therefore set DefaultThreadCurrentCulture.
When I use
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.GetCultureInfo("hr-HR");
before any action, I get the same result you have. So, obviously, you should use
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.GetCultureInfo("en-US");
to achieve the expected output (other than mentioned in the comments it's not enough to do this in the ToString() method, cause it also affects sorting).
Okay, let's check step by step an try to find inconsistencies. I have the correct answer.
Initial data:
names.Length == 5163
names.Count(w=>!Regex.IsMatch(w,"^[A-Z]+$")) == 0
names.Sum(w=>w.Length) == 30959
Partial sums (after N elements):
500: 7139561
2500: 187773540
5000: 811204450
UPDATE:
I have one idea: Sort is locale-specific! Try Sort(StringComparison.Ordinal).
UPDATE2:
To switch culture, set thread culture or AppDomain culture to, say, CultureInfo("en-US").

Neat solution to a counting within a string

I am trying to solve the following problem but cannot find an elegant solution. Any ideas?
Thanks.
Input - a variable length string of numbers, e.g.,
string str = "5557476374202110373551116201";
Task - Check (from left to right) that each number (ignoring the repetitions) does not appear in the following 2 indexes. Using eg. above, First number = 5. Ignoring reps we see that last index of 5 in the group is 2. So we check next 2 indexes, i.e. 3 and 4 should not have 5. If it does we count it as error. Goal is to count such errors in the string.
In the above string errors are at indexes, 3,10 and 16.
in addition to the other excellent solutions you can use a simple regexp:
foreach (Match m in Regexp.Matches(str, #"(\d)(?!\1)(?=\d\1)"))
Console.WriteLine("Error: " + m.Index);
returns 3,10,16. this would match adjacent errors using lookahead with a backreference. handles repetitions. .net should support that. if not, you can use a non-backreference version:
(?<=0[^0])0|(?<=1[^1])1|(?<=2[^2])2|(?<=3[^3])3|(?<=4[^4])4|(?<=5[^5])5|(?<=6[^6])6|(?<=7[^7])7|(?<=8[^8])8|(?<=9[^9])9
A simple indexed for loop with a couple of look ahead if checks would work. You can treat a string as a char[] or as an IEnumerable - either way you can use that to loop over all of the characters and perform a lookahead check to see if the following one or two characters is a duplicate.
Sorry, not a C# man, but here's a simple solution in Ruby:
a="5557476374202110373551116201"
0.upto(a.length) do |i|
puts "error at #{i}" if a[i]!=a[i+1] && a[i]==a[i+2]
end
Output:
error at 3
error at 10
error at 16
Here's something I threw together in C# that worked with the example input from the question. I haven't checked it that thoroughly, though...
public static IEnumerable<int> GetErrorIndices(string text) {
if (string.IsNullOrEmpty(text))
yield break;
int i = 0;
while (i < text.Length) {
char c = text[i];
// get the index of the next character that isn't a repetition
int nextIndex = i + 1;
while (nextIndex < text.Length && text[nextIndex] == c)
nextIndex++;
// if we've reached the end of the string, there's no error
if (nextIndex + 1 >= text.Length)
break;
// we actually only care about text[nextIndex + 1],
// NOT text[nextIndex] ... why? because text[nextIndex]
// CAN'T be a repetition (we already skipped to the first
// non-repetition)
if (text[nextIndex + 1] == c)
yield return i;
i = nextIndex;
}
yield break;
}

Categories