Archive: January, 2011

XenClient and Provisioning Services

1 comment January 28th, 2011

So! I was supposed to go and have a lecture on Provisioning Services a few weeks ago and i needed a demo. As im running XenClient on my laptop, and with the SP1 update XenClient gets support to provisioning services! So i thought why not set up an internal Provisioning Server on my XenClient? How hard can it be!

Well it wasnt that hard, you just need a little bit of Linux knowlege to be able to do it!

I started out by installing a Server 2003 with provisioning services, only problem I had with this was to get XenClient tools installed but it works good.  I configured local storage and the PVS server was up and running. Oh and i also installed the Licens Server, to be able to get licensing going for the PVS.

I had to decide on which network to use for provisioning thou, i dont want it spam dhcp stuff outside of my laptop, so first i thought hey lets use the internal network option in xenclient to isolate the network. Turns out there is a bug thou in XenClient that wont turn on the internal network unless there is a cable plugged in the physical network port. That sucked! What about the wireless?

In xenclient all guests share the wireless and they all get an internal address, so it suited me fine! Now all i needed to do was to add the dhcp options to the internal dhcp server. XenClient uses dnsmasq as a dhcp server and dns forwarder.  All i needed to do was to edit /etc/dnsmasq.brwireless and add the options there! Awesome. So now all i need to do is install a Master Target Device!

I created a new guest, called it MTD and installed XP on it. When it was finished I installed the PVS tools to make an image of it and runned the wizard. Of course i configured the guest to also use the wireless network. It prepared XP to be sucked into PVS and rebooted. When it was rebooting I turned it of and set it to only boot on network. Started it again, crossed my fingers and waited for it to boot on the network. It started good I saw it got the bootfilename to boot from, but it wouldnt boot! It timed out all the time. When i looked closer it tried to boot from the PVS netboot image, but from the wrong server! The ip i had specified in the dhcp-option wasnt used. It tried to connect to which is the XenClient host OS. After some fiddling around with dnsmasq and confirming that i entered the correct ip to the PVS server i found somewhere on google that some networkcards have problems with that option. And they default to dhcp server. This meant i couldnt get it to boot from the PVS unless the PVS was the dhcp server!

Well no problem, i disabled dhcp part of dnsmasq and installed the builtin dhcp-service from windows and configured it with the same options. Tried to boot the MTD again and voila! I was making a Golden Image of my XP!

All i had to do then was to create a new guest, called it TD1 and make it boot from the network! I had to make a local drive to the guest as you have to create a disc with every XenClient guest. But made it just 1 gb so thats no biggie.

So now i have my laptop running a provisioned XP client wherever i go. Im going to make a win7 guest that i can use as my private image. This works really good and as im a consultant can use a clean image at every new job!

Downsides thou that i havnt had time yet to work out, shouldnt be a problem thou, is that i always have to be connected to a wireless network as the guest will thing the network is disabled otherwise! But all i need to do is to figure out how to activate the network manually. Or wait until citrix fixes that bug to be able to use the dedicated internal network!

VB script to get VirtualIP

3 comments January 26th, 2011

I built this script to get the virtual ip of the usersession as i needed to send that to the application when the user started. I built two versions of it one using mfcom, the user needs to have certain admin rights in the farm to get this going which I dont like, and the other uses WMI and the registry to figure it out. Its not perfect and should be modified to fit your situation. It will only get the last sessions virtualip, as thats all i needed. So if the user has 2 sessions going you will only get the last one of them.

It is very not documented as i was in abit of rush writing it. Sorry for that! =)

** Updated with bug fix discussed in the comments thnx Augustin **

Here is the script (sesInfo.vbs):

‘ Written by Roger Eklund (roger.eklund at
‘ Use at your own risk!
‘ To get the Client Virtual IP run “sesInfo.vbs ip”
‘ To get the Client hostname run “sesInfo.vbs clientname”

Const HKCR = &H80000000 ‘HKEY_CLASSES_ROOT
Const HKCU = &H80000001 ‘HKEY_CURRENT_USER
Const HKU  = &H80000003 ‘HKEY_USERS
Const REG_SZ        =1
Const REG_BINARY    =3
Const REG_DWORD     =4
Const REG_MULTI_SZ  =7
Const MetaFrameWinFarmObject = 1
Const MetaFrameWinSrvObject = 6
Const Active=1
Const Connected=2

args = WScript.Arguments.Count

If args < 1 then
WScript.Echo “usage: sesInfo.vbs [ip|clientname]”
wscript.echo “Will get either VirtualIP of the client”
wscript.echo “or the Clientname”
end If

choice = ucase(wscript.arguments.item(0))

Select Case choice
Set oReg = GetObject( “winmgmts:!root/default:StdRegProv” )
curUser = GetCurrentUser(“.”)
uSid = GetSIDFromUser(curUser)
wscript.echo vbCrLf & GetVal(hkey,uSid+”\Volatile Environment” , “CLIENTNAME”)
Case “IP”
Set oReg = GetObject( “winmgmts:!root/default:StdRegProv” )
path = “SOFTWARE\Citrix\VIP\” & SessionID
Vip = GetVal(hkey,path , “VIPAddress”)
wscript.echo hex2ip(Vip)
Case Else
wscript.echo “omg”
End Select
Function hex2ip(hex)
Dim oct1
Dim oct2
Dim oct3
Dim oct4
Dim IPadress

If len(hex) = 7 Then
hex = “0″ & hex
end if

if len(hex) > “8″ or len(hex) < “8″ Then
wscript.echo “Not a Hex number: ” & hex
end if

oct1 = (Mid(hex, 1, 2))
oct2 = (Mid(hex, 3, 2))
oct3 = (Mid(hex, 5, 2))
oct4 = (Mid(hex, 7, 2))
hexNumber1 = “&H” & oct1
hexNumber2 = “&H” & oct2
hexNumber3 = “&H” & oct3
hexNumber4 = “&H” & oct4
int1 = CLng(hexNumber1)
int2 = CLng(hexNumber2)
int3 = CLng(hexNumber3)
int4 = CLng(hexNumber4)
hex2ip = int1 & “.” & int2 & “.” & int3 & “.” & int4
End Function
Function convertIP(BinIP)

Dim x
Dim Num
Dim IPNumeric
Dim IPAddy

IPNumeric = BinIp

For x = 1 To 4

Num = int(IPNumeric / 255 ^ (4 – x))
IPNumeric = IPNumeric – (Num * 255 ^ 4 – x)

If Num > 255 Then
IPConvert = “″
wscript.echo(“fail” & Num)
End If

If x = 1 Then
IPAddy = Num
IPAddy = IPAddy & “.” & Num
End If


End Function
Function GetVal( strHive, strTree, strKey )

‘ Read all keys and their values for the entire section into an array
If oReg.EnumValues( strHive, strTree, sKeys, iKeyType ) Then
GetVal = “-None-”
For Count = 0 to UBound( sKeys )
‘ Select the requested key
If strKey = sKeys( Count )  Then
‘ Format the output

Select Case iKeyType( Count)
oReg.GetStringValue strHive, strTree, sKeys( Count ), sValue
GetVal = sValue
oReg.GetExpandedStringValue strHive, strTree, sKeys( Count ), sValue
GetVal = sValue
oReg.GetBinaryValue strHive, strTree, sKeys( Count ), aValue
GetVal =  Join( aValue,”” )
oReg.GetDWORDValue strHive, strTree, sKeys( Count ), lValue
GetVal = hex(lValue)
oReg.GetMultiStringValue strHive, strTree, sKeys( Count ), sValue
GetVal =  Join( sValue,”” )
End Select
End If
GetVal = GetVal
End If
End Function

Function GetCurrentUser(sstrComputer)
On Error Resume Next
Dim sstrKeyPath,sstrCU,sstrCUD,sstrCurrentUser,sstrCurrentUserDomain
Set sobjRegistry = GetObject(“winmgmts:\\” & sstrComputer & “\root\default:StdRegProv”)
sstrKeyPath = “SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon”
sstrCU = “DefaultUserName”
sstrCUD = “DefaultDomainName”
sobjRegistry.GetStringValue sHKEY_LOCAL_MACHINE, sstrKeyPath, sstrCU, sstrCurrentUser
sobjRegistry.GetStringValue sHKEY_LOCAL_MACHINE, sstrKeyPath, sstrCUD, sstrCurrentUserDomain
GetCurrentUser = sstrCurrentUserDomain & “\” & sstrCurrentUser
End Function
Function GetSIDFromUser(UserName)

Dim DomainName, Result, WMIUser
If InStr(UserName, “\”) > 0 Then
DomainName = Mid(UserName, 2, InStr(2,UserName, “\”) -2)
UserName = Mid(UserName, InStr(2, UserName, “\”) + 1)
DomainName = CreateObject(“WScript.Network”).UserDomain
End If
On Error Resume Next
Set WMIUser = GetObject(“winmgmts:{impersonationlevel=impersonate}!” _
& “/root/cimv2:Win32_UserAccount.Domain=’” & DomainName & “‘” _
& “,Name=’” & UserName & “‘”)
If Err = 0 Then Result = WMIUser.SID Else Result = “”
On Error GoTo 0
GetSIDFromUser = Result
End Function
Function GetSessionID()
Dim TheFarm, TheSession, TheSession2
Dim sessionID, strComputerName
SessionID = -1

Set objWSHNet = CreateObject(“WScript.Network”)
strServerName = objWSHNet.ComputerName
Set TheFarm = CreateObject(“MetaFrameCOM.MetaFrameFarm”)
Set TheSession = theFarm.GetSession(MetaFrameWinSrvObject, strServerName, SessionID)
strSessionID = TheSession.SessionID
GetSessionID = strSessionID
End Function