Alasdair 的个人资料alasdair's brain dump日志列表网络 工具 帮助

日志


2008/3/31

SIDs, Profiles and Vista, oh my!

I lost my domain controller last August, and despite some fair efforts to rebuild it, I ended up just buying a proper server instead of the crappy workstation which I had been using for the last five years (I wonder why it died?!). Feeling kinda brave, I stuck Windows 2008 and Hyper-V beta on it and created a VM for my new DC, and installed Windows 2003 R2 in the VM. This has all been find and dandy, and I got most of the machines in the shop talking to the new DC, but not my Vista Business x86 development rig, 'cos I didn't have time to fix it. And then I just carried on. And on.

So, today, I get a call and I need to write some code on an intranet that uses Windows integrated authentication. So I have to fix the Dev rig.

I didn't want to lose my user profile, and I haven't. The basic idea is to get the SID changed in your profile so it matches the SID on your new domain. Here's what I did:

  1. Read http://support.microsoft.com/kb/930955
  2. Download & install Windows6.0-KB930955-x86.msu
  3. Reboot
  4. Log on as local administrator
  5. Remove the PC from the old domain by joining a new workgroup (Start, right-click on Computer, Properties, in Computer name, domain... click Change Settings)
  6. Reboot
  7. Log on as local administrator
  8. Join the new the PC to the new domain (same as joining workgroup)
  9. Reboot (getting tedious this, init?)
  10. Log on as domain administrator (or at least a domain account with local admin access)
  11. Find the old SID - this is easy - it appears in all the permission lists for objects (e.g. files) that belonged to the the old user. Mine was S-1-5-21-606747145-1677128483-854245398-1017.
  12. Knobble this here vbs script to set the variables at the top and run it:

    ' Connect an old profile with a new user account

    ' For Vista

    ' *Requires* this installed: http://support.microsoft.com/kb/930955

    strComputer = "."
    strSidOld = "S-1-5-21-606747145-1677128483-854245398-1017"
    strNewDomain = "ACS-SOLUTIONS"
    strNewUsername = "alasdair"

    Set objWMIService = GetObject( "winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2" )
    Set objUserProfile = objWMIService.Get( "Win32_UserProfile.SID=""" + strSidOld + """" )
    Set objAccountNew = objWMIService.Get( "Win32_UserAccount.Domain=""" + strNewDomain + """,Name=""" + strNewUsername + """" )

    WScript.Echo objUserProfile.SID
    WScript.Echo objAccountNew.SID

    Set oInParams = objUserProfile.Methods_( "ChangeOwner" ).InParameters.SpawnInstance_()
    oInParams.Properties_.Item("Flags") = 0
    oInParams.Properties_.Item("NewOwnerSID") = objAccountNew.SID

    'Leave this in until you're sure you're good to go...
    ' WScript.Quit

    Set oOutParams = objWMIService.ExecMethod( "Win32_UserProfile.SID=""" + strSidOld + """", "ChangeOwner", oInParams )

    WScript.Echo "Done & Dusted"
  13. Log off
  14. Log on as your domain account
  15. Wonder at the desktop background, the icons, the start menu - ah - Joy!

Gotchas - not many so far, except Visual Studio encrypts the information in the connection string in Server Manager. It says "Key not valid for use in specified state". The easy fix is just to delete all of them and add them again. Apparently you can also delete the underlying file in your profile: see http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=199339&SiteID=1

2008/3/27

System.Transactions and the Silent Timeout of Death

There's a huge whopping gaping hole of a bug in .NET 2.0 (and also by default in .NET 3.5) with the interaction between the native SqlClient and the System.Transactions code when lightweight transactions are in use.
 
Basically, it goes like this
  1. You start a transaction with a time out
  2. You do some work on your transacted connection
  3. The timeout triggers in the background, and
    1. The transaction gets rolled back
    2. The connection is left in the default "auto commit" mode
    3. NO EXCEPTION GETS RAISED
  4. You do some more work on what you think is your transacted connection and NO EXCEPTION GETS RAISED
  5. You go to commit or rollback and it raises an exception which says "What transaction? I already rolled it back!"

Now, go look in the database, and Shock! Horror! All the stuff you did in Step 2 has been rolled back, but all the stuff you did in step 4 is there! Half a transaction! Argh!

Go see the initial report of this bug and the admission from Microsoft and their belated and weak fix for it in this thread.

 

GPMC - Group Policy Management Console for .NET 2.0 and Windows x64

Received wisdom has it that GPMC won't work on x64 and won't work unless .NET 1.0 or 1.1 is installed. All basically true, except as far as I can see it's only a restriction in the installer.

Darren Mar-Elia pointed out that it's possible to use Orca from the Microsoft Windows Software Development Kit to hack the msi file and remove the .NET 1.0/1.1 checks. I didn't want to spend ages getting the whole SDK, but found a recent copy of the orca.msi on mitchb's Technipages.

I went a bit cleverer (I hope) than Darren and instead of ripping out the .NET framework checks, I extended them to check for and permit the v2.0 framework.

I've built a knobbled version called gpmc.net2.msi. It has the benefit that it installs and seems to run OK on Windows Server 2003 x64. The only gotcha I've found so far is that it expects to find gpedit.msc in the same directory as itself, but it gets pushed into the %SystemRoot%\SysWOW64 whereas gpedit.msc is in %SystemRoot$\System32. I just copied the one from System32 to SysWOW64 and all seems to be fine and dandy.

Obviously - use at your own risk. If it formats your hard drive, don't come running to me...