Philippsen's Blog

Everyday findings in my world of .net and related stuff

Archive for the ‘Microsoft .net’ Category

How to diagnose .net memory issues

Posted by Torben M. Philippsen on November 7, 2016

Recently I had the quite interesting task to debug some memory issues in a windows service.

I was quite surprised how good the various tools have become and after some reading I was quite quickly able to pinpoint where the probmelm, in this case a memory leak, was to be found.

I found to articles to be very helpful:

In my case I had to upgrade to VS 2015 enterprise to being able to debug the managed memory.

 

In combination the two articles describe how to get started and I recommend reading especially the first one. But if You are in a hurry this list of things to do might be helpful.

  1. First of all we need to create the actual memory dump
  2. Download ProcDump from https://technet.microsoft.com/en-us/sysinternals/dd996900.aspx and save/unzip it to a folder on the machine where your application is installed.
  3. Open a command prompt and switch to the folder where you saved/unzipped ProcDump.exe
  4. Run the command “ProcDump.exe –ma NameOfYourService.exe NameOfDumpFile
    ProcDumpCommandExample
  5. This will create a memorydump in the same folder as where ProcDump is located.
  6. As described in the article on msdn, it could be a good idea to create a baseline/initial dump and afterwards create another dump to see how memory consumption evolves.
  7. Having created the dump file, we need to switch to Visual studio – in my case VS 2015 Enterprise
  8. From the files menu select “open file” and browse to select your dump file. You will see something like this
    VSMemDumpDebugging 
  9. If you do not see the “Debug Managed Memory” action, then your version of VS doesn’t support this and You will need to upgrade to a “bigger” version.
  10. In my scenario it was quite obvious in which area the problem were to be found – please note the “Size (Bytes)” column.
    MemDumpAnalyzed
  11. Having the information above I could go back to my code at analyze where the objects were used and ensure proper release of the memory used by these objects.
    If you know what to look for, things get a hole lot easier:-)
Advertisements

Posted in Microsoft .net | Tagged: , , , , , | Comments Off on How to diagnose .net memory issues

Fetch users from AD using a security group as point of entry

Posted by Torben M. Philippsen on June 27, 2014

In my organisation I have been coding a small application that fetches users from our corporate AD. _Until now I have been using a colection of OU’s to get users from different locations in our AD. However now our IT department has organized the users in security groups. It is common practice for security administrators to create hierarchies of security groups, which allows for easier membership management.

The requirement I faced was that whatever privileges were granted to members of a security group, those privileges apply to any members of security groups found downstream in the hierarchy. This is also a commonly used concept. It was necessary for me to find the security group in AD (represented as a single directory entry) and then drill down into each level of the group hierarchy and find all user members of all associated security groups. I will try to boil it all down to an “easy to go through” article.

My point of entry was this MSDN blogpost – thanks for the inspiration. However I quickly noticed that the code samples lacked a lot of code in order for me to produce a working proof of concept application.

Googling the parts that were missing I actually managed to combine all into a working sample – feel free to download it from here.

