dotNoted

Icon

Observations of .Net development in the wild

Clobbering the %PATH% var with EnvironmentVariableTarget

If you use Environment.GetEnvironmentVariable("Path") to get the Path and later set it via Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine), you will kill your path, since the former retrieves it from the process’s environment block, which includes both Machine and User environments (and more sometimes). I did this block-headed thing, and set my path a couple of times, and it grew to be too long and got truncated. Ouch. Developer tools stop working quickly if that happens.

Thankfully, the machine environment on a Windows NT kernel based OS is controlled by a key in the System key of the HKLM hive: HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment. This means that on a successful boot, the control set is copied over to a second key called ControlSet002. This is how "Last Known Good Configuration" recovery is accomplished – Windows just uses this backup key if you hit F8 and "Last Known Good" at boot. This means my old path should be in HKEY_LOCAL_MACHINESystemControlSet002ControlSession ManagerEnvironment. Bingo, it was. What a relief.

So, don’t forget to call your Environment.GetEnvironmentVariable and Environment.SetEnvironmentVariable methods with matching EnvironmentVariableTarget values, unless you have a carefully considered reason.

Filed under: Uncategorized

Getting more than 1000 results from a DirectorySearcher query

Ok, this isn’t exactly clear. Need to make a note of this so I don’t forget it. The DirectorySeacher only returns 1000 results when the defaults are used. This setting actually comes from an AD server, not the .Net stuff, or even the ADSI or LDAP protocol implementation which are under the covers. So, basically, it’s as good as hard-coded. ADSI helps out here, and we can take advantage of it, by just setting the DirectorySearcher.PageSize to a number besides 0. I like to set it to the DirectorySearcher.SizeLimit default which is 1000 (actually, it’s 0, but this means 1000). This actually makes ADSI make as many paged requests as needed to get the entire result set, not just the first SizeLimit records. The docs aren’t terribly clear on this, and I try to make repeated requests to the server until the resulting SearchResultsCollection’s Count property is less than the searcher’s PageSize property… which doesn’t work since ADSI has done this bit for me and now I’m sitting with all the results in the collection. Here’s how to get all the users (with a few properties) in the domain [in IronPython]:

import clr
from System import *
clr.AddReference("System.DirectoryServices")
from System.DirectoryServices import *
from System.Collections.Generic import *

searcher = DirectorySearcher()
searcher.PageSize = 1000

def GetDomainUsers():

  searcher.Filter = "(&(objectClass=user)(sAMAccountName=*)(!objectClass=computer))"
  searcher.PropertiesToLoad.Add("userPrincipalName")
  searcher.PropertiesToLoad.Add("userAccountControl")
  searcher.PropertiesToLoad.Add("sAMAccountName")
  l = List[SearchResult]()
  domainResults = searcher.FindAll()

  l.AddRange(domainResults)
  domainResults.Dispose() # Get rid of the unmanaged ADSI resources ASAP

return l

Filed under: .Net Basics

DirectoryInfo and Path rely on ancient technology – the sad story of MAX_PATH

NTFS is a very robust and well architected file system. I like it. I’ve looked at others, like WinFS (not really a core FS, just a layer on NTFS… but good technology idea nonetheless), ReiserFS 4 (my favorite, at least conceptually), XFS and JFS. NTFS plays in the same league with these higher performance creations from the previous age Unix heavyweights, including transactions (Vista and Longhorn), journaling, compression, encryption and a peerless access control system (in my experience). Along with all of this is support for paths which are 2^15 (32768) characters long. This beats the 260 chars of MS-DOS legacy.

Oddly, this is hardcoded into two places – Win32 and the CRT:

<WinBase.h> … #define MAX_PATH 260

<stdlib.h>      … #define _MAX_PATH 260 /* max. length of full pathname */

However, help is at hand… From the MSDN docs:

Note The C Runtime supports path lengths up to 32768 characters in length, but it is up to the operating system, specifically the file system, to support these longer paths. The sum of the fields should not exceed _MAX_PATH for full backwards compatibility with Windows 98 FAT32 file systems. Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003, and Windows Server 2003 NTFS file system supports paths up to 32768 characters in length, but only when using the Unicode APIs. When using long path names, prefix the path with the characters \? and use the Unicode versions of the C Runtime functions.

But, try creating a DirectoryInfo prefixed with \? … you’ll throw an exception since it contains an invalid path char (?). Too bad, since people are finally getting the hang of long file names… one more legacy to detract from the shininess of Vista.

I’ve opened a Connect issue… if you run into this, be sure to vote for it.

Filed under: .Net Basics

DynamicMethod in .Net 2.0 is very powerful, but a debugger visualizer is almost needed to take advantage

We’re creating a dynamic thunk layer to host .Net managed objects in Sybase’s Powerbuilder (both visual and nonvisual objects) and we want a way to mark up our classes with a bit of metadata in the form of Attribute, and then let reflection take over and write the needed Powerbuilder metadata to describe the objects. This works pretty well – reflection is done on a path at design time on the .Net assemblies and the metadata is generated (it isn’t dynamic) for Powerbuilder. At runtime, there were few options since it is dynamic – late-binding calls need to be made in this case. But what about all that great .Net metadata…? Couldn’t we use that to bring a bit more load (or JIT) time binding into the picture, so that the parameters are mapped out in memory to specific method handle locations? Well, in comes DynamicMethod. It is a dynamically built bit of IL which is then, of course, JITted into machine code… at load time. MS calls it Lightweight Code Generation in case you haven’t found this bit already. It’s generally an important component of the dynamic language groundswell in the .Net code space. All sorts of fun ideas from dynamic app reconfiguration and optimization to evolutionary algorithms stand out as being able to be easily taken advantage of. Sure you could always do this with System.Reflection.Emit, but it’s much easier now, since all the assembly stuff is taken out – methods belong to the current assembly.

