Click here to Skip to main content
13,254,154 members (60,873 online)
Click here to Skip to main content
Add your own
alternative version


73 bookmarked
Posted 25 Dec 2007

Windows Service which Kills Unwanted Windows

, 8 Jan 2008
Rate this:
Please Sign up or sign in to vote.
Written in C# Windows service which monitors all Windows and kills unwanted ones.


The main goal of this project is to create a Windows service in C# which will monitor all appearing Windows and kill unwanted ones.

This sample project is an illustration for two topics:

  1. Use of PInvoke, and
  2. Writing a Windows service in C#


Some time ago, I had two phone interviews and one on-site interview with Google. That was fun (you know those crazy puzzles they like to ask at Google interviews!) and I enjoyed that, but when I was denied without any reasonable explanation, I became so mad that I decided to write this service to kill any Internet browser on my PC as soon as user dialed in the address bar. Now I think this project could be useful for those who want to automatically kill some unwanted popups on their computers. For example, this approach could be used to kill some Windows ToolTips after some timeout because they can stay on the desktop forever if there is no user activity.

Using the Code

There are two stages if you want to kill some window:

  1. Find a handle to this window, and
  2. Close this window

It looks like to find a window there is an API call FindWindowEx and that was my first approach, but very soon I figured out that it doesn't work well for all kind of windows, for example, it doesn't work for tooltip popups because their title is their content. So, I've tried another approach - using another API call EnumWindows. This API call requires two parameters - pointer to callback function and some structure - to be passed. In the code snippet below, we use member m_hwndFound to return the result of a search:

CallBackPtr callBackPtr = new CallBackPtr(ReportWindow);
m_hwndFound = IntPtr.Zero;
EnumWindows(callBackPtr, new PopupWinow(classToKill, titleToKill));
if (m_hwndFound != IntPtr.Zero)
{... do something if window is found ...}

This code uses class PopupWindow...

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
public class PopupWinow
  public string wClass = "tooltips_class32";
  public string wTitle = "";

  public PopupWinow(string wclass, string wtitle)
    wClass = wclass;
    wTitle = wtitle;

... and callback method ReportWindow which must return true to continue enumeration and false to stop it if a window is found:

private IntPtr m_hwndFound = IntPtr.Zero;
private bool ReportWindow(IntPtr hwnd, PopupWinow lparam)
  // Set the user interface to display in the
  // same culture as that set in Control Panel.
  Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

  string classToKill = lparam.wClass;
  string titleToKill = lparam.wTitle;

  // Get the window title
  StringBuilder sbTitle = new StringBuilder(1024, 1024);
  IntPtr nbytes = SendMessage(hwnd, /*WM_GETTEXT = 
            */0x000D, new IntPtr(sbTitle.Capacity), sbTitle);
  string wTitle = sbTitle.ToString();

  //Get the window class name
  StringBuilder sbClass = new StringBuilder(100);
  int res = GetClassName(hwnd, sbClass, sbClass.Capacity);
  if (res == 0) return true; // just continue enumeration
  string wClass = sbClass.ToString();

  // Check if requested window is found
  if ((wTitle == "" && titleToKill == "") || (wTitle != "" && wClass == classToKill))
    if (wTitle.IndexOf(titleToKill) != -1)
      m_hwndFound = hwnd;
      return false; // stop enumeration
  return true; // continue enumeration

After the window handle is found we can close it. Note that for different classes of Windows, we have to use different "close window" calls:

switch (popupType)
  case PopupWindowType.Tooltip:
    // tooltip window found --> gently close it 
    // (if use WM_CLOSE message the balloon will be closed forever!)
    nbytes = SendMessage(m_hwndFound, /*WM_LBUTTONDOWN = */0x0201, 0, IntPtr.Zero);

  case PopupWindowType.Edit:
  case PopupWindowType.IEFrame:
  case PopupWindowType.MozillaUIWindowClass:
  case PopupWindowType.MessageBox:
    // message box window found --> close it
    nbytes = SendMessage(m_hwndFound, /*WM_CLOSE = */0x0010, 0, IntPtr.Zero);


If you want to kill some Windows other than default for this solution just change call to KillPopupWindow:

m_windowFinder.KillPopupWindow(<some word from window title>, <some PopupWindowType>);

To find out a window title and class, you can use Microsoft Spy++ utility which comes with SDK.

To install this service, use regular InstallUtil.exe utility which is a part of the .NET Framework.

Service Startup Parameters

Recently I used this service in my practice. I opened some website in one of the tabs in Internet Explorer and was faced with a lot of error message boxes with 'Yes' / 'No' choices. I was tired of clicking on the 'No' button and did not want to kill Internet Explorer because I did not want to lose many other opened tabs there. So, I decided to use this service to kill all those error Windows automatically. The trick is that it's not possible to close Yes/No Windows just sending them WM_CLOSE message. To close them, we need to find their 'Yes' or 'No' child button window and send it WM_LBUTTONUP message. Here is how to do that:

switch (popupType)
  case PopupWindowType.MessageBox:
    // message box window found --> close it
    if (m_buttonToClick == "")
      nbytes = SendMessage(m_hwndFound, /*WM_CLOSE = */0x0010, 0, IntPtr.Zero);
      // Find child button window and click it!
      IntPtr button = FindWindowEx(m_hwndFound, IntPtr.Zero, "Button", m_buttonToClick);
      if (button != IntPtr.Zero)
        nbytes = SendMessage(button, /*WM_LBUTTONDOWN = */0x0201, 0, IntPtr.Zero);
        nbytes = SendMessage(button, /*WM_LBUTTONUP = */0x0202, 0, IntPtr.Zero);

I also modified the OnStart method to parse parameters to make it possible to start the service to kill different types of Windows. For details, see the downloaded solution. Here is the example of service startup parameters if you want to kill popups with title "Error" and buttons "Yes" and "No" (500 is polling interval in ms):

Error #32770 500 &No

Make Service Self-Installable

For me, it's very painful to install/uninstall services using InstallUtil application. To avoid this, we can use another set of API functions to control Service Control Manager. I added a special class ServiceInstaller to the solution to manage that. This class is a helpful wrapper for API calls to advapi32.dll to perform install, uninstall, start and stop service.

Here is the most complicated method InstallService:

public static bool InstallService(string svcPath, string svcName, 
        string svcDispName, string svcDescription, bool bRun)
  // Open Service Control Manager
  IntPtr hSCM = OpenSCManager(
    null, // lpMachineName
    null, // lpSCDB
    (uint)Win32Methods.SCM_ACCESS_TYPE.SC_MANAGER_CREATE_SERVICE // scParameter
  if (hSCM == IntPtr.Zero) return false;

  // Create the service
  IntPtr hService = CreateService(
    hSCM,       // SC_HANDLE
    svcName,    // lpSvcName
    svcDispName,// lpDisplayName
    Win32Methods.SERVICE_ALL_ACCESS,                           // dwDesiredAccess
    (uint)Win32Methods.SERVICE_TYPE.SERVICE_WIN32_OWN_PROCESS, // dwServiceType
    (uint)Win32Methods.SERVICE_START_TYPE.SERVICE_AUTO_START,  // dwStartType
    (uint)Win32Methods.SERVICE_ERROR_CODE.SERVICE_ERROR_NORMAL,// dwErrorControl
    svcPath,    // lpPathName
    null,       // lpLoadOrderGroup
    IntPtr.Zero,// lpdwTagId
    null,       // lpDependencies
    null,       // lpServiceStartName
    null        // lpPassword
  if (hService == IntPtr.Zero)
    return false;

  // Change service description
  if (!ChangeServiceConfig2(
    hService,                  // handle to service
    ref svcDescription          // value: new description
    return false;

  // Set check box "Allow service to interact with desktop" 
  // checked to allow service show popup messages.
  OperatingSystem os = Environment.OSVersion;
  if (os.Version.Major < 6) // 6 is Vista: service cannot interact with desktop on Vista
    System.ServiceProcess.ServiceController serviceController = 
            new System.ServiceProcess.ServiceController();
    serviceController.ServiceName = svcName;
    ConnectionOptions coOptions = new ConnectionOptions();
    coOptions.Impersonation = ImpersonationLevel.Impersonate;

    ManagementScope mgmtScope = 
        new System.Management.ManagementScope(@"root\CIMV2", coOptions);

    ManagementObject wmiService = new ManagementObject
                    ("Win32_Service.Name='" + svcName + "'");
    ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
    InParam["DesktopInteract"] = true;

    ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);


  // Run service
  if (bRun) return RunService(svcName);
  return true;

This code uses calls to advapi32.dll functions implemented in Win32Methods class (see downloaded solution for details).

Now you can install/uninstall this service calling it from the command line like this...

WindowKiller -a

... where the parameter -a means "auto" install/uninstall depending on the current service status. To get help on other command line parameters, you can call the service with -h parameter.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior) Intel Corp.
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionWindows Api FindWindow do not work Pin
Member 1023634811-Aug-16 22:31
memberMember 1023634811-Aug-16 22:31 
Generaldoesn't work :( Pin
ashex_14321-Jul-08 4:00
memberashex_14321-Jul-08 4:00 
GeneralRe: doesn't work :( Pin
Victuar7-Sep-08 22:37
memberVictuar7-Sep-08 22:37 
GeneralRe: doesn't work :( Pin
Victuar9-Sep-08 8:51
memberVictuar9-Sep-08 8:51 
JokeGreat, also for other usages Pin
protix11-Jan-08 3:48
memberprotix11-Jan-08 3:48 
JokeTake that google! Pin
Ben Daniel8-Jan-08 21:23
memberBen Daniel8-Jan-08 21:23 
GeneralExcellent Pin
Vyskubov7-Jan-08 8:05
memberVyskubov7-Jan-08 8:05 
Generalthe smell of C++ Pin
Thanks for all the fish2-Jan-08 11:36
memberThanks for all the fish2-Jan-08 11:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171114.1 | Last Updated 8 Jan 2008
Article Copyright 2007 by Victuar
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid