Monday, March 25, 2013

PowerShell to convert SID to User name and vice versa

Recently when we were profiling for database performance using SQL Profiler, we could see some query hits are coming to DB server from an unknown user account. Unknown means the user name in the profiler result view,it shows the SID of the user instead of readable username. Initially we ignored those requests and the performance issues got resolved by tuning the SPs.

The story was over with success in the task. But one item got into my backlog. Its nothing but how to convert the sid to user name. SID is nothing but the secure identifier given to windows system objects. Initial google gives a command called wmic and the usage is as follows.


wmic useraccount get name,sid


I tried this command and it lists all the users in the active directory. Very difficult to figure out. I had to export   to excel and filter out. This thinks me to code and as always I selected C#.Net. It was so simple.


        static string GetUserNameFromSID(string sid)
        {
            SecurityIdentifier si=new SecurityIdentifier(sid);
            NTAccount ntAccount=(NTAccount)si.Translate(typeof (NTAccount));
            return ntAccount.Value;
        }


I created this program in my machine and it needs additional one more step of copying to the server and to make sure the server has the corresponding .net version. I forgot PowerShell again. This should have been done in PowerShell. Ported to PowerShell immediately and saw its good.



# Program to find windows user name from sid
  $sid="<sid string value>"
  $sidInstance = New-Object System.Security.Principal.SecurityIdentifier($sid)
  $ntAccount= $sidInstance.Translate([System.Security.Principal.NTAccount]);
  $ntAccount.Value



Is there a program required to find out the user name from sid? How the system admins are doing it? The chance of them coding to get the username from the sid is very less. So there must be a direct command. This directed me again to the wmic command. After some reading I could see that wmic is the command interface for our favorite WMI (Windows Management Instrumentation). It supports filtering. Yes getting user name from sid is simple as the below command which can be directly entered in command prompt.


wmic useraccount where sid="S-1-5-21-1411863409-2385935799-2106976

The take out from this experience is "Commands itself becoming programs". If we look at the command we can see there is a where condition :-)

Happy coding.

Monday, March 18, 2013

IIS HTTP Error 503 - Failed to find the RegisterModule entrypoint in the module DLL C:\Windows\System32\inetsrv\iis_ssi.dll

It started with an 503 http error while browsing WCF service hosted in IIS in one of my colleagues machine. He was able to find that the application pool is getting automatically stopped when he browse the service. I was pulled into this after his team members had tried for couple of hours.The error is simple as

"HTTP Error 503. The is service unavailable"

Since it is about automatic app pool stopping and disabling the same, I started from the event log. There were 2 clear entries in the System log about this incident.

First one was a warning
A listener channel for protocol 'http' in worker process '4752' serving application pool 'ASP.NET v4.0' reported a listener channel failure.  The data field contains the error number.

Followed by an Error
Application pool 'ASP.NET v4.0' is being automatically disabled due to a series of failures in the process(es) serving that application pool.

This shows a scope for getting more details in the application event log. Yes there was one application error.

Failed to find the RegisterModule entrypoint in the module DLL C:\Windows\System32\inetsrv\iis_ssi.dll.  The data is the error.

Now its more narrowed. The server side include module is not getting loaded or some issues while finding the entry point. I don't think the second sentence about data has any meaning. How the data becomes error? Actual trouble shooting starts from here
  1. First thing I checked was for the presence of iis_ssi.dll in the inetsrv folder. It was present.
  2. Next thing tried was to disable that module via IIS -> Features -> Modules -> ServerSideIncludeModule and select Remove. But it showed an security access related error message.
  3. Then I checked for permissions. I was not able to find the NetworkService in the Security tab of the file properties. Network Service is the user / service account which we use for the application pool. I gave permission to Network Service and restarted the IIS. But again failed.
  4. A research started at this time about iis_ssi.dll and ServerSideInclude module. We could see that its not an essential module for WCF to work. So decided to remove this feature from IIS. Went to appwiz.cpl -> Turn Windows features on or off -> Internet Information Services -> World Wide Web Services -> Application Development Features -> Server-Side Includes and unchecked the ServerSide Includes. It removed SSI feature from IIS and reconfigured it. Finally it asked a restart and after restart also the issue remained same.
  5. Last place about and IIS related config is the global configuration available at C:\Windows\System32\inetsrv\config\applicationHost.config file. So opened that file and searched for iis_ssi.dll. It gave an entry as follows

    <add name="ServerSideIncludeModule" image="%windir%\System32\inetsrv\iis_ssi.dll" />

    This means not only this entry but also all the references to "ServerSideIncludeModule" name needs to be removed. We saw around 4 places where the name is referred. Deleted all and restarted IIS. This time it worked.
  6. Below are some links which we got during debugging. Some says it may be due to web config file issues. To avoid that, we deleted all the applications from IIS and kept only one simple html file.
    1. http://mvolo.com/where-did-my-iis7-server-go-troubleshooting-503-quotservice-unavailablequot-errors/
    2. http://blogs.msdn.com/b/vpandey/archive/2009/08/04/http-error-503-the-service-is-unavailable.aspx
    3. Some sites mentioned that its a known issue in 64 bit machines it we host 32 bit apps. But our system is 32.
