StrCmpLogicalW (shlwapi)
Last changed: -79.206.146.153

.
Summary
'Logical' sorting (i.e. natural sorting) of Unicode strings - the way Windows Explorer sorts filenames on XP.

C# Signature:

[DllImport("shlwapi.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
static extern int StrCmpLogicalW(string x, string y);

VB Signature:

Declare Unicode Function StrCmpLogicalW Lib "shlwapi.dll" (ByVal s1 As String, ByVal s2 As String) As Int32

User-Defined Types:

None.

Alternative Managed API:

Do you know one? Please contribute it!

Notes:

Comparison is case insensitive, numbers are treated by numerical value instead of ASCII code, for example:

File1
fIle2
fiLe10

instead of

File1
fiLe10
fIle2

Note
for some reason, Vista Explorer appears to use a different sorting algoritm. The result is similar, but non-alphanumeric characters such as parentheses are ordered differently.

Tips & Tricks:

Please add some!

C# Sample Code:

public class StringLogicalComparer : Comparer<string>
{
   [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
   private static extern int StrCmpLogicalW(string x, string y);

   public override int Compare(string x, string y)
   {
     return StrCmpLogicalW(x, y);
   }
}

Or, since C# 8:

public class StringLogicalComparer : Comparer<string>
{
   [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
   private static extern int StrCmpLogicalW(string? x, string? y);

   public override int Compare(string? x, string? y) => StrCmpLogicalW(x, y);
}

VB Sample Code:

Private Class StringLogicalComparer
   Inherits Comparer(Of String)

   Private Declare Unicode Function StrCmpLogicalW Lib "shlwapi" _
     (ByVal s1 As String, ByVal s2 As String) As Integer

   Public Overrides Function Compare(ByVal x As String, ByVal y As String) _
     As Integer _

     Return StrCmpLogicalW(x, y)
   End Function
End Class

Private Sub Test()
  Dim cp As New StringLogicalComparer
  Debug.WriteLine(cp.Compare("a", "a"))    ' 0
  Debug.WriteLine(cp.Compare("1", "1"))    ' 0
  Debug.WriteLine(cp.Compare("a1", "a2"))  ' -1
  Debug.WriteLine(cp.Compare("a10", "a2")) ' +1
End Sub

Documentation