Showing posts with label Citrix. Show all posts
Showing posts with label Citrix. Show all posts

Wednesday, January 30, 2008

Latest Project: Server Monitoring Using WMI

It was a while since my last post. Year ender is quite busy and the new year was as much.

I've been working on a latest project for our team. I set up a monitoring server running WMI scripts against remote servers in intervals of 2 or 30mins (depending on the frequency of data required).

Below are few simple snippets I used in to collect remote data and pump it in an html template and send it via email to the team (if ever performance thresholds were exceeded).

Code Snippets:

  1. Sub DisplayErrorInfo
  2. WScript.Echo "Error: : " & Err
  3. WScript.Echo "Error (hex) : &H" & Hex(Err)
  4. WScript.Echo "Source : " & Err.Source
  5. WScript.Echo "Description : " & Err.Description
  6. Err.Clear
  7. End Sub

#1 Bytes Converter Snippet (
One of my favorite snippet, pretty handy!)

  1. Function SetBytes(Bytes,fKB)
  2. If fKB=True then Bytes = Bytes * 1024
  3. If Bytes >= 1073741824 Then
  4. SetBytes = FormatNumber((Bytes / 1024 / 1024 / 1024),2,,-1,-1) & " GB"
  5. ElseIf Bytes >= 1048576 Then
  6. SetBytes = FormatNumber((Bytes / 1024 / 1024),2,,-1,-1) & " MB"
  7. ElseIf Bytes >= 1024 Then
  8. SetBytes = FormatNumber((Bytes / 1024),2,,-1,-1) & " KB"
  9. ElseIf Bytes <>
  10. SetBytes = Bytes & " Bytes"
  11. End If
  12. End Function

#2 Get Available Memory on the server

  1. strComputer = "."
  2. Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
  3. Set colItems = objWMIService.ExecQuery _
  4. ("Select * From Win32_PerfRawData_PerfOS_Memory")
  5. For Each objItem in colItems
  6. intValue = objItem.AvailableBytes
  7. Wscript.Echo "Available memory = " & SetBytes(intValue,false)
  8. Exit For
  9. Next

Note: This requires cooking. If you you have no idea how that works then just use AvailableMBytes instead.

#3 Get CPU Usage (%)

  1. Function GetCPUProcUsg(svr)
  2. c = 0
  3. strComputer = "."
  4. Set objWMIService = GetObject("winmgmts:\\" _
  5. & strComputer & "\root\cimv2:Win32_PerfRawData_PerfOS_Processor.Name='_Total'")
  6. If Err = 0 Then
  7. While (True)
  8. N1 = objWMIService.PercentProcessorTime
  9. D1 = objWMIService.TimeStamp_Sys100NS
  10. Wscript.Sleep(1000)
  11. Set objWMIService2 = GetObject("winmgmts:\\" _
  12. & strComputer & "\root\cimv2:Win32_PerfRawData_PerfOS_Processor.Name='_Total'")
  13. N2 = objWMIService2.PercentProcessorTime
  14. D2 = objWMIService2.TimeStamp_Sys100NS
  15. PercentProcessorTime = (1 - ((N2 - N1)/(D2-D1)))*100
  16. Wscript.Echo "Processor Usage: " & Round(PercentProcessorTime,2) & "%"
  17. GetCPUProcUsg = Round(PercentProcessorTime,2) & "%"
  18. Wend
  19. Else
  20. DisplayErrorInfo
  21. End If
  22. Set objWMIService = nothing
  23. Set objWMIService2 = nothing
  24. End Function

#4 Get Available Disk Space
  1. strComputer = "."
  2. strUser =
  3. strPass =
  4. Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
  5. Set oWMI = objSWbemLocator.ConnectServer(strComputer, "root\cimv2", strUser, strPass)
  6. Set colDisks = oWMI.InstancesOf("win32_PerfRawData_PerfDisk_LogicalDisk.Name")
  7. For Each objDisk in colDisks
  8. intBaseValue = objDisk.PercentFreeSpace_Base
  9. dblActualFreeSpace = (100 * objDisk.PercentFreeSpace) / intBaseValue
  10. Wscript.Echo objDisk.Name & Int(dblActualFreeSpace)
  11. Next


If at first you fail, call it version 1.0

Thursday, September 13, 2007

HowTo: Enum Citrix Server License using LMSTAT

Our PS4 server seems to fail to execute the license information scripts from Citrix.Com (Dependency on SDK).

So instead of relying on it, I decided to develop a script using LMSTAT and a short vb script to parse the output file and write it to a .CSV file for better viewing (Data Filtering and such...)