Debugging one of these dynamic methods is a big pain, though. I went through the trouble of wiring up some debug writelines to get an idea of why my hand crafted IL worked, but the dynamically generated stuff didn’t… and ran into an InvalidOperationException trying to access the GetILAsByteArray method. The exception text is very, very misleading: "System.InvalidOperationException : Operation is not valid due to the current state of the object." What this really means is "Not implemented." For shame! The MethodBase base class throws this. This is what NotImplementedException or NotSupportedException are for, I believe. At least give some textual clues which are not misleading.

So, on a hunt to find a better method of debugging these dynamic methods, I came upon this debugger visualizer. I was skeptical at first, but I tried it out and found it was very nice! It implements the most easily accessible examples like the MSDN doc’s and Joel Pobar’s. Do try when you go down this path… it will save you time and headache. However, you will still need to know IL.

Filed under: Software Engineering

MSysInternals keeps the BSOD going

That MS acquired Sysinternals is old news – but what pleases me is that they are keeping the BSOD screen saver around – they are definitely loosening up as a company.

http://www.microsoft.com/technet/sysinternals/Miscellaneous/BlueScreen.mspx

Filed under: Uncategorized

Be safe: rid yourself of MSXML4

Last week there was a post which finally helped me emerge from the shrouding mists of confusion on MSXML versions. After reading this, I was finally put at ease about which versions are which, and which to use.

Now, apparently, there is a zero-day exploit on MSXML 4. But, according to the well timed post above, we really shouldn’t be using MSXML 4. In fact, Adam made it clear that MSXML 6 is the one to use, if you need MSXML 4 functionality:

MSXML4 was a predecessor to MSXML6 but hasn’t ever shipped in the operating system.  MSXML6 is a significant step forward in terms of reliability, security, W3C and System.Xml compatibility, and it also has support for native 64-bit environments.  Right now we are investing much more heavily in MSXML6 and MSXML3 and we’re encouraging our customers to move to 6 when possible and 3 when necessary.

So, I recommend you kill MSXML 4 from being used on your machine from IE. You can do this with the registry, by setting what is known as the "kill bit". Here’s how you do that from the command line (forget the .reg file approach MS outlines in the workaround).

reg add "HKLMSoftwareMicrosoftInternet ExplorerActiveX Compatibility{88d969c5-f192-11d4-a65f-0040963251e5}" /v "Compatibility Flags" /t REG_DWORD /d 0x400

Of course, this will break sites which use MSXML 4 – but they shouldn’t be doing so. Kindly write them and ask them to redo this bit, pointing to the above clarification on MSXML.

Filed under: Administration

Getting today’s date (without the time) in T-SQL (enhanced)

Ok, I thought about it some more.
 
I have been surprised by all the hits on dotNoted which are looking for ways to express the date without the time in SQL Server’s T-SQL.
 
And I realized how lame the string concatination example looks. So I went back to the drawing board to give you some more T-SQLly goodness. Here’s the result. It keeps the datetime binary throughout, so all the overhead converting to and manipulating strings is eliminated. Plus, it seems a bit more elegant:

DECLARE @datemask bigint

SET

@datemask = 0xffffffffff000000

SELECT

CAST(CAST((CAST(getdate() as binary) & @datemask) as binary(8)) as datetime)


Let’s try to compare the performance of this method to the string method…

DECLARE

@tdate datetime

DECLARE

@datemask bigint

SET

@datemask = 0xffffffffff000000

DECLARE @iterationcount int

SELECT

@iterationcount = 1000000

DECLARE

@start datetime

DECLARE @end datetime

DECLARE

@i int

SELECT

@i = 0

SELECT @start = getdate()

WHILE(@i < @iterationcount)

BEGIN

SELECT @tdate = CAST(CAST((CAST(getdate() as binary) & @datemask) as binary(8)) as datetime)

SELECT @i = @i+1

END

SELECT

@end = getdate()

SELECT

@end @start as "Binary Method Time"

SELECT

@i = 0

SELECT @start = getdate()

WHILE

(@i < @iterationcount)

BEGIN

SELECT @tdate = CAST(YEAR(getdate()) as varchar) + RIGHT(’00’+CAST(MONTH(getdate()) as varchar), 2) + RIGHT(’00’+CAST(DAY(getdate()) as varchar), 2)

SELECT @i = @i+1

END

SELECT

@end = getdate()

SELECT

@end @start as "String Method Time"

Here are the results after iterating 1,000,000 times –

Binary Method Time: 2.22 sec

String Method Time: 3.517 sec

Not very impressive gains, but it probably is worth using the binary method. Not worth converting existing code, however. The succinctness of the binary method is it’s strongest point – it can be inlined into the code more easily than the comparitively unwieldy string method, but if your looking for massive performance gains, they aren’t here. It is a relatively easy thing for the engine to compute, either way.

 

Filed under: Code Kaizen

Windows Vista License Terms Shocker

Well, I’m shocked, shocked, to learn of this change. Windows had been slated to allow reinstall one time on your hardware. The usual suspects had a field day trashing this. I was pretty bummed myself…
 
But that changed today:
 
They apparently heard the feedback, and are changing the license terms…. MS changing the license terms to suit customer wishes? Now I am convinced they are trying to change their evil ways.

Filed under: Metathought