Page 1 of 1 1
Topic Options
#212573 - 2017-07-04 05:11 PM Best Procedure for using server names in script
Robdutoit Offline
Hey THIS is FUN
***

Registered: 2012-03-27
Posts: 363
Loc: London, England
Seems like ages since I last visited as I hardly do much scripting anymore as everything is working! Hope that everyone is alive and well and enjoying life.

I have encountered a problem that really needs resolving. Years ago when I setup my existing clients, I gave the servers the same names at each client so as to make scripting easy in that my current global coding is $ServerName = "\\Serverwhatever" etc.

This made it easy to just use $servername everywhere in the script for Wsus, locations to text files required by the scripts etc.

However, with new clients coming onboard this year and with them using different names for their servers, the Global Coding $ServerName = "\\Serverwhatever" in my udfs.kix file is not practical as I have to keep changing the "\\serverwhatever" to whatever the server name is in the udf file. I use the same script for every client, so I only have one script to update.

Why do you guys do to address this issue as I don't think a readline (handle) type coding works in global. But if I want to install a printer for example, I need to have \\servername\printername in the script. I do a readline (handle) for the printer name, no problem, but thats not global and I need the server names global as there are many lines of coding pointing to \\servername\location whether is wsus, printer, a specific directory, mapped drive etc.

Thanks

Top
#212574 - 2017-07-04 05:21 PM Re: Best Procedure for using server names in script [Re: Robdutoit]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4545
Loc: USA
Use INI files, dude. The tools are built into kix for easy manipulation.

Better yet, Glenn wrote complete replacements UDFs for manipulating INI files as arrays. These things are slick as butter, have been thoroughly tested, and kept up to date.

There is a version here that is not the most current although I doubt you would run into any of the issues that were fixed afterwords: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=202790#Post202790