Looks like a chain of actions for troubleshooting.But it took total of 2 hours.

Tuesday, March 12, 2013

Get the binding used to call wcf service in implementation code

This is about how to find out what is the binding used to call WCF at service implementation method. These type of situation may come when you develop a WCF based application which exposes net.tcp binding to internal / intranet users and http binding to external public users. In the ideal case the service request must be processed in same way for external and internal users. But rarely there may be requirements to process it differently and in those scenarios we need to programatically determine how the service is called or which binding is used to invoke the WCF service. Below is the code to deal with the same.

string binding = OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri.Scheme;


The OperationContext is an important class when you want to deal with these kind of things. Its thread static property Current gives the details about current operation.You may explore that to find more details such as security and other stuff. The whole service side can be as follows.



    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }
    public class HelloWorldService : IHelloWorldService
    {
        public string SayHello(string name)
        {
            string binding = OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri.Scheme;
            return string.Format("Hello, {0}.You called me using {1} binding", name,binding);
        }
    }

Monday, March 4, 2013

C# V/S VB.Net - Difference in Literals

Recently I was going through C# code which I needed to port to VB.Net. Usually I take help of reflector to do these kind of tasks. ie Opens the dll in reflector and change the language, export the project. But since this piece of code is small, I thought of trying manually

It was all going smooth since I encounter the below line

return 3e3m;

I could understand that this suffix 'm' is a decimal literal by placing the mouse over the number.Thanks to Visual Studio. But how to convert this to VB.Net. Initially I tried copy pasting the same string. No chance. So as usual had to google. There is no direct comparison of literals even in wiki page which explains the difference between C# and VB.Net. The literal to denote decimal in VB.Net is 'D'. There are so many literals like 'm' in C# such as D for double,  f for float etc...which are not same in VB.Net.

Type
C#
VB.Net
char '' ('a') ""c ("a"c)
Int I (100I) I / % (100%)
Unsigned Int U / u (100U) UI (100UI)
Long L / l (-100L) L / & (-100&)
Unsigned Long UL / ul (100UL) UI (100UL)
float / Single F / f (102.2F) F / ! (102.2!)
double D / d (102.2D) R / # (102.2#)
decimal M / m ( 202.3M) D /@ (202.3D)
exponent E / e (2E3M decimal 2000) Replaced with value in editor
xml literals Not available  Direct xml string

Below are the links to literals in C# and VB.Net .

C#
http://msdn.microsoft.com/en-us/library/aa664672.aspx
http://www.dotnetperls.com/suffix

VB.Net
http://msdn.microsoft.com/en-us/library/dzy06xhf.aspx

Sunday, March 3, 2013

C# V/S VB.Net variable scope in using block

Recently there was a scenario faced by one of our colleague which brought one more difference between C# and VB.Net. Now it is related to the 'using' block.The difference can be summarized as

"In C# if we reinitialize a variable in the header of using block which is declared already in the higher scope,it overwrite the already declared variable.But in VB.Net if we try reinitialize already declared variable it will create a new variable only for the 'using' block.

This is little difficult to understand. Lets see in code.

Code Output
class Disposable : IDisposable
{
    string input;
    public Disposable(string arg)
    {
        input = arg;
    }
    public void Display()
    {
        Console.WriteLine(input);
    }
    public void Dispose(){}
}
public class Program
{
    static Disposable dispo = new Disposable("higher level");
    static void Main(string[] args)
    {
        using (dispo = new Disposable("using block level"))
        {
            dispo.Display();
        }
        dispo.Display();
    }
}


using block level

using block level


Public Class Disposable
    Implements IDisposable
    Dim input As String
    Public Sub New(arg As String)
        input = arg
    End Sub
    Public Sub disp()
        Console.WriteLine(input)
    End Sub
    Public Sub Dispose() Implements IDisposable.Dispose 'Implement later
    End Sub
End Class

Module Module1
    Dim dispo As New Disposable("higher level")
    Sub Main()

        Using dispo = New Disposable("using block level")
            dispo.disp()
        End Using
        dispo.disp()
    End Sub
End Module


using block level

higher level

It is clear that at the first look the code looks same. This type of scenarios may come when we do a C# to VB.Net conversion or vice versa.
If you want to get the C# behavior in VB.Net you need to move the initialization part out of using block header.Code below

dispo = New Disposable("using block level")
Using dispo
    dispo.disp()
End Using
dispo.disp()