308075 308075 - 1 month ago 6
C# Question

Counting how many occurences have been between datetimes

public void getCountUsers()
{
number = 0;
//UserList = new ObservableCollection<Users>();
UserList = new List<Users>();
EventLog myNewLog = new EventLog();
myNewLog.Log = "Security";
foreach (EventLogEntry entry in myNewLog.Entries)
{
if (entry.InstanceId == 4624 && entry.TimeWritten.Date == DateTime.Today)
{
Regex ip = new Regex(@"192");
Match IP = ip.Match(entry.ReplacementStrings[18]);
Regex tester = new Regex(@"127");
Match Tester = tester.Match(entry.ReplacementStrings[18]);
if (Tester.Success || IP.Success)
{
if (UserList.Count > 0)
{
bool check = false;
foreach (var user in UserList)
{
if (user.User == entry.ReplacementStrings[5])
{
user.countUsers += 1;
check = true;
}
}
if (!check)
{
Users u = new Users(1, entry.ReplacementStrings[5]);
UserList.Add(u);
}
}
else
{
Users u = new Users(1, entry.ReplacementStrings[5]);
//UserList = new ObservableCollection<Users>();
UserList = new List<Users>();
UserList.Add(u);
}
}
}
}
}


This is what I use to count up how many users have been on one day. What I need to retrieve is how to filter the peak hour of the day, and how many people were online on that peak hour, and whom were in it.

(So for example 12:00 has 1 user and 15:00 has 15, 15:00 is the peak hour with 15 users in total)

If you need any more information, I would gladly edit.

Edit:

foreach (EventLogEntry entry in myNewLog.Entries)
{

if (entry.InstanceId == 4624 && entry.TimeWritten.Date == DateTime.Today)
{
Regex ip = new Regex(@"192");
Match IP = ip.Match(entry.ReplacementStrings[18]);
string userName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(entry.ReplacementStrings[5]);

Regex tester = new Regex(@"127");
Match Tester = tester.Match(entry.ReplacementStrings[18]);

if (IP.Success || Tester.Success)
{
Console.WriteLine(number +
". \t[Time of logon]\t\t" + entry.TimeWritten.ToLongTimeString() + "\t" + entry.TimeWritten.ToShortDateString() +
"\n \t[Username-logon]\t" + userName +
"\n \t[IP-Adress]\t\t" + entry.ReplacementStrings[18] +
"\n----------------------------------------------------------------------- ");
number++;
//Console.WriteLine(entry.TimeWritten.ToLongTimeString() + " ; " + entry.TimeWritten.ToShortDateString() + " ; " + entry.ReplacementStrings[5] + " ; " + entry.ReplacementStrings[18]);
}
}
}


Above outputs the first part, under outputs the second part.

public void showAmount()
{
int indexUsername = 0;
++indexUsername;
Console.WriteLine("\nGebruikers:");
foreach (var user in UserList.Where(u => u.User != "SYSTEM"))
{
string userName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(user.User);
//Console.WriteLine(indexUsername + ". " +" \t " + userName +"" + user.countUsers);
Console.WriteLine("#" +indexUsername + ".\t {0} has been online {1}x times ", userName, user.countUsers);
indexUsername++;
}
}


Output

Answer

Is this the kind of thing you're after?

public void getCountUsers()
{
    EventLog myNewLog = new EventLog();
    myNewLog.Log = "Security";

    var query =
        from EventLogEntry entry in myNewLog.Entries
        where entry.InstanceId == 4624
        where entry.TimeWritten.Date == DateTime.Today
        where new[] { "192", "127" }.Any(x => entry.ReplacementStrings[18].Contains(x))
        select new { entry.TimeWritten.Hour, User = entry.ReplacementStrings[5] };

    var result =
        query
            .GroupBy(x => x.Hour, x => x.User)
            .OrderByDescending(x => x.Count())
            .Take(1)
            .Select(x => new
            {
                Hour = x.Key,
                Users =
                    x
                        .GroupBy(y => y)
                        .Select(y => new Users(y.Count(), y.Key))
                        .ToList()
            })
            .First();

    Hour = result.Hour;
    UserList = result.Users;

}

query effectively replaces your code. It performs a loop over myNewLog.Entries and pulls out the entry.ReplacementStrings[5] value that you used to create the Users objects. I have added to this data the entry.TimeWritten.Hour value.

Now in the result variable I take the query and group the User property by Hour. Then I order by the descending count of users in each hour slot and when I .Take(1) I get the hour with the most users only. I then select the hour and do another grouping of user to create the Users objects - just like you did in your code - and finally I take .First() to get the highest populated hour out.

The final two assignments are only there to mimic your code.


Here's a way to produce your output string:

string output =
    String.Format(
        "Most active users were online on {0},{1} The users online at the peak was: {2}",
        TimeSpan.FromHours(result.Hour),
        result.Users.Count(),
        String.Join(", ", result.Users.Select(x => x.User)));