Here is how it works:

  1. Looking at the “Tester” project You’ll notice that it contains a simple main method
             static  void  Main(string [] args)
             {
                 ADUserFromSecGroupsPOC.GetAllUsers  users = new  ADUserFromSecGroupsPOC.GetAllUsers();
                 List<ADUser> searchresult = new  List<ADUser>();
                 searchresult = users.GetADSecurityGroupUsers("USR_ERP_RMSsubscription");
                 foreach  (ADUser u in searchresult)
                 {
                     Console.WriteLine(u.AccountExpires);
                     Console.WriteLine(u.PrimarySMTPAddress);
                     Console.WriteLine(u.SAMAccountName);
                     Console.WriteLine(u.SID);
                     Console.WriteLine(u.UserAccountControl);
                     Console.WriteLine("----------------------------------------------------------------" );
                 }
                 Console.ReadKey();
             }

  2. The magic happens in the “ADUserFromSecGroupsPOC” class when calling the method “GetADSecurityGroupUsers” method parsing the security group used as single point of entry.
    /// <summary>
    /// This method takes security group alias and fetches list of user alias that are member of this SG   
    /// </summary>
    ///
    /// <param name="sgAlias">Security group alias</param>
    /// <returns>List of String</returns>
    public  List <ADUser> GetADSecurityGroupUsers(String  sgAlias)
    {
        string  path = "LDAP://OU=Security groups,DC=deverp,DC=local" ;
        string  filter;
        string  filterFormat = "(cn={0})" ;
        filter = String .Format(filterFormat, sgAlias);
        //Get all the AD directory entries of this security group.   
        PropertyCollection  properties = CISFLDAP.GetADPropertiesForSingleEntry(path, filter);
        List <ADUser> groupMembers = new  List <ADUser>();
        if  (properties != null)
        {
             //Used to limit AD search of members to only security groups and users.   
             //The filter is built here but only really needed in the recursive method called below.   
             //Was placed here for performance reasons.  Has no affect on AD call in this method.   
             Collection <int> sAMAccountTypes = new  Collection <int>();
             sAMAccountTypes.Add((int)AuthZGlobals .sAMAccountType.SecurityGroup);
             sAMAccountTypes.Add((int)AuthZGlobals .sAMAccountType.User);
             sAMAccountTypes.Add((int)AuthZGlobals .sAMAccountType.DomainLocalGroup);
             //Builds the filter based on the sAMAccountTypes in the collection.   
             string  sAMAccountFilter = CISFLDAP .MakesAMAccountTypeQueryString(sAMAccountTypes);
             //Look up all the members of this directory entry and look for person data   
             //to add to the collection.   
             groupMembers = GetUsersInGroup(properties, groupMembers, sAMAccountFilter);//GetUsersInGroup do not return anything.    
        }
        return  groupMembers;
    }
    
    

     

     

  3. From this security group we will drilldown adding ONLY user accounts from all nested levels. If the type of the member is a security group, the method will recurse and get the members for this new security group:
    /// <summary>

    /// Recurses through the's member records and collects all the users.   
    /// </summary>
    /// <param name="properties">The collection of the directory's properties.</param>
    /// <param name="groupMembers">List of users found. </param>
    /// <param name="filter">sAMAccountTypes to filter the AD search on.</param>
    public  List <ADUser > GetUsersInGroup(PropertyCollection  properties, List <ADUser > groupMembers, string  filter)
    {
        string  pathFormat = "LDAP://{0}" ;
        string  memberIdx = "member" ;
        string  sAMAccountNameIdx = "sAMAccountName" ;
        string  sAMAccountTypeIdx = "sAMAccountType" ;
        DateTime  accountExpires = DateTime .MinValue;
        bool  hasExpired = false ;
        //string personnelNumberIdx = "extensionAttribute4";
        if  (properties[memberIdx] != null )
        {
            foreach  (object  property in  properties[memberIdx])
            {
                string  distinguishedName = property.ToString();
                string  path = String .Format(pathFormat, distinguishedName);
                //Get the directory entry for this member record.  Filters for only the sAMAccountTypes  
                //security group and user.   
                PropertyCollection  childProperties = CISFLDAP .GetADPropertiesForSingleEntry(path, filter);
                if  (childProperties != null )
                {
                     //If the's sAMAccountType is User.   
                     if  ((int )childProperties[sAMAccountTypeIdx].Value == (int )AuthZGlobals .sAMAccountType .User)
                     {
                        //If member is a user then add, else member is a Service Account with no    
                        //personnel number.   
                        //if (childProperties[personnelNumberIdx].Value != null)
                        if  (childProperties[sAMAccountNameIdx].Value != null )
                        {
                            //groupMembers.Add(searchResults.Properties[sAMAccountNameIdx].Value.ToString());
                            ADUser  userObj = new  ADUser ();
                            userObj.PrimarySMTPAddress = GetPrimarySMTPAdress(childProperties["proxyaddresses" ]);
                            userObj.SAMAccountName = childProperties["SAMAccountName" ].Value.ToString();
                            userObj.SID = GetSidString((byte []) childProperties["objectSid" ][0]);
                            if  (childProperties["accountExpires" ].Count > 0)
                            {
                                LargeInteger  oaccountExpires = (LargeInteger )childProperties["accountExpires" ].Value;
                                accountExpires = ConvertAccountExpiresToDate(oaccountExpires);
                                //find out whether the account has expired
                                hasExpired = IsAccountExpired(accountExpires);
                                userObj.AccountExpires = accountExpires.ToShortDateString();
                            }
                            userObj.UserAccountControl = childProperties["userAccountControl"][0].ToString();
                            groupMembers.Add(userObj);
                        }
                        else
                        {
                             //You'll need to decide if you want to capture the Service Acount info.
                        }
                    }
                    else
                    {
                        //RECURSE - Look up all the members of the security group just found. 
                        GetUsersInGroup(childProperties, groupMembers, filter); // entry is not declared anywhere  
                    }
                }
            }
        }
        return  groupMembers;
    }
    
    

