Please wait for system event notification service

This is a very nasty error which happens from time to time on Windows 2008 R2 machines.
A user tries to logon to the machine via RDP, or perform a logout. The screen he sees is hanging with the following message:

Please wait for system event notification service

Of course, one solution is to reboot the machine.

What if it is not possible due to certain reasons?

You can read a lot about it on the web, but none of the solutions was suitable for me.

The first option is to go to run services.msc and try to restart the „System Event Notification Service„. In my case it failed with a message, that the service could not be restarted because it did not respond in a timely fashion.

Last resort, a bit hardcore, but working:

  1. On the machine, run the command prompt as an administrator
  2. type sc queryex sens
  3. you’ll get some properties, including the process ID (PID), e.g. 123.
  4. Now you can kill the process with following command: taskkill /PID 123 , using the PID from previous step
  5. You should get a message „SUCCESS: The process with PID 123 has been terminated.
  6. If it still does not work, use the force parameter, like this: taskkill /PID 123 /F
  7. Then, go back to services list, and start the System Event Notification Service

Hope it helps.
Łukasz

SharePoint: „Loading this assembly would produce a different grant set from other instances” after a security patch from MS

Hello,

after installing the critical patches for .NET framework, as described in the MS Security Bulletin MS11-100, some of our MOSS 2007 applications were hitting the following exception:

FileLoadException : Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401

It seems that the security fix applied in the patch KB2657424 (maybe also KB2656351, although it’s a different version of .NET framework) has caused this temporary problem. The solution is to recycle the affected applications’ IIS pool – the exceptions don’t occur anymore and applications work correctly again.
The solution with restarting application pools appears to be quite strange, since the whole machine had to be restarted upon installation of those security updates. But still, it worked.

Hope this helps,
Łukasz

Finding Active Directory user’s group membership in C#

Hi there,

there are a couple of ways to programmatically find a user and groups he belongs to in Active Directory. Recently I tested a few of them and here are some thoughts of what I found out.

DirectorySearcher

The System.DirectoryServices namespace provides us with a DirectorySearcher class. Filter property of that class can be used in order to specify the search query on the entire directory. An example filter for a user with login name ‘lkarolak’ could look like this:

(&(objectClass=user)(SAMAccountName=lkarolak))

If search is successful, the FindOne() method of the DirectorySearcher class should return an object of type DirectoryEntry. Finding this object’s membership requires iterating through its properties, finding the ones with name ‘memberOf’, and then (if needed) also performing some recursion in order to find out the nested group membership. After all, a bit complicated and quite resource-costly.

SearchRequest

Similar approach could be to use the SearchRequest and SearchResponse objects (this time from System.DirectoryServices.Protocols namespace), which are executed within a LDAP connection. The filter for the query looks just as in the previous example. Also in this case one has to recursively search within the result class’ (SearchResultEntry) attributes in order to get all the user’s nested groups.

Here’s a small example:

// establish a connection to LDAP
LdapDirectoryIdentifier id = new LdapDirectoryIdentifier(domain, port);
LdapConnection _connection = new LdapConnection(id);
_connection.SessionOptions.SecureSocketLayer = secureConnection;
_connection.AuthType = AuthType.Basic;
_connection.Credential = new NetworkCredential(ldapUser, ldapPassword);
_connection.Bind();

// distinguished name of the object 
// at which to start the search.
String _target = "dc=EXAMPLE,dc=COM";

String filter = "(&(objectCategory=person)(SAMAccountName=lkarolak))";
String[] attributesToReturn = { "SAMAccountName", "memberOf", "cn" };

SearchRequest searchRequest = new SearchRequest(_target, filter,
      SearchScope.Subtree, attributesToReturn);
SearchResponse response =
      (SearchResponse)_connection.SendRequest(searchRequest);

if (response.Entries.Count == 1)
{
  SearchResultEntry entry = response.Entries[0];
  for (int index = 0; index < entry.Attributes["memberOf"].Count; index++)
  {
      // get the group name, for example:
      String groupName = entry.Attributes["memberOf"][index].ToString();
  }
}

GroupPrincipal

The most interesting and straightforward solution to me was, however, another approach. Within the namespace System.DirectoryServices.AccountManagement we can find an easy way to find a user in AD and check his group memberships. Without having to recursively loop over the parent groups, we’re able to fetch the groups of the user, an much more data. The only constraint is that the code has to be run on a machine that is located within the domain. Let’s have a look at this sample code:

// "company" is the domain we would like to search in
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "COMPANY");

// get the user of that domain by his username, within the context
UserPrincipal up = UserPrincipal.FindByIdentity(pc, username);

// fetch the group list
PrincipalSearchResult groups = up.GetAuthorizationGroups();
GroupPrincipal[] filteredGroups = (from p in groups
           where p.ContextType == ContextType.Domain
           && p.Guid != null
           && p is GroupPrincipal
           && ((GroupPrincipal)p).GroupScope == GroupScope.Universal
           select p as GroupPrincipal).ToArray();

The last lines actually do the trick. The GetAuthorizationGroups() method would fetch all the security groups of the user. If we would also like to have the distribution groups of the user, we’d have to use the GetGroups() method instead. Of course one could want to filter out some groups, like „Everyone” etc., maybe with help of a LINQ query like here, or in another way.
Anyway, the GroupPrincipal object returned contains the properties we need in order to get the name of the groups of a user (first of all, the DistinguishedName property).

After some unit tests done, it seems also that this last method is the fastest approach of those three mentioned here, probably also due to lack of recursive functions.

Hope this helps,
Łukasz

Use command prompt to control remote desktop connections on Windows Server

Hello,

while working on Sharepoint applications running on Windows Server machines, we often need to connect to the server via Remote Desktop (e.g. in order to perform debugging). Those who work this way often are probably familiar with the standard limitations of Windows Server systems: only two concurrent remote desktop connections at a time. If you’re working alone, this shouldn’t be a problem, however, in teams, it may sometimes happen that you’re denied logging in onto the system with the warning:

„The terminal server has exceeded the maximum number of allowed connections.”

This may happen not only when your work mates are busy doing their job, but sometimes also you are the one who is occupying one or two sessions, without actually being working on the server. Such situations occur, for example, if your local remote desktop connection window doesn’t get closed properly, or due to instable local operating system.

What then? We are not physically on the server and we cannot log on. If you are one of the “blocked” server’s administrators, the command prompt comes to rescue.

First of all, we can check who is logged on on the server. To do this, first we have to perform authentication in order for the server to allow us actually do this. The simple solution is to map a share on the server: either via accessing the share in Windows Explorer ( \servernameshare ) and entering your username and password, or, the same but using command line:

net use /user:MyUsername \servernameshare

After successful authentication, we can now check who is actually logged on with the query session command:

query session /server:MyServerName

The server name can be replaced by the IP address of the machine. The output of this command could look like this:

command_terminal

Seeing such list, we now know who is logged on, so we can contact the proper person. But what if we ourselves are the ones who occupy the sessions? Then we can disconnect the sessions remotely, too. Having noted the ID of the session which we received via previous method, we can use it in the reset session command:

reset session 1 /server:MyServerName

Now the session is free and we can log on to the machine again.