NetInverse Developers Blog

March 31, 2009
Category: Wordpress — Tags: , , — admin @ 9:07 pm

The first principle to optimize permalinks is to ensure that they include your keywords. An URL with a keyword is better than an URL without one for search engines. Following sample uses the category and the post title as part of a Permalink.

For detailed steps, you can check out this blog: http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/. You can also check out MSDN URL Rewriting in ASP.NET.

Following outlines the steps needed to enable WordPress Premera Link on IIS 7.0.  It may just take you 10 minutes.  

  1. Install URL rewrite module Go Live release.
  2. Create a debugging page. This is really optional; it would be handy when you later need to troubleshoot the regular expression rules.  Copy the file to into your WordPress folder.
    <%@ Page Language="C#" %>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>URL Rewrite Module Test</title>
    </head>
    <body>
          <h1>URL Rewrite Module Test Page</h1>
          <table>
                <tr>
                      <th>Server Variable</th>
                      <th>Value</th>
                </tr>
                <tr>
                      <td>Original URL: </td>
                      <td><%= Request.ServerVariables["HTTP_X_ORIGINAL_URL"] %></td>
                </tr>
                <tr>
                      <td>Final URL: </td>
                      <td><%= Request.ServerVariables["SCRIPT_NAME"] + "?" + Request.ServerVariables["QUERY_STRING"] %></td>
                </tr>
          </table>
    </body>
    </html>
  3. Log into the Wordpress Admin page, choose Settings  -> Permalinks from the left navigation bar. Note following steps are based on Wordpress v2.7.
  4. Change your Permlinks structure to be
    Custom Structure: /%category%/%postname%/%post_id%/
  5.  Run inetmgr.  Click “Start” -> “Run”, type in “inetmgr”, then click the button “Ok”.
  6. Choose your web site,  click the “Url Rewrite” icon from “Features View”.
  7. Click “Add rules”.
  8. Give the new rule a name like “Wordpress page rule”, and define the Pattern and Rewrite Url.
      Pattern: ^MyBlog/([_0-9a-z-]+)/([_0-9a-z-]+)/([0-9]+)/
    
      Rewrite Url: /MyBlog/?p={R:3}
  9. Save the rule, then try out your Wordpress page to see if it works. You may need to creat more rules. Open the web.config, you will see the rules like below.

        <system.webServer>
            <rewrite>
                <rules>
                    <clear />
                    <rule name="wordpress calendar month" enabled="true">
                        <match url="^MyBlog/date/(\d\d\d\d)/(\d\d)" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?m={R:1}{R:2}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress calendar day" stopProcessing="false">
                        <match url="^MyBlog/date/(\d\d\d\d)/(\d\d)/(\d\d)" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?m={R:1}{R:2}{R:3}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress page">
                        <match url="^MyBlog/([_0-9a-z-]+)/([_0-9a-z-]+)/([0-9]+)/" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?p={R:3}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress category">
                        <match url="^MyBlog/category/([_0-9a-z-]+)" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?cat={R:1}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress paging">
                        <match url="^MyBlog/page/([0-9]+)" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?paged={R:1}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress tag">
                        <match url="^MyBlog/tag/([_0-9a-z-]+)" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Rewrite" url="/MyBlog/?tag={R:1}" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress feed" stopProcessing="true">
                        <match url="^MyBlog/feed$" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Redirect" url="/MyBlog/?feed=rss2" appendQueryString="false" />
                    </rule>
                    <rule name="wordpress comment feed" stopProcessing="true">
                        <match url="^MyBlog/comments/feed$" />
                        <conditions logicalGrouping="MatchAll" />
                        <action type="Redirect" url="/MyBlog/?feed=comments-rss2" appendQueryString="false" redirectType="Permanent" />
                    </rule>
                </rules>
            </rewrite>
        </system.webServer>
    1. You see, it is easy!

March 29, 2009
Category: Debugging — Tags: , , , — admin @ 12:28 am

Using SOS in Visual Studio

First, you need to right mouse click on the project in solution explorer, choose properties, switch to the Debug tab, and make sure “Enable Unmanaged Code Debugging” is selected.

Second, open the Immediate window (Debug->Windows->Immediate). You can simply press shortcut keys Ctrl + Alt + I. Then type following command in the Immediate window.

.load C:\windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

Third, Type “!help” for help.

!help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function.