Posted in Active Directory, Microsoft .net | Tagged: , , , , | Comments Off on Fetch users from AD using a security group as point of entry

UAC troubles

Posted by Torben M. Philippsen on June 12, 2012

Working with UAC (User Access control) in relation to win vista, win7 and win server 2008 can be quite troublesome.
Yesterday we found that one our helper apps, which has a feature to start and stop services both local and remotely, didn’t work as expected. When running the application in elevated mode, everything worked fine.
Since we can’t expect all users to remember to run the application in elevated mode, we needed to find a more permanent solution.
I have previously been working with UAC problems relating to processes not running in elevated mode, but i didn’t know how to force the entire application ro run in elevated mode. Google turned out to be my friend again and I found tons of articles telling me “just” to add a manifest file changing the existing:
<requestedExecutionLevellevel=asInvokeruiAccess=false />

to:

<requestedExecutionLevellevel=requireAdministratoruiAccess=false />

Simple one would think – and it was, so You might figure my level of frustration, when this turned out not  to be enough.

Actually there was nothing wrong with the suggested solution, but all post that I read, failed to explain how to tell Visual Studio to use the added manifest file – I had to figure that out myself. A complete solution on how to force Your application to always run in elevated mode wil be listed here:

  • In Visual Studio 2010 (I guess the same applies to VS2008, but I haven’t tested it) right click Your project and select “add new item”
  • Add a application manifest file – the default name will be app.manifest.
  • Inside the manifest file, change the existing configuration from
    <requestedExecutionLevellevel=”asInvoker”uiAccess=”false” />
    To
    <requestedExecutionLevellevel=”requireAdministrator”uiAccess=”false” />
  • Save and close the manifest file.
  • Please note that Your manifest file won’t show up anywhere in your solution. In order to fix that, in solution explorer, click the “show all files” button.
  • Important: Right click the manifest file and add it to the project – we need that in order to tell VS to use the manifest file when compiling our application.
  • Right click Your project and select “properties”.
  • On the application tab, the bottom section, select the manifest file:

    manifest file selection

    manifest file selection

  • Compile and run the application. If Your UAC settings are enabled, You will be prompted to allow the application to start in elevated mode.

Sometimes it can come in handy to check whether Your application is actually running in elevated mode or not. Maybe You will find this codesnippet usefull:

 WindowsPrincipal myPrincipal = new WindowsPrincipal (WindowsIdentity .GetCurrent());

 if (myPrincipal.IsInRole(WindowsBuiltInRole .Administrator) == false )
 {
  //show messagebox - displaying a messange to the user that rights are missing
  MessageBox .Show("You need to run the application using the \\"run as administrator\\" option" , "administrator right required" , MessageBoxButtons .OK, MessageBoxIcon .Exclamation); 
 }
 else
 {
  MessageBox .Show("You are good to go - application running in elevated mode" , "Good job" , MessageBoxButtons .OK, MessageBoxIcon .Information);
 }