First I piped the result of lmstat -a to a text file then I used the script below to parse the contents then write it to a .CSV file

Code Snippet:

Parse the source file (lmstat output file): srcfile

  1. Sub GetData(srcfile)
  2. Set f = fso.GetFile(srcfile)
  3. Set ts = f.OpenAsTextStream(ForReading, TristateUseDefault)
  4. Do While ts.AtEndOfStream <> True
  5. readResults = Trim(UCase(ts.ReadLine))
  6. If InStr(readResults, "/27000") Then
  7. mps = split(readResults, Chr(32))
  8. msg = mps(1) & "," & mps(3) &amp; "," & mps(4) &amp;amp; "," & mps(5) & mps(6) & mps(8) &amp;amp; " " & mps(9) &amp;amp; " " & mps(10)
  9. WriteToCSV msg, license_out
  10. End If
  11. Loop
  12. End Sub

Write to CSV function: oCsv(Output File), msg(parsed ReadLine results)


  1. Function WriteToCSV(oCsv,msg)
  2. If Not fso.FileExists(oCsv) Then fso.CreateTextFile(oCsv)
  3. Set f = fso.GetFile(oCsv)
  4. Set ts = f.OpenAsTextStream(ForAppending, TristateUseDefault)
  5. ts.Write msg & vbCrlf
  6. msg = ""
  7. ts.Close
  8. End Function
If at first you fail, call it version 1.0

Friday, July 13, 2007

MFCOM: Farm Session Count

Another day of Citrix Administration, a simple MFCOM script to view Active Farm Sessions.

Code Snippet:

  1. Const cMetaFrameWinFarmObject = 1
  2. Const MFSessionStateActive = 1
  3. Set theFarm = CreateObject("MetaFrameCOM.MetaFrameFarm")
  4. theFarm.Initialize(cMetaFrameWinFarmObject)
  5. intSessionCount = 0
  6. intActiveCount = 0
  7. For Each oSession In theFarm.Sessions
  8. intSessionCount = intSessionCount + 1
  9. If (oSession.SessionState = MFSessionStateActive) and (oSession.SessionName <> "Console") Then
  10. intActiveCount = intActiveCount + 1
  11. WScript.Echo vbcrlf & "*****************************"
  12. WScript.Echo "User Name: " & oSession.UserName
  13. WScript.Echo "IP Address: " & oSession.ClientAddress
  14. WScript.Echo "Server: " & oSession.ServerName
  15. WScript.Echo "Application: " & oSession.AppName
  16. WScript.Echo "Logon Time: " & oSession.ConnectedTime
  17. End If
  18. Next
  19. WScript.Echo "Total Session Count = " & intSessionCount & vbcrlf & _
  20. "Active Session Count = " & intActiveCount


If at first you fail, call it version 1.0

MFCOM: Connection licenses and usage count

Yet Another Citrix Administrator Task, monitor the connection licenses and usage count in the farm...

Feel like a hill billy...

Code Snippet:

  1. Dim fso
  2. Set fso = CreateObject("Scripting.FileSystemObject")
  3. If not fso.FolderExists("c:\liclog" ) then
  4. Set MyFolder = fso.createFolder("c:\liclog" )
  5. else
  6. End if
  7. if not fso.FileExists("c:\liclog\licCount.log" ) then
  8. Set MyFile= fso.createTextFile("c:\liclog\licCount.log")
  9. MyFile.writeline "Date " & " Time " & "Lic Type " & "Used"
  10. MyFile.close
  11. else
  12. end if
  13. Const ForAppending = 8
  14. Set MyFile= fso.OpenTextFile("c:\liclog\licCount.log", ForAppending,True)
  15. Dim theFarm, aLicense
  16. Set theFarm = CreateObject("MetaFrameCOM.MetaFrameFarm")
  17. ' Initialize the farm object.
  18. theFarm.Initialize(MetaFrameWinFarmObject)
  19. For Each aLicense In theFarm.LicenseSets(MFLIcenseClassConnection)
  20. if aLicense.LicenseID = "0000000000000003" then
  21. MyFile.WriteLine date & "," & time & "," & aLicense.Name &amp;amp; "," & aLicense.pooledinuse("")
  22. else
  23. end if
  24. next
  25. MyFile.Close


If at first you fail, call it version 1.0

Monday, July 09, 2007

KD Memory.dmp debugging

One of our Citrix server encountered a BSOD, luckily we had RSA and managed to hard reboot the server.

I've gathered the memory dump to view the cause of BSOD and found the Symantec Antivirus has caused a module error on the NIC driver.

We have then disabled the Network Drives in the File System Auto Protect and it had not experienced the same ever since.

Did not find any help from Symantec regarding the root cause other than it's a known issue.

Below are some steps that you could use for debbuging:

  1. Launch windbg passing it the location of the symbol files, the source files (i386 directory) and the dump file. Example: windbg -y dump\symbols -i SRC\i386 -z dump\Memory.dmp

  2. At the bottom of the Command window there is a kd> prompt.

  3. The commands are entered into that prompt: kd>!analyze -v

  4. Two things to look for in the results: the memory referenced and the FAULTING_IP

  5. The command: kd>lm - will produce a listing of modules and their memory location.

  6. Look to see which module's memory the memory referenced identified above falls in.

  7. That usually indicates the process that caused the crashed and will probably match the FAULTING_IP if listed.

  8. Also informative: kd>.reload –v

If at first you fail, call it version 1.0

Monday, June 18, 2007

ADSI Kixtart UDF for Citrix login

Having a mixed mode environment gave us a lot of hassle when logging in to NT and querying group membership in AD... Specially in our case, we have nested OU's...

Ifmember.exe is useful for this problem but it does cause a slight delay in the login process and the users are complaining on the slow login session, some couldn't wait and cancels the connection... catastrophic experience ends up as a global complain... hmmm... some people are just impatient...

So to be able to execute an ADSI query through kix login script the function below can be inserted anywhere in the login script to perform InGroup query... or this can fully replace the built in InGroup function in kixtart.


Code Snippet:

  1. Function fnInGroupAD($sGroup,Optional $bComputer)
  2. Dim $objSys,$objTarget,$aMemberOf,$sMemberOf
  3. $objSys = CreateObject("ADSystemInfo")
  4. $objTarget = GetObject("LDAP://"+Iif($bComputer,$objSys.ComputerName,$objSys.UserName))
  5. $aMemberOf = $objTarget.GetEx("memberOf")
  6. For Each $sMemberOf in $aMemberOf
  7. If InStr($sMemberOf,"CN="+$sGroup+",")
  8. $fnInGroupAD = Not 0
  9. Exit
  10. EndIf
  11. Next
  12. $fnInGroupAD = NOT 1
  13. EndFunction

If at first you fail, call it version 1.0

Wednesday, June 13, 2007

String manipulation in NT scripts

I was working on a Citrix Login script and found out most clients are not able to perform WMI queries to get session information from the server or just simple evironment variable expansion... or is it just our GPO is just too tight?

Instead of using vbscript for the string manipulation, I opted to the old school NT scripting, since the built in usrlogon script in PS4 is native to NT.

So I searched the help files and the net for old DOS commands for string manipulation as my goal for this script is to get the first 2 characters from the environment variable %CLIENTNAME%. If the machine name's first 2 characters are "UK", then a certain drive is required to be mapped.

Now, It is possible to retrieve specific characters from a string variable.

Syntax:
%variable:~num_chars_to_skip%
%variable:~num_chars_to_skip,num_chars_to_keep%

This can include negative numbers:
%variable:~num_chars_to_skip, -num_chars_to_skip%
%variable:~-num_chars_to_skip,num_chars_to_keep%

A negative number will count backwards from the end of the string. In Windows NT 4 the syntax for negative numbers was not supported.

Examples:
The variable _test is used for all the following examples:

SET _test=123456789abcdef0

::Extract only the first 5 characters

SET _result=%_test:~0,5%
ECHO %_result% =12345

::Skip 7 characters and then extract the next 5

SET _result=%_test:~7,5%
ECHO %_result% =89abc

::Skip 7 characters and then extract everything else

SET _result=%_test:~7%
ECHO %_result% =89abcdef0

::Extract only the last 7 characters

SET _result=%_test:~-7%
ECHO %_result% =abcdef0

::Extract everything BUT the last 7 characters

SET _result=%_test:~0,-7%
ECHO %_result% =123456789

::Extract between 7 from the front and 5 from the end

SET _result=%_test:~7,-5%
ECHO %_result% =89ab

::Go back 7 from the end then extract 5 towards the end

SET _result=%_test:~-7,5%
ECHO %_result% =abcde

::Extract between 7 from the end and 5 from the end

SET _result=%_test:~-7,-5%
ECHO %_result% =ab

And this is the final script:
SET _CNAME=%CLIENTNAME%
CALL SET _ORIGIN=%_CNAME:~-0,2%

IF %_ORIGIN% EQU UK (
NET USE R: \\UKFILSERVER\CITRIX$
) ELSE (
GOTO Done
)

:Done

If at first you fail, call it version 1.0