Object Inspection              Examining code and stacks
-----------------------------  -----------------------------
DumpObj (do)                   Threads
DumpArray (da)                 CLRStack
DumpStackObjects (dso)         IP2MD
DumpHeap                       U
DumpVC                         DumpStack
GCRoot                         EEStack
ObjSize                        GCInfo
FinalizeQueue                  EHInfo
PrintException (pe)            COMState
TraverseHeap                   BPMD

Examining CLR data structures  Diagnostic Utilities
-----------------------------  -----------------------------
DumpDomain                     VerifyHeap
EEHeap                         DumpLog
Name2EE                        FindAppDomain
SyncBlk                        SaveModule
DumpMT                         GCHandles
DumpClass                      GCHandleLeaks
DumpMD                         VMMap
Token2EE                       VMStat
EEVersion                      ProcInfo
DumpModule                     StopOnException (soe)
ThreadPool                     MinidumpMode
DumpAssembly
DumpMethodSig                  Other
DumpRuntimeTypes               -----------------------------
DumpSig                        FAQ
RCWCleanupList
DumpIL

Some common commands are listed below:

!CLRStack
!ip2md [EIP Address]
!DumpIL [MethodDesc Address]
!help [Command]

Command: !CLRStack

!CLRStack [-a] [-l] [-p]

CLRStack attempts to provide a true stack trace for managed code only. It is handy for clean, simple traces when debugging straightforward managed programs. The -p parameter will show arguments to the managed function. The -l parameter can be used to show information on local variables in a frame. SOS can’t retrieve local names at this time, so the output for locals is in the format = . The -a (all) parameter is a short-cut for -l and -p combined.