You may also find these references helpfull:

http://stackoverflow.com/questions/2818179/how-to-force-c-sharp-app-to-run-as-administrator-on-windows-7

http://msdn.microsoft.com/en-us/library/bb756929.aspx

http://victorhurdugaci.com/using-uac-with-c-part-1/

Posted in Books and reading stuff, Microsoft .net, Visual Studio | Tagged: , , , , , | Comments Off on UAC troubles

WSDL validation

Posted by Torben M. Philippsen on January 2, 2012

When consuming webservice from other vendors it often can come in handy to have their wsdl validated – just to rule out errors related to failure in validation.

I have found these validation sites to be very usefull:

Posted in WCF (Windows Communication Foundation) | Tagged: | Comments Off on WSDL validation

Manually compile C# project using command line

Posted by Torben M. Philippsen on June 20, 2011

For various reasons I sometimes have to build projects outside my Visual Studio environment. One approach is to use the sommand line tool csc.exe (for c# projects) or vbc.exe (for vb.net projects). It can be quite exhausting to build the command – especially if your are using external libraries, ressources, settings and other quite common stuff. It would be nice if one could just fetch the command that Visual Studio uses to compile the project – well you can:-)

If you want to have a look at the command that Visual studio uses to compile you project, all you need to do is to launch a command similar to this in a visual studio command prompt:

E:\VSS\Grene\AxXMLService\AxXMLService>msbuild AxXMLService.csproj /t:rebuild /clp:showcommandline >> log.txt

This command will produce a log file containing the output – this will look something like this:

csc command output

csc command output

Please note the highlighted section – here you will find the command you need to build your project outside visual studio. the only requirement is ofcouse that the relevant framework version is installed on the machine performing the build.

Posted in Tools, Visual Studio | Tagged: , , , | Comments Off on Manually compile C# project using command line

Reading extended properties using EWS managed API

Posted by Torben M. Philippsen on June 20, 2011

Having been working with Exchange 2007 Web Services (EWS) for a couple af years a recent bug led me to testing various scenarios regarding appointment items using the EWS Managed API instead of the proxy classes that I have grown used to working with.

One of my struggles was to read the extended properties that we use. Having gotten it all to work I though that I’d create this post. Below you will find my code sample:

This first snippet set up the service connection using autodiscover.

        private ExchangeService GetService()

        {

            ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);

            service.Credentials = new NetworkCredential(Settings.Default.ConnectingUser, Settings.Default.ConnectingUserPassword, Settings.Default.ConnectingUserDomain);

            service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SID, Settings.Default.ImpersonatedUserSID);

            service.Url = new Uri(Settings.Default.EWSURL);

            return service;

        }

This second snippet defines and fetches the standard properties as well as the extended properties.

        private void btnGetItem_Click(object sender, EventArgs e)

        {

            string itemId = txtItemId.Text;

            ExchangeService service = GetService();

            AlternateId sourceId = new AlternateId(IdFormat.EwsLegacyId, itemId, Settings.Default.ImpersonatedUserMailbox);

            AlternateId destinationId = service.ConvertId(sourceId, IdFormat.EwsId) as AlternateId;

            //reference: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/e01fe982-83c2-49ee-b900-78d49c47323c/

            //define the extended properties that should be fetched

            ExtendedPropertyDefinition rmsIsRms = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, “RMS-IsRMS”, MapiPropertyType.Boolean);

            ExtendedPropertyDefinition rmsCustomerProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, “RMS-CustomerProp”, MapiPropertyType.String);

            ExtendedPropertyDefinition rmsInternalProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, “RMS-InternalProp”, MapiPropertyType.Boolean);

            ExtendedPropertyDefinition rmsProjectProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, “RMS-ProjectProp”, MapiPropertyType.String);

            ExtendedPropertyDefinition rmsActivityProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, “RMS-ActivityProp”, MapiPropertyType.String);

            ExtendedPropertyDefinition[] userFields = new ExtendedPropertyDefinition[] { rmsIsRms, rmsActivityProp, rmsCustomerProp, rmsInternalProp, rmsProjectProp };

            //get the item and it’s extended properties

            PropertySet extendedPropertySet = new PropertySet(BasePropertySet.FirstClassProperties, userFields);

            Appointment item = (Appointment)Item.Bind(service, new ItemId(destinationId.UniqueId), extendedPropertySet);

            //having the item – get the extended properties

            object isRMS;

            object customerProp;

            object isInternalProp;

            object projectProp;

            object activityProp;

            //Print properties

            rtItemProps.AppendText(“ItemClass: “ + item.ItemClass + “\n”);

            rtItemProps.AppendText(“Subject: “ + item.Subject + “\n”);

            rtItemProps.AppendText(“CalendarItemType: “ + item.AppointmentType.ToString() + “\n”);

            rtItemProps.AppendText(“Organizer: “ + item.Organizer.Name + “\n”);

            rtItemProps.AppendText(“OrganizerEmail: “ + item.Organizer.Address + “\n”);

            rtItemProps.AppendText(“Start: “ + item.Start + “\n”);

            rtItemProps.AppendText(“End: “ + item.End + “\n”);

            rtItemProps.AppendText(“Location: “ + item.Location + “\n”);

            rtItemProps.AppendText(“Free/busy: “ + item.LegacyFreeBusyStatus.ToString() + “\n”);

            rtItemProps.AppendText(“—————RMS INFO————–\n”);

            //extended properties are printed only if they exist

            if (item.TryGetProperty(rmsIsRms, out isRMS) && isRMS != null)

            {

                rtItemProps.AppendText(“IsRMS: “ + isRMS.ToString() + “\n”);

            }

            if (item.TryGetProperty(rmsCustomerProp, out customerProp) && customerProp != null)

            {

                rtItemProps.AppendText(“Customer: “ + customerProp.ToString() + “\n”);

            }

            if (item.TryGetProperty(rmsProjectProp, out projectProp) && projectProp != null)

            {

                rtItemProps.AppendText(“Project: “ + projectProp.ToString() + “\n”);

            }

            if (item.TryGetProperty(rmsActivityProp, out activityProp) && activityProp != null)

            {

                rtItemProps.AppendText(“Activity: “ + activityProp.ToString() + “\n”);

            }

            if (item.TryGetProperty(rmsInternalProp, out isInternalProp) && isInternalProp != null)

            {

                rtItemProps.AppendText(“IsInternal: “ + isInternalProp.ToString() + “\n”);

            }

        }

Posted in Exchange development, Microsoft .net | Tagged: , , | 5 Comments »

Manually sign any file using a pfx file

Posted by Torben M. Philippsen on June 6, 2011

A colleegue of mine recently build a MSI installer using some third party tool unknown to me. He kindly asked me, what he needed to do, to sign the installer using our corporate codesigning certificate.

I am used to build my installers using Visual Studio, but I remembered that I once or twice had used the SignTool.exe command line tool, to sign some files. I looked up the documentation for the tool And quickly I was able to create a command meeting my needs:

E:\VSS\USMT\MSIProject>signtool sign /f E:\VSS\CodeSigningCert\Trustzone\eg_codesigning.pfx /p mypassword /d USMTApp USMTApp.msi

Note: To me it seems rather important to remember the d options – adding a description to the installer. This will show when the user runs the isntallation package.

Posted in Visual Studio | Tagged: | Comments Off on Manually sign any file using a pfx file

Codesigning struggles

Posted by Torben M. Philippsen on March 14, 2011

Do you also keep asking yourself something like this:

  • Why does something so simple always turn out to be so relatively hard and timeconsuming?
  • Once you have aquired your certificate, shouldn’t it be easy to apply to you project?

In my oppinion Visual Studio 2010 offers limited support for wanting to codesign your apps before distribution. In my experience You will only experince a fair ammount of success when dealing with clickonce applications. In those cases it is pretty much straigth forward to apply your certificate (pfx file) and You may remember a screen like this:

Codesigning screendump from VS2010

Codesigning screendump from VS2010

The troubles start when you want to sign the assembly. This never works the first time for me. Either I keep some strange errors stating that the certificate can not be imported or that a reference to a token can not be found and so on and so on and so on… All these errors have always turneed out to be less than helpfull and today I had enough and once and for all I wanted to find a nearby bulletproof way to sign my apps in the future.

Reading various blogs I noticed that a lot of people have had the same frustrations as I, and a lot of those people had turned to external signing tools. Since I am pretty keen on using the standard tools from Microsoft I chose to go along with the Signtool util that Microsoft provides along with Visual Studio. I also learned something new called “Post build events” until now I didn’t know they existed, but in this case they come in pretty handy – let me explain… I’am usually required to deliver my apps as a MSI package. When building the MSI package based on the primary output from my assembly the assembly gets rebuild. If the assembly is not signed during this process, you will end up having an unsigned assembly. This is where the post build event comes into play.

 

Sign the assembly using signtool.exe and the post build event (VB.net)

  1. Right click your project file of your assembly – select “properties”
  2. Select the “Compile” tab and notice the “Build events” button in the lower left corner
  3. Click that button. You will now be able to provide a pre-build event command and/or a post-build event command
  4. Enter the signtool command that applies to your needs. You can use the visual studio command prompt to test the command. In that way you don’t have to wait while all projects are being recompiled.
    A piece of advice is to use the built-in macros. Using those macros it is pretty easy to supply the correct paths.
  5. Choose when to run the post-build event – for instance “on successful build”
  6. click “ok” to exit
  7. Recompile your assembly. If you have put in the signtool command correctly, your assembly will be signed.

To get the signtool command to work properly I had to try out various commands. The one thing that kept getting in my way, was to supply the proper paths. Here is what you need to know:

  • When putting the signtool command into visual studio it does not know where to locate the signtool.exe file. You will have to put in the exact path to the signtool.exe. Using Visual Studio 2010 my path was “C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool”. Notice that the signtool is located in a previous version of Visual Studio. You might need to perform a search to find it in your environment.
  • If you have any spaces in your file paths, remember to but the path in quotes <“path”>
  • Remember to use the exact filepath when pointing to your certificate
  • Remember to supply the password for the certificate
  • Remember to use the full filepath to the assembly that needs to be signed – this is done by using the build-in macros

Here’s a sample command that worked for me:

“C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool” sign /f “$(ProjectDir)resources\eg_codesigning.pfx” /p mypassword “$(TargetPath)”

 

Sign the installer using Signtool.exe (VB.net)

Once the assembly is signed you can move forward to have your installer signed. I will assume you know how to add a setup project to your solution.

  1. Select the “setup project” project file and view the properties.
  2. Notice that you will have a property called “PostBuildEvent”. Click the browse button to enter the command line screen.
  3. As you did before you need to build the command. I will not go into further details since the process is pretty much the same as described above.
  4. Once you have entered your command rebuild the setup project.

Things you need to know:

  • If you do not put in a description using the signtool, You will notice that when installing your app, a funny name like 77eu891.msi will show up in the UAC prompt. To avoid this, just remember to use the /d option in the signtool command. This will add a description to the MSI package and this description will display in the UAC prompt.

Here’s a sample that worked for me:

“C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool” sign /f “$(ProjectDir)eg_codesigning.pfx” /p mypassword /d “EGPackageMaker – Corporate software administration tool” “$(BuiltOuputPath)”

 That’s it. For now my struggles regarding codesigning have ended – and maybe this article can be of use to someone else.

Posted in Visual Studio | Tagged: , | 1 Comment »

Find out which control triggered post back event

Posted by Torben M. Philippsen on January 3, 2011

In a recent Reporting Services web project I used the ReportViewer control to display reports.

In order to position some asp.net controls properly according to whether the parameters bar was present or not, I needed to determine if the “view report” button was clicked – causing the postback. Analyzing the html output of the reportviewer control, I needed to deterrmine if the control with id “ReportViewer1_ctl00_ctl00” caused the postback.

This is what I did:

    Control ctrl = GetPostBackControl(this);

    if (ctrl.ClientID.Equals(“ReportViewer1_ctl00_ctl00”))

    {

        ImageButton1.CssClass = “”;

        LinkButton1.CssClass = “LinkButton”;

    }

 

And the code for the GetPostBackControl method:

    public static Control GetPostBackControl(Page page)

    {

        Control control = null;

        string ctrlname = page.Request.Params.Get(“__EVENTTARGET”);

        if (ctrlname != null && ctrlname != string.Empty)

        {

            control = page.FindControl(ctrlname);

        }

        else

        {

            foreach (string ctl in page.Request.Form)

            {

                if ((ctl.LastIndexOf(“.x”) > 0) || (ctl.LastIndexOf(“.y”) > 0))

                {

                    control = page.FindControl(ctl.Substring(0, ctl.Length – 2));

                    break;

                }

                control = page.FindControl(ctl);

                if ((control is System.Web.UI.WebControls.Button))

                {

                    break;

                }

            }

        }

        return control;

    }

Posted in asp.net, Reporting Services | Tagged: , | 1 Comment »

Retrieving user SID using DirectoryEntry and DirectorySearcher

Posted by Torben M. Philippsen on December 7, 2010

Recently I was working on one of main projects that amongst other things retrieves some user properties from Active Directory.

In order to use Exchange 2007 Webservices I needed to retrieve the SID because the SID was needed when impersonating a given user. This articke describes how to retrieve the SID into a byte array and using P/Invoke.

Step 1 – Search the AD

    1 public SearchResultCollection getUserInfo(string ldapPath)

    2         {

    3             string ADUserName = ConfigurationManager.AppSettings[“UserName”];

    4             string ADPassword = ConfigurationManager.AppSettings[“Password”];

    5             DirectoryEntry rootEntry = new DirectoryEntry(ldapPath, ADUserName, ADPassword);

    6             DirectorySearcher searcher = new DirectorySearcher(rootEntry);

    7             //add the properties to retrieve

    8             //accountstatus

    9             searcher.PropertiesToLoad.Add(“userAccountControl”);

   10             //mail

   11             searcher.PropertiesToLoad.Add(“mail”);

   12             searcher.PropertiesToLoad.Add(“accountExpires”);

   13             searcher.PropertiesToLoad.Add(“proxyaddresses”);

   14             searcher.PropertiesToLoad.Add(“SAMAccountName”);

   15             searcher.PropertiesToLoad.Add(“objectSid”);

   16             SearchResultCollection results;

   17             results = searcher.FindAll();

   18             return results;

   19         }

 

Step 2 – loop the SearchResultCollection retriveing the “objectSid”

    string sidStringValue=””;

    foreach (SearchResult result in src)

             {

                  //reset SID

                  byte[] SID = null;

                  if (result.Properties[“objectSid”].Count > 0)

                  {

                      SID = (byte[]) result.Properties[“objectSid”][0];

                  }

                  sidStringValue = GetSidString(SID); 

             }//end foreach

Step 3 – In the code example above a call to the method “GetSidString” is made – this method looks like this:

        [DllImport(“advapi32”, CharSet = CharSet.Auto, SetLastError = true)]

        static extern bool ConvertSidToStringSid([MarshalAs(UnmanagedType.LPArray)] byte[] pSID, out IntPtr ptrSid);

 

        public static string GetSidString(byte[] sid)

        {

            IntPtr ptrSid;

            string sidString;

            if (!ConvertSidToStringSid(sid, out ptrSid))

                throw new System.ComponentModel.Win32Exception();

            try

            {

                sidString = Marshal.PtrToStringAuto(ptrSid);

            }

            finally

            {

                Marshal.FreeHGlobal(ptrSid);

            }

            return sidString;

        }

    }

Posted in Exchange development | Tagged: , , , | 1 Comment »

 
%d bloggers like this: