15 Jan 2016 @ 3:38 AM 

This is the first post in a short series. This post covers the determination of what executable is currently in the foreground.

What with all the hubbub regarding “Telemetry” privacy, and the like regarding Windows 10, I actually decided it would be interesting information to have for my own purposes to track some tidbits. In particular, I have decided it would be interesting to chart/track the various foreground applications I have open. How long, for example, do I use Visual Studio? My Web Browser? The Command Prompt? etc. I decided to take the most straightforward approach- a background program that merely logs, every few seconds, what the foreground application is. No need to complicate it too much- write out the data and then that data can be imported.

Even so, I have, however, hemmed and hawwed about whether it would be wise to even share it. Not, mind you, for any IP concerns- but rather whether it is wise to share code and logic that, while I was using it for a benevolent purpose, could easily be used for malicious purposes. It’s something of an ethical dilemma. Should we refrain from sharing code that could be used maliciously? I don’t think so, because pretty much any code can be used for malicious purposes. On the other hand- something like watching every program that is running in the background with no user intervention is something very easily co-opted for purposes against the users consent.

I’ve decided to share the code and it’s engineering anyway. Those seeking to write malicious code will be able to write that malicious code with our without help; there isn’t really a need to censor oneself based on what others might do with the information provided. Even if the road to hell is paved with the best intentions, I’m not the one putting those cobblestone bricks of good intentions onto the roadway, though I am responsible for stretching that analogy beyond the point where it is useful.

Engineering

Now, with that out of the way, we can turn to the program itself. I thought I would compartmentalize particular parts of it into different blog posts. It’s much easier to cover smaller parts of the program likely for the same reason we write code as a series of classes and methods, as it makes things easier to understand overall.

The core seems fairly straightforward- if we want to log foreground applications, we create a background program that uses a timer that will check the foreground program every, say, 5 seconds, and write out the foreground program to a log file. We’ll cover that part later- but to start with, we’ll want to be able to determine what the current foreground process is at any one time.

Retrieving the Foreground Process

Before we get to the plumbing, let’s explore this problem- how do we determine what the current foreground application is at a given time? We can use the GetForegroundWindow() API function to retrieve the foreground Window; we can then use that window hWnd and determine the ProcessID with the GetWindowThreadProcessID() function, and use that ProcessID in a Process.GetProcessByID call. At which point we can retrieve the executable file for the application by using the FileName property of the MainModule of that Process. The first order of business, is the NativeMethods.cs class, as we will be using Win32 API P/Invoke calls. This is, of course, not a strict requirement- realistically we can declare DllImport externals wherever we please, However, in C# it is considered good design to have Native Win32 Calls separated into a separate class as static methods. This makes a lot of sense, so I’ll be doing it here:

With that in place, we can write our function to get the Active Process:

This isn’t bulletproof, mind you- however, we can do two things to help that. First, we can check for 0 being returned from GetForegroundWindow. We can also check the return value of GetWindowThreadProcessId()- it returns 0 if the provided handle is not a Window Handle, which is a possible race condition. We can also wrap the call to GetProcessById() in an exception handler, to handle the race condition where we retrieve a Process ID but before we retrieve the Process itself, it terminates:

Now, this is all well and good. But perhaps we’ve not considered future additions. In particular, perhaps we want to retrieve the Window Text of that foreground Window as well? As it stands we’re returning one string result. If we want to add more information, we can encapsulate the return value into either a struct or a class. In this case, I’ve gone with a class:

Here I’ve chosen to add the WindowText. An instance of this class will be used as the return value of the GetActiveProcess() function. But, hold on a second- GetActiveProcess is a terrible name, isn’t it? since an Active Process is effectively one that is running (as opposed to, say, a suspended process). So let’s rename the function to GetForegroundProcess. Meanwhile, we’ll want to add the ability to retrieve the Window Text, as well. We do this by adding the appropriate Win32API functions to our NativeMethods class:

Then we can make appropriate revisions to the GetActiveProcess() method, including giving it a proper name. Furthermore, GetProcessId() doesn’t return null, so my checking for it in the original segment was unnecessary. Instead, we want to catch ArgumentException and InvalidOperationException. In those cases we should return null straight up because we cannot retrieve the Foreground Process at all so any result we give wouldn’t be reliable.

With these underpinnings in place, we can start to construct the code that makes use of it and polls the active process- and finally, we’ll look into creating a useful UI for the program- such as a Notification Icon that can be used to start or stop the logging, or to configure options such as the delay.

Have something to say about this post? Comment!

Posted By: BC_Programming
Last Edit: 15 Jan 2016 @ 03:38 AM

EmailPermalink
Tags
Categories: .NET, C#, Programming


 

Responses to this post » (None)

 
Post a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Tags
Comment Meta:
RSS Feed for comments

 Last 50 Posts
 Back
Change Theme...
  • Users » 44271
  • Posts/Pages » 365
  • Comments » 105
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight

PP



    No Child Pages.

Windows optimization tips



    No Child Pages.

Software Picks



    No Child Pages.

BC’s Todo List



    No Child Pages.