Might need Glenn to post a link to the newer version as his link in the UDF page is broken now \:\(

Top
#212576 - 2017-07-04 05:41 PM Re: Best Procedure for using server names in script [Re: Allen]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4545
Loc: USA
Until Glenn can update all his links to where ever his new site is, here is the current version.

 Code:
;; 
;;=====================================================================================----- 
;; 
;;FUNCTION       IniArray() 
;;                  ReadIniArray()  - subfunction for reading array 
;;                  WriteIniArray() - subfunction for writing array 
;; 
;;ACTION         Reads INI file into an array; 
;;               Writes array to INI format file & reloads the array with fresh data 
;;                 ReadIniArray() reads a Section:Key:Data set from the array 
;;                 WriteIniArray() writes a Section:Key:Data set to the array 
;; 
;;AUTHOR         Glenn Barnas 
;; 
;;VERSION        1.3 - 2014/06/23 - Fixed issue when data contained equal signs. 
;;               1.2 - 2013/04/20 - Read empty section or file, write empty section,  
;;               WriteIniArray() - fix error if duplicate write of null data Added Options 
;;               to IniArray for Write to add blank lines between sections. 
;;               1.1 - 2013/04/17 - Improve file load time on large files. 
;;               1.0 - 2011/08/02 
;; 
;;SYNTAX         IniArray(filename [,array] [,options]) 
;; 
;;PARAMETERS     Filename - REQUIRED - String 
;;               - The name of the INI file to read/write 
;; 
;;               Array - OPTIONAL - Array 
;;               - The properly formatted array to write 
;; 
;;               Options - OPTIONAL - Integer 
;;               - A bitwise settings to control output formatting 
;;               Value   Mode    Description 
;;               1       Write   Adds blank lines between Sections when true 
;;               2       Write   Suppress the array reload on write, useful when no further INI manipulation is planned. 
;; 
;;REMARKS        Reads an entire INI file into an array for processing. There is no 
;;               limit on the size of the INI file, other than any Kix limits on 
;;               general file sizes. On read, blank lines and comments (lines that 
;;               begin with ";" or "#") are ignored. On write, only sections that 
;;               contain data/value pairs are written, mimicing the action of 
;;               WriteProfileString(). Similarly, only Keys that have non-null 
;;               values are written. 
;; 
;;               The secondary functions ReadIniArray() and WriteIniArray() make 
;;               using the IniArray() UDF as easy to use as ReadProfileString() 
;;               and WriteProfileString(), simply requiring calls to IniArray to 
;;               load and then save the INI file. The Read and Write sub-functions 
;;               use the same syntax as the ProfileString functions but reference 
;;               the array instead of the INI file. 
;; 
;;               NOTE: The WriteIniArray function returns the updated array. This 
;;               is the only significant deviation from the WriteProfileString operation. 
;; 
;;               NOTE: During array manipulation, deleted records are set to null 
;;               and not reused. Similarly, when a new key/data pair is added, deleted 
;;               array items are not reused. When the array is written to disk, the 
;;               null records are skipped. When the file is again read, the array will 
;;               only contain valid data with no empty records. 
;;               WRITING an array causes a RE-READ operation, cleaning the empty records. 
;; 
;;               NOTE: IMPORTANT - When using WriteIniArray() to create a new Ini-array, 
;;               you MUST first declare the array via Dim $array[1, 0]. This is not 
;;               necessary if you read an INI file first. 
;;  
;;RETURNS        Returns a two-dimensional array of two-dimensional arrays. The first 
;;               element is the section name, the second element is a two-dimensional 
;;               array consisting of the key/data pairs. 
;; 
;;                 Consider the following simple INI file: 
;;                  [COLORS] 
;;                  Apple=Red 
;;                  Lime=Green 
;;                  [TASTES] 
;;                  Apple=sweet 
;;                  Lime=sour 
;; 
;;                 The call $aINI = IniArray('inifile.ini) would return an array that 
;;                 contained the following values: 
;;                  $aINI[0,0] contains "COLORS" 
;;                  $aINI[1,0] contains an array of data/value pairs from this section 
;;                  - extract with $aData = $aINI[1,0] 
;;                   $aData[0,0] contains "Apple"; $aData[1,0] contains "Red" 
;;                   $aData[0,1] contains "Lime"; $aData[1,1] contains "Green" 
;; 
;;                  $aINI[0,1] contains "TASTES" 
;;                  $aINI[1,1] contains Array of data/value pairs from this section 
;;                  - extract with $aData = $aINI[1,1] 
;;                   $aData[0,0] contains "Apple"; $aData[1,0] contains "Sweet" 
;;                   $aData[0,1] contains "Lime"; $aData[1,1] contains "Sour" 
;; 
;;                  ; the following would return "Sweet", just like ReadProfileString 
;;                  $Taste = ReadIniArray($aINI, 'TASTES', 'Apple') 
;; 
;; 
;;DEPENDENCIES   none 
;; 
;;TESTED WITH    W2K, WXP, W2K3, W2K8, W7 
;; 
;;EXAMPLES       INI FILE READ: 
;;                   $aIni = IniArray('testfile.ini') 
;;                   'File contains ' UBound($aIni, 2) + 1 ' sections' ? 
;; 
;;                 ENUMERATE: 
;;                   For $I = 0 to UBound($aIni, 2) 
;;                     $aData = $aIni[1, $I] 
;;                   
;;                     'Section: ' $aIni[0, $I] ' contains ' UBound($aData, 2) + 1 ' Data/Value elements' ? 
;;                     ' Press a key: ' get $ ? 
;;                    
;;                     For $J = 0 to UBound($aData, 2) 
;;                       $J ': ' $aData[0, $J] ' = ' $aData[1, $J] ? 
;;                     Next 
;;                   Next 
;; 
;;                  ELEMENT READ: 
;;                   ; Return a specific value 
;;                   $Value = ReadIniArray($aIni, 'SectionName', 'keyname') 
;;                   ; Return an array of all section names 
;;                   $aSections = Split(ReadIniArray($aIni), Chr(10)) 
;;                   ; Return an array of Keys in a specific section 
;;                   $aKeys = Split(ReadIniArray($aIni, 'SectionName'), Chr(10)) 
;; 
;;                  ELEMENT WRITE/UPDATE: 
;;                   ; Write a key/value pair in the named section 
;;                   $aIni = WriteIniArray($aIni, 'SectionName', 'keyname', 'Data') 
;; 
;;                  ELEMENT DELETE: 
;;                   ; Remove the named key from the defined section 
;;                   $aIni = WriteIniArray($aIni, 'SectionName', 'keyname') 
;; 
;;                  SECTION DELETE: 
;;                   ; Remove all key/value pairs from the section, deleting the section 
;;                   $aIni = WriteIniArray($aIni, 'SectionName') 
;; 
;;                  INI FILE WRITE: 
;;                   ; Flush the array to the file and then reload the array 
;;                   $aIni = IniArray('testfile.ini', $aIni) 
; 
Function IniArray($_fSrcFile, OPTIONAL $_aDataWrite, OPTIONAL $_Options)
	
  Dim $_                                        ; temp var 
  Dim $_Fp					; file pointer 
  Dim $_C, $_I, $_J, $K				; index pointers 
  Dim $_AddLine, $_NoRead			; Option Vars 
  Dim $_Sect					; Section Name 
  Dim $_aDat					; Data pair array 
  Dim $_aSect[1, 499], $_aData[1, 499]		; Section & Data Arrays 
	
  $_NoRead = 0					; perform read after write 
	
  If $_Options
    If $_Options & 1
      $_AddLine = @CRLF
    EndIf
    If $_Options & 2
      $_NoRead = 1				; write & exit w/o re-reading 
    EndIf
  EndIf
	
	
  ; Obtain a File Handle for Read or Write operations 
  ; ============================================================ 
  $_Fp = FreeFileHandle				; locate an available file handle 
  If Not $_Fp
    Exit 1					; none available - exit 
  EndIf
	
  ; WRITE: verify that we have properly formatted data 
  ; ============================================================ 
  If VarType($_aDataWrite)  > 0			; Write the array to the INI file and exit 
    If VarType($_aDataWrite) < 8192		; data but not an array - exit! 
      Exit 87
    EndIf
	
    Del $_fSrcFile				; delete any pre-existing file 
    $_ = Open($_Fp, $_fSrcFile, 5)		; open the file for write/create 
    If @ERROR Exit @ERROR EndIf			; exit if error opening 
	
    ; Write the section data. If no data exists in the section, do not write anything! 
    For $_I = 0 to UBound($_aDataWrite, 2)
      $_Sect  = $_aDataWrite[0, $_I]		; Section name to write 
      $_aData = $_aDataWrite[1, $_I]		; Data array 
      If UBound($_aData, 2) > -1		; create Sect and write data if data is present 
        $_ = '[' + $_Sect + ']' + @CRLF		; section name 
        $_C = 0
        For $_J = 0 to UBound($_aData, 2)	; key/data pairs 
          If $_aData[1, $_J]			; only write keys that have non-null data 
            $_C = 1
            $_ = $_ + $_aData[0, $_J] + '=' + $_aData[1, $_J] + @CRLF
          EndIf
        Next
        If $_C
          $_ = WriteLine($_Fp, $_ + $_AddLine)	; write the output line 
	EndIf
        If @ERROR
	  $_ = Close($_Fp)			; close the file 
	  Exit @ERROR
	EndIf		; exit if error writing 
      EndIf
    Next
	
    $_ = Close($_Fp)				; close the file 
    ReDim $_aData[1, 0]				; clear array 
	
    If $_NoRead
      exit 0					; exit here without a re-read of the freshly written data 
    EndIf
	
  EndIf
	
  ; READ: Load the ini file into an array 
  ; ============================================================ 
  $_I = -1  $_J = -1				; Initialize index pointers 
  
  $_ = Open($_Fp, $_fSrcFile, 2)		; open the file for read 
  If @ERROR
    ReDim $_aSect[1, 0]
    ReDim $_aData[1, 0]
    $_aSect[1, 0] = $_aData
    $IniArray = $_aSect				; return an empty array 
    Exit @ERROR					; exit if error opening 
  EndIf
	
  ReDim $_aSect[1, 499], $_aData[1, 499]	; Prep Section & Data Arrays for Read 
	
  $_ = Trim(ReadLine($_Fp))			; remove leading/trailing spaces 
	
  While Not @ERROR				; loop through the file contents 
    If Left($_, 1) = '['			; found a section 
	
      If $_I >= 0				; process prior section data, if any 
        If $_J >= 0
        ReDim Preserve $_aData[1, $_J]		; trim data array to size 
        $_aSect[1, $_I] = $_aData
        ReDim $_aData[1, 499]			; create the  
        $_J = -1
        Else
          $_I = $_I - 1				; ignore empty sections 
        EndIf
      EndIf
	
      $_I = $_I + 1				; increment the section index 
      If $_I Mod 499 = 0 And $_I > 0
        ReDim Preserve $_aSect[1, $_I + 500]
      EndIf
      $_aSect[0, $_I] = Split(SubStr($_, 2), ']')[0]
    Else
      If Not InStr(';#', Left($_, 1)) And Len($_) > 2
        $_aDat = Split($_, '=')			; break into array 
        If UBound($_aDat) > 1			; does data have embedded = signs? 
          $_ = $_aDat[1]
          For $K = 2 to UBound($_aDat)		; extract them into a single value 
            $_ = $_ + '=' + $_aDat[$K]
          Next
          $_aDat[1] = $_
          ReDim Preserve $_aDat[1]
        EndIf
        $_J = $_J + 1				; increment the data index 
        If $_J Mod 499 = 0 And $_J > 0
          ReDim Preserve $_aData[1, $_J + 500]
        EndIf
        $_aData[0, $_J] = $_aDat[0]		; Store the value 
        $_aData[1, $_J] = $_aDat[1]		; Store the data 
      EndIf
    EndIf
	
    $_ = Trim(ReadLine($_Fp))			; remove leading/trailing spaces 
  Loop						; done with input data 
	
  $_ = Close($_Fp)				; close the file 
  $_ = 2					; prep for Not Found exit 
	
  ; process the last/only section 
  If $_I >= 0
    If $_J >= 0
      ReDim Preserve $_aData[1, $_J]		; trim data array to size 
      $_aSect[1, $_I] = $_aData
    Else
      ReDim Preserve $_aData[1, 0]
      $_aSect[1, $_I] = $_aData
    EndIf
    ReDim Preserve $_aSect[1, $_I]		; trim section array to size 
    $_ = 0
  EndIf
	
  $IniArray = $_aSect				; return the array 
	
  Exit $_					; exit success 
	
EndFunction
	
	
Function ReadIniArray($_aIniFile, OPTIONAL $_Section, OPTIONAL $_Key)
	
  ; exit immediately if the data format is invalid 
  If VarType($_aIniFile) < 8192			; data but not an array - exit! 
    Exit 87
  EndIf
	
  Dim $_aSectIdx[UBound($_aIniFile, 2)]		; Section Index Array 
  Dim $_I, $_J					; Index pointers 
  Dim $_aData					; Array of Key/Data pairs 
	
  ; Create a section index array 
  For $_I = 0 to UBound($_aIniFile, 2)
    $_aSectIdx[$_I] = $_aIniFile[0, $_I]
  Next
	
  ; If the Section is null, return a delimited string of Sections [same as ReadProfileString(file)] 
  If Not $_Section
    $ReadIniArray = Join($_aSectIdx, Chr(10))
    Exit 0
  EndIf
	
  ; Search the index for a section 
  $_I = aScan($_aSectIdx, $_Section)
  If $_I < 0 Exit 2 EndIf			; section not found - Exit 
	
  $_aData = $_aIniFile[1, $_I]			; Extract the key/value array 
	
  ; Create a Key index for the requested section 
  Dim $_aKeyIdx[UBound($_aData, 2)]
  For $_J = 0 to UBound($_aData, 2)
    $_aKeyIdx[$_J] = $_aData[0, $_J] 
  Next
	
  ; If the Key is null, return a delimited string of Keys [same as ReadProfileString(file, section)] 
  If Not $_Key
    $ReadIniArray = Join($_aKeyIdx, Chr(10))
    Exit 0
  EndIf
	
  ; Search the index for a Key 
  $_J = aScan($_aKeyIdx, $_Key)
  If $_J < 0 Exit 2 EndIf			; Key not found 
	
  $ReadIniArray = $_aData[1, $_J]
	
  Exit 0
	
EndFunction
	
	
Function WriteIniArray($_aIniFile, $_Section, OPTIONAL $_Key, OPTIONAL $_Data)
	
  ; exit immediately if the data format is invalid 
  If VarType($_aIniFile) < 8192			; data but not an array - exit! 
    Exit 87
  EndIf
	
  Dim $_aSectIdx[UBound($_aIniFile, 2)]		; Section Index Array 
  Dim $_I, $_J					; Index pointers 
  Dim $_aData					; Key/Data array 
	
	
  ; Create a section index array 
  For $_I = 0 to UBound($_aIniFile, 2)
    $_aSectIdx[$_I] = $_aIniFile[0, $_I]
  Next
	
  ; Search the index for a section 
  $_I = aScan($_aSectIdx, $_Section)
	
  ; If the section does not exist and Keydata is present - add the section and key/value pair (new Sect:Key:Data) 
  If $_I < 0					; section not found - Add if Data is present 
    If $_Key And $_Data
      $_I = 0					; default to empty array 
      If $_aIniFile[0, 0]
        $_I = UBound($_aIniFile, 2) + 1		; find next section index 
      EndIf
      ReDim Preserve $_aIniFile[1, $_I]		; Add new section 
      ReDim $_aData[1, 0]			; create data array 
      $_aData[0,0] = $_Key			; key 
      $_aData[1,0] = $_Data			; data 
      $_aIniFile[0, $_I] = $_Section		; section name 
      $_aIniFile[1, $_I] = $_aData		; section data 
    Else
      Exit 0					; nothing to do 
    EndIf
  Else						; the section does exist, locate the Key 
	
    ; If the Key is null, delete the section (delete Section) 
    If Not $_Key
      ReDim $_aData[1, 0]			; create empty keys array 
      $_aIniFile[1, $_I] = $_aData		; write to section 
      $_aIniFile[0, $_I] = ''			; write null section name 
    Else
      $_aData = $_aIniFile[1, $_I]		; Extract the key/value array 
      ; Create a Key index for the requested section 
      Dim $_aKeyIdx[UBound($_aData, 2)]
      For $_J = 0 to UBound($_aData, 2)
        $_aKeyIdx[$_J] = $_aData[0, $_J]	; create the index 
      Next
      $_J = aScan($_aKeyIdx, $_Key)		; find the key 
	
      ; If the key does not exist, add the key/data (new Key/data) 
      If $_J < 0
        If $_Data
          $_aData = $_aIniFile[1, $_I]		; array of key/data pairs 
          $_J = UBound($_aData, 2) + 1		; find next key index 
          ReDim Preserve $_aData[1, $_J]	; create data array 
          $_aData[0, $_J] = $_Key		; key 
          $_aData[1, $_J] = $_Data		; data 
          $_aIniFile[1, $_I] = $_aData		; section data 
        Else
	  $WriteIniArray = $_aIniFile		; return original array 
          Exit 0				; nothing to do (no data) 
        EndIf
	
      Else					; the key exists - either Update or Delete 
    
        ; if the data is not null, write the new data (update key) 
        If $_Data
          $_aData[1, $_J] = $_Data
	
        ; If the data is null, write empty key and data values (delete key) 
        Else
          $_aData[0, $_J] = ''			; delete key 
          $_aData[1, $_J] = ''			; clear data value 
        EndIf
        $_aIniFile[1, $_I] = $_aData		; update the array 
      EndIf
	
    EndIf
	
  EndIf
	
  $WriteIniArray = $_aIniFile
	
  Exit 0
	
EndFunction

Top
#212581 - 2017-07-11 06:45 PM Re: Best Procedure for using server names in script [Re: Allen]
Robdutoit Offline
Hey THIS is FUN
***

Registered: 2012-03-27
Posts: 363
Loc: London, England
Hi Allen,

Sorry to take so long to get back to you. I was off ill for a few days.

I will have a look and see if using ini files will do what I need. Many thanks

Top
#212582 - 2017-07-12 06:25 AM Re: Best Procedure for using server names in script [Re: Robdutoit]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4545
Loc: USA
It takes a little practice getting going with the INI files but they really do make it easy to make modifications to scripts.

If you need any assistance show us some code and we will get you in the right direction.

Top
#212596 - 2017-07-15 02:17 AM Re: Best Procedure for using server names in script [Re: Allen]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4396
Loc: New Jersey
When I teach my scripting class, one of the guidelines is to consider your data elements, plan how they are organized, then write the code to load, manipulate, and then possibly write/update the results.

I do this with every script no matter how simple. For Kix, I create the INI file to hold and manage my data before the script writing begins. Next, I write the script header and fill out blocks of comments to describe each processing component. Finally, I flesh out the logic, block by block, testing as I go. Takes a bit longer to complete development, but I'm using Kix scripts to perform monitoring, maintenance, and alert processing for thousands of endpoints.

FYI - the IniArray is slightly slower than direct reads, which is why I don't use it in my login script (where performance must parallel reliability), but most other applications that have more than a section or two do use it. LARGE (over 64K) INI files do read slowly, but there's no other way to use them. Allen's got some pretty large INI files he manages with this UDF.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#212600 - 2017-07-20 12:26 PM Re: Best Procedure for using server names in script [Re: Glenn Barnas]
Robdutoit Offline
Hey THIS is FUN
***

Registered: 2012-03-27
Posts: 363
Loc: London, England
Ya I think that I am going to need to review my script and see where I need to have the name of a server inputted as the ini file that Allen has provided above is a very very long script and I don't think that I need an array. All I need in the actual script is to say WSUS server is $Servername + "\xyz" kind of thing.

I just need to find a way to define $servername. I might have a look at how I did the printers as I created text files with the printer names for each client and all I did was run the udf at that point in the script. I can do the same thing for the servername in theory. In addition I can perhaps do @domain\path name instead of \\servername\pathname.

I will review this when I go on holiday next week.

Top
#212603 - 2017-07-21 01:40 PM Re: Best Procedure for using server names in script [Re: Robdutoit]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4396
Loc: New Jersey
Something like this:
 Code:
[Drive G]
PATH=\\server\folder
NAME=The cool kids share
DISK=G:
GROUPS=group1,group2
Repeat as needed.

Then, simple ReadProfileString() functions are all you need.
 Code:
; Get a list of drive mappings from the INI file
$aMappings = Splic(ReadProfileString('config.ini', '', ''), Chr(10))
For Each $Map in $aMappings
  $Path = ReadProfileString('config.ini', $Map, 'PATH')
  $DISK = ReadProfileString('config.ini', $Map, 'DISK')
  ; Get list of groups
  $Grps = ReadProfileString('config.ini', $Map, 'GROUPS')
  $OK = 1        ; OK to map this resource
  If $Grps       ; if Grps is defined, check for membership
    If Not InGroup($Grps)
      $OK = 0    ; not a member, so NOT OK
    EndIf
  EndIf
  If $OK         ; OK to map resource
    USE $Disk $Path
  EndIf
Next
This is somewhat oversimplified - could use error checking, logging, user messages, etc, but this is the basic premise of using external data. Using a more advanced drive mapping UDF will allow you to use the NAME parameter as the mapped drive description, which is why I added it. These UDFs provide much more control and enhanced features compared to the Use command.

There are UDFs available that will read the INI and return a list of sections, but that's basically what the first step does - the list of drive mappings can then be enumerated easily and each processed one at a time.

You should never worry about the size of a UDF - it does the job and you should never modify it - just add it to your code. I write simple scripts with just 10-15 lines of actual logic, then KGen identifies and includes all the UDFs that I used and the script becomes 1000+ lines - so what? I never look at the UDFs once they are written and placed into a script.

As for "@DOMAIN", that will reference your DC, not a file server. Putting shares on a DC is a significant security risk. DCs should be small systems that provide security and DNS services ONLY. We don't install any apps (like Acrobat, Zip/rar, net scan), services (no DHCP even!), or other non-security roles. IAS/RADIUS is one of the only features we might add to a DC. When we bring on a new client, we clean up the DC to meet security standards, as more and more companies are being audited by their customers to identify and mitigate risk of data breach. A dedicated file and app server and a few hours of consulting time is much less expensive than losing a client or dealing with a data breach.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
Page 1 of 1 1


Moderator:  Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 507 anonymous users online.
Newest Members
gespanntleuchten, DaveatAdvanced, Paulo_Alves, UsTaaa, xxJJxx
17864 Registered Users

Generated in 0.061 seconds in which 0.027 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org