Category Archives: Development - Page 3

List AD users in a group using powershell

This is not a rocket science thing since there are apparently multiple ways to do this but I had a specific requirement to quickly get a list of users for a group but only list specific properties which include the “Title” property that is not available using the AccountManagement namespace.

So without mush further ado… here is a simple script that works for me.

# Read the input parameters $GroupName
param([string] $GroupName = $(throw write-host "Please specify the group name." -Foregroundcolor Red))

$Recurse = $true

$OutputFile = "GroupUsers.csv"
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$group=[System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($ct, $GroupName)
$members = $group.GetMembers($Recurse)

$columnNames = "Name,Title,Description"
$columnNames | Out-File -FilePath $OutputFile -Encoding 'UTF8'
foreach($user in $members){
    $DE = $user.GetUnderlyingObject()
    $output = $user.name + "," + $DE.title + "," + $user.description

    Write-Host $output
    $output | Out-File -FilePath $OutputFile -Encoding 'UTF8' -append
    $output = ""
}

In order to get to the ‘Title’ property I use the ‘GetUnderlyingObject’ method to get the DirectoryEntry object which do have the ‘Title’ property. This way it makes it possible to access any/all the ‘forgotten’ properties which they never implemented in the new namespace.
Additionally it also save the output to a CSV file.

Creating a Multi-instance self registering service

This is one of those things I’ve been wanting to do for a long time for my Event Scavenger pet project. Basically the requirement is this:

“Being able to have one executable (.exe) file that can be used multiple times for different service instances.”

It turns out it is not too hard to achieve this using C# and .Net 4.0 (might even work with older frameworks but haven’t tried it). It is an extension of my already improved self registering Windows Service extensions which make it possible to simply run the Service exe with a ‘-install’ command line parameter. With the latest additions a ‘named’ instance can also be specified. This means, in the Service Manager of Windows you can see the Service executable plus a command line parameter that makes it unique. It allows you to stop/start/manage it separately as an entity. This is exactly the same as how Microsoft BizTalk Server implements ‘Host Instances’.

Now lets get dirty with some code samples. The first code snippet shows (an example) part of main program.cs that handles the command like parameters.

string collectorName = "Default";		

if (args.Length > 0)
{                
  if (args[0].ToUpper() == "-INSTALL")
  {
              string serviceParameters = "";
    if (args.Length > 1)
    {
      collectorName = args[1];
                  serviceName = "Event Reaper - " + collectorName;
      displayName = "Event Reaper - " + collectorName;
                  serviceParameters = "\"-Collector:" + collectorName + "\"";
    }
    if (args.Length > 2)
      displayName = args[2];
    if (args.Length > 3)
      description = args[3];

    HenIT.Services.ServiceRegister.InstallService(
      System.Reflection.Assembly.GetExecutingAssembly().Location,
      serviceName,
      displayName,
      description,
                  serviceParameters);
    return;
  }
  else if (args[0].ToUpper() == "-UNINSTALL")
  {
    if (args.Length > 1)
    {
      collectorName = args[1];
                  serviceName = "Event Reaper - " + collectorName;
    }
    HenIT.Services.ServiceRegister.UnInstallService(
       System.Reflection.Assembly.GetExecutingAssembly().Location,
                 serviceName);
    return;
  }
  collectorName = HenIT.CommandLineUtils.GetCommand(args, "", "-Collector:");
}
if (collectorName.Length == 0)
  collectorName = Properties.Settings.Default.CollectorName;

ServiceBase[] servicesToRun;
servicesToRun = new ServiceBase[] 
{ 
  new EventReaperService() { CollectorName = collectorName }
};
ServiceBase.Run(servicesToRun);

All this section does is to check for the “-INSTALL” or “-UNINSTALL” parameters and then call the helper class that does the registration/unregistration. The Display name of the service instance is always prefixed with “Event Reaper – ” to grouped all instances visually together in Service manager.

InstallService

The ServiceRegister class only has two methods. InstallService is the first one and handles all the bits to gather login details, set properties and then register the service.

public static bool InstallService(string serviceExePath,
        string serviceName,
        string displayName,
        string description,
        string serviceParameters)
{
    bool success = false;
    try
    {
        string workingPath = System.IO.Path.GetDirectoryName(serviceExePath);
        string logPath = System.IO.Path.Combine(workingPath, "Install.log");
        ServiceStartMode startmode = ServiceStartMode.Automatic;
        ServiceAccount account = ServiceAccount.LocalService;
        string username = "";
        string password = "";
        bool delayedStart = true;

        InstallerForm installerForm = new InstallerForm();
        installerForm.StartType = ServiceStartMode.Automatic;
        installerForm.AccountType = ServiceAccount.User;
        installerForm.BringToFront();
        installerForm.TopMost = true;
        if (installerForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            startmode = installerForm.StartType;
            account = installerForm.AccountType;
            delayedStart = installerForm.DelayedStart;
            if (installerForm.AccountType == ServiceAccount.User)
            {
                username = installerForm.UserName;
                password = installerForm.Password;
            }


            Hashtable savedState = new Hashtable();
            ProjectInstallerForHelper myProjectInstaller = new ProjectInstallerForHelper(delayedStart);
            InstallContext myInstallContext = new InstallContext(logPath, new string[] { });
            myProjectInstaller.Context = myInstallContext;
            myProjectInstaller.ServiceName = serviceName;
            myProjectInstaller.DisplayName = displayName;
            myProjectInstaller.Description = description;
            myProjectInstaller.StartType = startmode;
            myProjectInstaller.Account = account;
            if (account == ServiceAccount.User)
            {
                myProjectInstaller.ServiceUsername = username;
                myProjectInstaller.ServicePassword = password;
            }
            myProjectInstaller.Context.Parameters["AssemblyPath"] = serviceExePath + " " + serviceParameters;

            myProjectInstaller.Install(savedState);
            success = true;
        }
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message, "Install service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
    }
    return success;
}

The class InstallerForm is simply a plain Windows Form to capture service properties like the username/password etc. I’m not showing its code here now. AssemblyPath is the actual property that Service manager use to launch the executable plus its parameters.

ProjectInstallerForHelper is an utility class that simply inherits from System.Configuration.Install.Installer. It looks like this:

internal class ProjectInstallerForHelper : System.Configuration.Install.Installer
{
    private ServiceProcessInstaller processInstaller;
    private System.ServiceProcess.ServiceInstaller serviceInstaller;

    public ProjectInstallerForHelper(bool delayedAutoStart = true)
    {
        processInstaller = new ServiceProcessInstaller();
        serviceInstaller = new System.ServiceProcess.ServiceInstaller();
        serviceInstaller.DelayedAutoStart = delayedAutoStart;

        Installers.AddRange(new Installer[] {
                processInstaller,
                serviceInstaller});
    }

    #region Added properties
    public string ServiceName
    {
        get { return serviceInstaller.ServiceName; }
        set { serviceInstaller.ServiceName = value; }
    }
    public string DisplayName
    {
        get { return serviceInstaller.DisplayName; }
        set { serviceInstaller.DisplayName = value; }
    }
    public string Description
    {
        get { return serviceInstaller.Description; }
        set { serviceInstaller.Description = value; }
    }
    public ServiceStartMode StartType
    {
        get { return serviceInstaller.StartType; }
        set { serviceInstaller.StartType = value; }
    }
    public ServiceAccount Account
    {
        get { return processInstaller.Account; }
        set { processInstaller.Account = value; }
    }
    public string ServiceUsername
    {
        get { return processInstaller.Username; }
        set { processInstaller.Username = value; }
    }
    public string ServicePassword
    {
        get { return processInstaller.Password; }
        set { processInstaller.Password = value; }
    }
    #endregion
}

UnInstallService

This is essentially just the reverse of InstallService.

public static bool UnInstallService(string serviceExePath, string serviceName)
{
    bool success = false;
    try
    {
        ServiceController sc = new ServiceController(serviceName);
        if (sc == null)
        {
            System.Windows.Forms.MessageBox.Show("Service not installed or accessible!", "Stopping service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
            return true;
        }
        if (sc.Status == ServiceControllerStatus.Running || sc.Status == ServiceControllerStatus.Paused)
        {
            sc.Stop();
        }
    }
    catch (Exception ex)
    {
        if (!ex.Message.Contains("was not found on computer"))
        {
            System.Windows.Forms.MessageBox.Show(ex.Message, "Stopping service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
        else
            return true;
    }
    try
    {
        string workingPath = System.IO.Path.GetDirectoryName(serviceExePath);
        string logPath = System.IO.Path.Combine(workingPath, "Install.log");

        ServiceInstaller myServiceInstaller = new ServiceInstaller();
        InstallContext Context = new InstallContext(logPath, null);
        myServiceInstaller.Context = Context;
        myServiceInstaller.ServiceName = serviceName;
        myServiceInstaller.Uninstall(null);
        success = true;
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message, "Uninstall service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
    }
    return success;
}

Summary

And this is basically the whole thing that allows you to create a Windows Service in C# that can handle multiple instances. There are a few things to keep in mind like the fact that all instances share the same config file unless you make a physical copy of the exe and config file to another directory and register it from there. Using this you can multiple services using different config all running side by side not affecting each other (hopefully hehe)

CreateSqlDBHelper – Tool to create and set up database from scripts

I’ve done it again. re-invented the wheel… uhm, no. But I did create a tool to create and set up a new sql server database from scripts that can be launched from the command line. This could be useful if you must automate the process of setting up a test database each time you need to run a new set of tests.

It works like this (coomand line options)

Usage: CreateSqlDBHelper.exe <server> <database> <data files path> <-d> <script1.sql [script2.sql …]>
Where
-d : drop database first

This allows you to specify a sql server/instance name, database name, path where the database files will be located plus any number of sql script files that needs to be run to set up a new database. Typically you’ll start by running scripts that will create tables, views, sprocs and also initial data rows etc. Optionally the tool can first ‘drop’ the existing database (but for now that requires a manual press ‘Y’ step). It makes use of the .Net 4.0 client framework plus SQL server SMO libraries – which come with SQL server…

You can find a copy of the tool here.

SQLScripter

I’ve been wanting to creating something like this for myself for a while. A simple tool to quickly create a backup copy of a SQL Server database ‘structure’ (or schema if you will). It is really a simple command line tool that simply takes a few parameters like server\instance name, database, output directory and a prefix name for the output files.

It creates separate files for Tables, Views and Stored procedures (which includes UDFs)

Example usage:

SQLScripter.exe <-s:server> <-d:database> [-od:outputDirectory] [-p:prefixFileName]

Grab it here (plain exe in a zip file). It make use of the .Net 4.0 client framework.

Event Scavenger 5

A quick heads up about a new version of my Event Scavenger tool/system that is coming. There are a whole lot of changes that build up on the existing functionality as far as the gathering service(s) and Administration are concerned. The Viewer part has (so far) being left unchanged so that a previous version Viewer tool can still access the new version database and Vice Versa.

Why things have changed?

The reasons for the update is simple to cater for some limitations I experienced myself with the tool/system. These include the following:

– Newly added Event Logs required a service restart so the gathering service (Event Scavenger service) could become aware of them.

– The original (Event Scavenger) service kept ‘open’ threads for each machine/log that needed to be ‘polled’. Most of the time each thread was left in a ‘sleeping’ state doing no work at all and just taking up resources.

– Only one instance of the collecting (Event Scavenger) service could run on a single machine – thus limiting it to only one database it can store logs into, one service that could be managed etc.

– Logs polled/imported into another database were set up ‘sort of’ separately from actual (machine)logs already in the current database. This made them (sort of) hard to managed.

– Setting up permissions for users was mostly a manual process.

Changes

To solve these issues the following changes have been made:

– The gathering service now spawn threads only for enabled machine/logs each time it ‘runs’ based on a master frequency. This is set to 60 seconds by default (but as always can be changed and now managed from the Admin tool itself). This solves both the 1st and 2nd points mentioned. A side effect is that the performance counters for each Machine/Log now have disappeared (may be a bad thing…). This also means the whole concept of Thread recycling have gone the way of the Dodo…

– The service is now ‘Multi instance’ aware so that multiple copies of the same service (each with its own physical copy of the exe and config file) can run separately ‘servicing’ different Event Logs/databases etc on the same machine. Each instance can thus operate totally independent doing totally its own thing. Multi-machine instances are still possible as before. To set up  a new ‘instance’ you simple make a copy of the service exe & config file (plus editing) and then use the “-install ‘<serviceName>’ ‘<displayName>’ ‘<Description>’ ” parameters on the service exe. The result is a separate entry in Service Manager which you can start/stop on its own.

– A Machine/Log entry now has another (sorta) state other than just be enabled/disabled. The 3rd ‘state’ is the option to have it being imported from another EventScavenger database. Using the Admin tool now makes it a lot easier to manage this.

– The Admin tool now has a simplistic view/editor to manage users in the database.

– The Admin tool also now provides a way to ‘manage’ the collectors (services). A simplistic way to stop/start/pause/continue services is built right into the tool.

– To set up the database is now a bit easier. I included a new (command-line) tool that simply runs the various sql scripts for you. Some editing of the scripts might still be required if you don’t like the default settings). You can always still do it manually.

[Update]

– Something new, the admin tool now has a simplistic way to manage ‘Reaper’ services so you can start/stop/pause services, manage a view of what physical services service what Collector name etc. At the moment the actual registration of a service is still a manual process but the admin tool shows you a help screen with instructions on how to set it up (or even unregister it).

New name

Because the ‘main’ service for collecting Event Logs changed I decided to give it a new name as well – Event Reaper (being a fan of the Mass Effect games must be obvious by now… 😉 ).  The name ‘Event Scavenger’ is now just a global name for the whole project/tool set. With the new multi instance support this means you can have multiple reapers (on the same box).

Source code

So far I’ve kept the changed source code ‘offline’ as it is now a totally new ‘branch’ of the original source code. The global version number has now being changed to 5 (and in fact – the default database name has now being changed to EventScavenger5) as it is not compatible with the previous version (with the exception of the viewer tool that works on both versions – for now…). Thus, previous version collector services and the Admin tool will not work anymore with the new database version – per design.

Release

I’m still in testing so no actual ‘Release’ has been made yet. I’ll post an update here when here is something that others can start playing with.

Update: A preview (Beta) can be found here. It is (should be) fully functional with all the above mentioned features already working.

MSMQ Monitor

I have this really old tool I create (literally) 10 years ago do help with some MSMQ related development stuff at the time. Since then I have hardly touched it (source code) but it still seems to work to this day – even on Windows 7. It was intended to help me/developers to ‘see’ what is going on inside some test queues while we were in the process of working with a system that we developed that uses the technology.

The ‘Tool’ is really simple yet really powerful to do just what it was intended – to monitor MSMQ queues and let you manipulate messages inside the queues. It can view/create/delete/resubmit and do all kind of crazy things with MSMQ messages. It even has a simple MSMQ stress tool built right in!

Some screenshots

MSMQ Monitor Main window

Queue options

MSMQ Monitor Queue options

Stress Tester

MSMQ Monitor Stress Tester

Of course, this tool is provided ‘as is’. I simply thought of sharing it if someone else might find it useful. The source code was/is written in plain old vb.net.

Grab it from here

VS2012 Express for Desktop

I’ve been waiting for this for a while so I was glad when they finally released this. Now for some initial feedback.

First off, the download was reasonable – size and speed wise. The installation was, lets just say ok – as I had to reboot since it had to update some libraries that were is ‘use’ at the time. Registration was also not too bad – since I have an old existing Hotmail/Live account where more of the details were already populated. Running it for the first time is where the shock comes in… it is as ugly as hell (reminds me death, all grey and boring). Unfortunately the same would apply to any of the other Express and even full versions of VS2012.

VS2012 Express For Desktop development

Functionality wise it provides just the very basics – not that you can expect anything more. Since I haven’t installed the ‘full’ express version I cannot comment on any other functionality that version might have. Anyway, The only templates worth mentioning is the Windows Forms, WPF and Console ones. Again, one cannot expect anything more of this release. Interestingly enough, when creating a new project the framework version cannot be changed on the ‘create project’ dialog screen. You can only change this ‘after’ the project has already been created.

One nice thing is that you can still create custom toolbars with ‘external’ commands – I use it to run a source backup tool I created some time ago. Another thing to remember is that this tool can be installed in Windows 7, unlike the full Express version that can ONLY be installed on Windows 8. The Web express version can also be installed on 7 (plus the TFS Express version).

If you excuse the way it looks (wearing shades to protect your eyes) then this tool is not that bad… Just wish they allowed old fashioned ‘themes’ to change the look and feel of the entire editor. Ah well, it is an ‘Express’ product… Fortunately you can import your VS 2010 color and font settings to get all your customizations back (even though it does moan about a whole bunch of settings that are not applicable to this edition which you can ignore)

In order to try it out you can follow this link.

Update:
If you like to change the overall theme and don’t like the built-in Light or Dark there are some more options if you look at this blog entry.

Getting list of disabled users in AD

Having to quickly help some colleagues find a list of all the currently disabled users on a domain I created a quick Powershell script (with some help from Google of course).

I suspect other people might also like to know how to do it so here is a copy of the script.

This script is easily modifiable to search for all kind of other ‘stuff’ in AD as well.

Enabling .Net 4.0 on Web server

Not being an active ‘web’ developer for some time I stumble across an issue to make a small .Net 4.0 web application to work on a new Windows 2008 R2 server. After copying the application files to the local server (inetpub) and even creating the application in IIS (with no warnings or indications of a problem) I tried to test the application from the local machine.

That’s when I got the ‘HTTP Error 404.2’ error with further details ‘The page you are requesting cannot be served because of the ISAPI and CGI Restriction list settings on the Web server.’. As usual I did not read the whole page again and went on to find an answer on Google which did not really help too much – but it did point me in the right direction. Eventually I went back and read the full error/warning page that actually list the solution…

The solution is to enable .Net 4.0 for IIS (this is a 64-bit machine) doing the following:

  1. Open the IIS Manager and navigate to the server level.
  2. In the Features view, double-click ISAPI and CGI Restrictions to verify that the Web service extension is set to Allowed.

At least next time I will know better (or find it quicker) 😉

Windows Command Centre

A few years ago I created a quick utility to simply bring together all the various configuration tools that are included inside Windows itself. The problem is that there are actually all these built-in tools and utilities but finding them sometimes require you to search or discover them by accident. The tool I created simply provides an easy way to get to a lot of them. Even in Windows 7 not everything is located in one place – especially the more ‘advanced’, older or legacy tools – e.g. ODBC settings. Additionally I added something simple to simply ‘list’ the installed .Net versions as well.

A quick summary of what it contains:

System

Control panel
Manage computer
System config
Registry editor
Performance monitor
Scheduled tasks
Locale

Regional settings
Date and time

.Net

List versions
Disable Explorer GAC view

Hardware

Device manager
Install hardware
Remove hardware
Power options
Disk management
Removable storage
Settings

Keyboard
Mouse
Display
Sound
Printer

Software

Add & remove programs
Default programs
Windows components

Services

Services
IISAdmin
Component services
ODBC

Security

Security centre
Firewall settings
User accounts
Policy
Local security settings

Connections

Network connections
Create share
Shared folders
Map network drive
Disconnect network drive
Internet options

Looks

Taskbar properties
Fonts
Folder options
Display themes

I’ve now simple recompiled the utility and created a very simple installer for it (one for x86 and one for x64)

x86 – https://dl.dropbox.com/u/20983/WindowsCommandCentreSetup.msi

x64 – https://dl.dropbox.com/u/20983/WindowsCommandCentreSetupx64.msi

I’ve tested it on Windows 7 and it use to work on Vista/XP as well. Unfortunately I cannot guarantee that it will work properly on Windows 8 if at all. All it requires is the base .Net 2.0 framework to work.