When you see methods with the name “[Frame:...", that indicates a transition between managed and umanaged code. You could run !IP2MD on the return addresses in the call stack to get more information on each managed method.

On IA64 and x64 platforms, Transition Frames are not displayed at this time. Especially on IA64, there is heavy optimization of parameters and locals. You can request the JIT compiler to not optimize functions in the managed app by creating a file myapp.ini (if your program is myapp.exe) in the same directory.

Put the following lines in myapp.ini and re-run:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
March 11, 2009
Category: .Net, Windows API — Tags: , , — admin @ 11:57 pm

Active Directory has a global catalog (GC), which contains a partial replica of all objects in the directory. It also contains partial replicas of the schema and configuration containers. One or more domain controllers in a domain can hold a copy of the global catalog.

The global catalog holds a replica of every object in Active Directory, but with only a small number of their attributes. The attributes in the global catalog are those most frequently used in search operations, such as a user’s first and last names, login names, and so on. The global catalog attributes also include those required to locate a full replica of the object. The global catalog allows users to quickly find objects of interest without knowing what domain
holds them and without requiring a contiguous extended namespace in the enterprise; that is, you can search the entire forest.

The following sample code demonstrates a way to check if a caller is in a perticular security group. It searches the global catalog to obtain the group’s SID(Security Id), and then call CheckTokenMembership to find out if the caller is in that group. It is very useful when a service process need to check a caller’s membership for authentication or authorization.

In real applications, you may need to cache the SIDs of the groups for better performance since searching the global catalog is fast, but not that fast.

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.DirectoryServices;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace IsInGroup
{
    ///
    /// Summary description for Class1.
    ///
    class Class1
    {
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern int CheckTokenMembership(int TokenHandle, byte[] PSID, out bool IsMember);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern bool IsValidSid(byte[] PSID);

        public static string GetCallerName()
        {
            WindowsPrincipal principal =
                new WindowsPrincipal(WindowsIdentity.GetCurrent());
            return principal.Identity.Name.Split('\\')[1];
        }

        ///
        /// The main entry point for the application.
        ///
        static void Main(string[] args)
        {
            string groupName = "administrators";

            //get current caller's information
            string user = GetCallerName();

            //search global catalog and get SID of the group
            Byte[] sid = null;

            DirectoryEntry entry = new DirectoryEntry("GC:");
            IEnumerator ie = entry.Children.GetEnumerator();
            ie.MoveNext();
            DirectorySearcher ds = new DirectorySearcher((DirectoryEntry)ie.Current);

            string sam = "(sAMAccountName=" + groupName + ")";
            ds.Filter = "(&(|" + sam + ")(objectClass=group))";
            using (SearchResultCollection resColl = ds.FindAll())
            {
                if (resColl.Count > 0)
                {
                    ResultPropertyCollection resultPropColl = resColl[0].Properties;
                    string name = (string)resultPropColl["name"][0];
                    string adsPath = (string)resultPropColl["adspath"][0];
                    sid = (byte[])resultPropColl["objectsid"][0];

                    if (sid == null || !IsValidSid(sid))
                    {
                        System.Console.WriteLine("Invalid SID for the group.");
                        return;
                    }
                    else
                    {
                        System.Console.WriteLine("Group found: " + name);
                        System.Console.WriteLine("Group ADS path: " + adsPath);
                    }
                }
                else
                {
                    System.Console.WriteLine("Required info was not found in the GC.");
                    return;
                }
            }

            bool bIsMember = false;
            if (CheckTokenMembership(0, sid, out bIsMember) == 0)
            {
                System.Console.WriteLine("Failed to call CheckTokenMembership.");
            }
            else
            {
                System.Console.WriteLine(user + (bIsMember ?
                    " is a member of " : " isn't a member of ") + groupName);
            }
        }
    }
}
Category: .Net — Tags: , — admin @ 9:20 pm

NHibernate is an Object-relational mapping (ORM) solution for the Microsoft .NET platform. It is licensed under the GNU Lesser General Public License. It is a port of the popular Java O/R mapper Hibernate to .NET. Version 1.0 mirrors the feature set of Hibernate 2.1, adding a number of features from Hibernate 3. NHibernate 1.2.0, released May of 2007, introduces many more features from Hibernate 3 and support for .NET 2.0, stored procedures, generics and nullable types.

  1. All classes and collections with 1.2 are now loaded lazily by default. You may need to change lazy=”false”, or make methods be virtual.
  2. Use .Net 2.0 Generics for all collection interfaces (You no longer have to use the NHibernate.Generics compatability library).
  3. Support Batching for SQL Server - huge perforamance increase in some scenarios.
  4. Support Stored Procedures.
  5. Support named connection strings.
  6. Support SQL Server 2005 and SQL Server 2005 Everywhere dialects.
  7. Support Parametrized types and User Collection Types.
  8. Support projections in criteria queries, i.e. CreateCriteria(typeof(T)).Count(), and CreateCriteria(typeof(T)).Max(…), etc.
  9. New IL-based reflection optimizer - another big performance boost.
  10. Use SetProjection(Projections.Count(”ID”)) instead of IQuery’s Select count(*).
  11. New DetachedCriteria
  12. New GetCurrentSession method of SessionFactory: SessionFactory.GetCurrentSession()

You can click here to check out a list of .Net ORM products.

March 10, 2009
Category: Visual Studio — Tags: — admin @ 11:38 pm

Debug Into .NET Framework Library

The source code of the .NET Framework libraries, and debugging support of them with Visual Studio 2008 is now available. Specifically, you can now browse and debug the source code for the following .NET Framework libraries:

  • .NET Base Class Libraries (including System, System.CodeDom, System.Collections, System.ComponentModel, System.Diagnostics, System.Drawing, System.Globalization, System.IO, System.Net, System.Reflection, System.Runtime, System.Security, System.Text, System.Threading, etc).
  • ASP.NET (System.Web, System.Web.Extensions)
  • Windows Forms (System.Windows.Forms)
  • Windows Presentation Foundation (System.Windows)
  • ADO.NET and XML (System.Data and System.Xml)You can check out Shawn Burke’s “Configuring Visual Studio to Debug .NET Framework Source Code” for detailed steps. LINQ, WCF and Workflow will become available soon.

Include Line Number in StackTrace

How to make the StackTrace include line number? compile your code in debug mode and deploy the .pdb file along with the assembly.

Set Breakpoints on Optimized Code

CLR has an issue: when JIT compiling optimized code, the mapping between x86 and IL is not kept. Thus when you attach the debugger to a process running optimized code, you may often not be able to set break points. To work around this issue, you can launch the application under the debugger rather than attach to it. When optimized code is JIT compiled when a debugger is present, the x86 to IL map is preserved. You can also create .ini file per assembly that tells the JIT compiler to generate the map. See this MSDN topic: Making an Image Easier to Debug.

Also, if your code is a C++/CLI mixed mode assembly, you may want to disable the option called Enable Just My Code under the tools/Options/Debug.

Debug Into Native Code

To debug into native code when calling a (PInvoke) native function, you need to go to Project->Properties, and make sure Enable Unmanaged Debugging is checked.

Execute permission denied on object ’sp_sdidebug’

If you are debugging a W3Wp process of a Web Service that executes some SQL stored procedures in SQL server 2000, you may get a SQL exception “Execute permission denied on object ’sp_sdidebug’ , database ‘master’, owner ‘dbo’”. To solve it, you can simply just select “Managed Code” only and not select “T-SQL” when you try to attach the process.

Vertical Selection and Copy&Paste

This is a very convenient feature allows you to choose multiple columns and copy/paste them. What you need to do is press and hold the Alt key down first, then press the left mouse key down, drag the highlight towards to the right side to choose columns, and then move mouse downward to select rows.

visualstudiocopypasttip

Force the Solution Explorer highlights the file you are working on

In Visual Studio, whenever you view a file in the main editor, the Solution Explorer would find and highlight that file for you.

  1. Navigate to Tools -> Options
  2. Select “Projects and Solutions” in the tree view on the left
  3. Select “Track Active Item in Solution Explorer

CodeRush Xpress for C# - Free

Developer Express and Microsoft are proud to announce a new version of CodeRush licensed exclusively for C# developers working in Visual Studio. The new product is called CodeRush Xpress, and it includes a fresh selection of hand-picked features taken from CodeRush and Refactor! Pro. It has following major features.

  • Editor Features
  • Navigation Features
  • TDD - Declaration from Usage
  • Refactorings - like Resharper

Visual Studio Debugger Tips and Tricks

The Visual Studio Debugger provides a slew of features that make the task of debugging both easier and more efficient. Learn about time-saving tips and tricks for all versions of the Visual Studio Debugger, including the new debugger features in Visual Studio 2010. Hear about the new mixed-mode debugging feature, the breakpoints window enhancements, the new WPF visualizers, and a number of other features. Also learn about thread debugging enhancements, new features for making stepping into properties easier, and more. Join us as we crack open the toolbox and walk through some of the debugger’s best practices.

Execution Control
- Step filtering for managed
Breakpoints
Symbols
Symbol search:
Path specified by: HKLM/HKCU
Software\Microsoft\VisualStudio\MSPDB\SymbolSearchPath
On the path at any of these
_NT_ALT_SYMBOL_PATH
_NT_SYMBOL_PATH
SystemRoot
Multi-threaded debugging
Post mortem debugging

Visual Studio Debugger Tips and Tricks

Visual Studio Debugger Tips and Tricks

http://channel9.msdn.com/pdc2008/TL59/

How to Config Visual Studo to Debug .Net Source Code

http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

March 9, 2009
Category: .Net, Design Pattern — Tags: , — admin @ 8:18 pm

A typicaly Singleton implementation in C# looks like below:

    using System;

    public sealed class Singleton
    {
       private static volatile Singleton instance;
       private static object syncRoot = new Object();

       private Singleton() {}

       public static Singleton Instance
       {
          get
          {
             if (instance == null)
             {
                lock (syncRoot)
                {
                   if (instance == null)
                      instance = new Singleton();
                }
             }

             return instance;
          }
       }
    }

[MSDN]This approach ensures that only one instance is created and only when the instance is needed. Also, the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed. Lastly, this approach uses a syncRoot instance to lock on, rather than locking on the type itself, to avoid deadlocks. This double-check locking approach solves the thread concurrency problems while avoiding an exclusive lock in every call to the Instance property method. It also allows you to delay instantiation until the object is first accessed.

Above solution looks perfect, however, actually the ‘Double-Checked Locking’ can be still broken under certain multi-processor machine. A recommended way to implement Singleton correctly is below:

    public sealed class Singleton
    {
        Singleton(){}
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        static class Nested
        {
            internal static readonly Singleton instance = new Singleton();
        }
    }

Above code looks weird, but correct. It leverages .Net’s Class Loader to achieve thread-safe.

Category: .Net, Build — Tags: — admin @ 7:59 pm

It is very common that you need to run some commands on a remote server. For example, you may want to config your source control server to start a build process on a dedicated build machine once it receives any checkins. To achieve this, you can leverage the WMI scripting APIs.

The steps are:

  1. Use SWbemLocator to create Locator object
  2. Use the Locator object to connect to the remote server and get back a Service object
  3. Use the Service object to get a Win32 process object
  4. Finally, use the Process object to issue your command

WMI WbemScripting script sample:

    Function RemoteExecute(strServer, strUser, strPassword, CmdLine)
        Const Impersonate = 3

        RemoteExecute = -1

        Set Locator = CreateObject("WbemScripting.SWbemLocator")
        Set Service = Locator.ConnectServer(strServer, "root\cimv2", strUser, strPassword)

        Service.Security_.ImpersonationLevel = Impersonate
        Set Process = Service.Get("Win32_Process")

        result = Process.Create(CmdLine, , , ProcessId)

        If (result <> 0) Then
            WScript.Echo "Creating Remote Process Failed: " & result
            Wscript.Quit
        End If

        RemoteExecute = ProcessId
    End Function

NAnt is very popular in the .Net development community. You may want to write a C# extension for NAnt scripts to achieve some build automations on remote servers. You can achieve that easily too. I am posting a WMI C# sample below for your reference too.

WMI C# sample:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Management;

    namespace WMISample
    {
        class Program
        {
            static void Main(string[] args)
            {
                string remoteMachine = "localhost";

                ConnectionOptions connOptions = new ConnectionOptions();
                connOptions.Impersonation = ImpersonationLevel.Impersonate;
                connOptions.EnablePrivileges = true;

                ManagementScope manScope = new ManagementScope(
                    String.Format(@"\\{0}\ROOT\CIMV2", remoteMachine), connOptions);
                manScope.Connect();

                ObjectGetOptions objectGetOptions = new ObjectGetOptions();
                ManagementPath managementPath = new ManagementPath("Win32_Process");
                ManagementClass processClass = new ManagementClass(
                    manScope, managementPath, objectGetOptions);

                ManagementBaseObject inParams = processClass.GetMethodParameters("Create");

                inParams["CommandLine"] = @"notepad.exe";
                ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null);

                Console.WriteLine("Creation of the process returned: " + outParams["returnValue"]);
                Console.WriteLine("Process ID: " + outParams["processId"]);
                Console.ReadLine();
            }
        }
    }
Category: .Net, ASP.Net — Tags: , , , — admin @ 7:30 pm

An ASP.Net applicatin may return an “Access Denied” error when it is accessing the Eventlog.

If it is not a GPO permission issue from your domain controller, you may need to check the SDDL string specified in the registry for the EventLog.

For example, if the identity of the App pool is the “Network service” account, “impersonation” in the web.config is true and authentication is enabled, you may need to add a WRITE access (A;;0×2;;;AU) for the authenticated users to the following registry key.

HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\Application\CustomSD

(A;;0x2;;;AU)   Note: AU means "Authenticated Users"

Similarly, you can grant permissions for the “Network service” account.

(A;;0x2;;;NS)   Note: NS means "Network service" account

What (A;;0×2;;;AU) is? You can check out Microsoft’s SDDL (Security Descriptor Definition Language) on MSDN.

Windows 2008 is much easier as long as you are ok giving the user/group read access to all event logs. If that is the case just add them to the Built in Event Log Readers group.

The location on the SDDL has changed in Windows 2008 and is no longer set it via the CustomSD in the registry. You now have to use the command line wevtutil utility.

 

Category: Agile — Tags: — admin @ 7:25 pm

Lean Software Development - An Agile Toolkit By Mary Poppendieck and Tom Poppendieck

This book contains seven chapters devoted to seven lean principles and thinking tools for translating each principle into agile practices.

  1. Eliminate waste. Waste is anything that does not add value to a product, value as perceived by the customer.
  2. Amplify learning. Development is an exercise in discovery. Take your most difficult problem and devise a way to increase feedback. Start iterations with a negotiation session between customers and developers. Post a progress chart for your current project in a common area so the team can see what needs to be done and everyone can see the project is converging. Find your toughest outstanding development problem and have the development team come up with three options on how to solve it. Instead of choosing one of the solutions, have the team explore all three options at the same time.
  3. Decide as late as possible. Development practices that provide for late decision making are effective in domains that involve uncertainty, because they provide any options-based approach.
  4. Deliver as fast as possible.
  5. Empower the team.
  6. Build integrity.
  7. See the whole. Finding and removing the limits of growth. Avoid the pattern called “Shifting the burden”. Ask “five whys” to counter the tendency to the burden to symptoms rather than addressing the root cause of a problem. Avoid “Suboptimization”. Local management tends to create local measuremens of performance. These local measurements often create systemwide effects that decrease overall performance.
Category: .Net — Tags: , , , , — admin @ 7:15 pm

The code is very simple. You just need to use DirectoryEntry object to locate the local group and the domain user. Then invoke an “Add” operation on the local group object.

public class AdUtil
{
    public static void AddDomainUserToLocalGroup(
        String domain,
        String userName,
        String groupName)
    {
        String groupPath = String.Format("WinNT://{0}/{1},group",
            Environment.MachineName, groupName);
        DirectoryEntry theGroup = new DirectoryEntry(groupPath);

        if (theGroup.SchemaClassName != "Group")
        {
            throw new ArgumentException("The local group specified doesn't exist.");
        } 

        String userPath = String.Format("WinNT://{0}/{1},user", domain, userName);
        theGroup.Invoke("Add", new object[] { userPath });
        theGroup.CommitChanges();
    }
}
Older Posts »

©2009 NetInverse. All rights reserved. Powered by WordPress