|
|
|||||||
We have a number of items in our script that re-run every morning, as the script grows we're starting to experience extended time for it to complete. These items are there because someone might login to another PC so the entries need applying. Here's an example of an Office setting, we have about 15 of these Code: ; ### Outlook Office 2007 registry entry to set default fonts ### IF ReadValue("HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\MailSettings","OutlookDefaultFonts") <> "Arial" $rc = WriteValue("HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\MailSettings","OutlookDefaultFonts", "Arial", "REG_SZ") $rc = WriteValue("HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\MailSettings","OutlookDefaultFontsDate", "@DATE", "REG_SZ") $rc = WriteValue("HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\MailSettings","OutlookDefaultFontsTime", "@TIME", "REG_SZ") RUN "regedit.exe /s \\<servername>\Office2007ProPlus\scripts\OutlookDefaultFonts.reg" ELSE ?"Value is already there (Outlook Default Font). No need to change." ENDIF Appreciate I could remove the entry for planting the insertion date/time! The script can sit waiting to complete for long periods of time on occasions, moreso when people are logging into a Terminal Server or when many people are logging in for the first time in the morning (all at the same time). Does anyone have some ideas how we could speed the process up. Thanks Mark |
||||||||
|
|
|||||||
Why are you running regedit after you just used kixtart to write to the registry? What is it doing? |
||||||||
|
|
|||||||
Are you adding printers in your script? |
||||||||
|
|
|||||||
if your script is getting larger, you would do good if you considered adding some logging in to it, just a simple: Code: run "%comspec% /c echo doing office registry mod %time% >> %temp%\logon.log" would suffice. add those lines after the parts and examine the log to see where it is taking the long time to execute. do remember to start your script with something like "echo logon start >" (instead of >>) so the log won't keep on accumulating in size. |
||||||||
|
|
|||||||
Originally Posted By: BradV Why are you running regedit after you just used kixtart to write to the registry? What is it doing? Good question, I'm sure I could plant these with WriteValue. Would this speed things up? Originally Posted By: Allen Are you adding printers in your script? Yes Originally Posted By: Lonkero if your script is getting larger, you would do good if you considered adding some logging in to it, just a simple: Code: run "%comspec% /c echo doing office registry mod %time% >> %temp%\logon.log" would suffice. add those lines after the parts and examine the log to see where it is taking the long time to execute. do remember to start your script with something like "echo logon start >" (instead of >>) so the log won't keep on accumulating in size. One of the main pauses is where it's running a vBscript for our Outlook Signature (something I guess we're going to have to live with). |
||||||||
|
|
|||||||
Why I asked is that every time you fork out of kixtart, you are slowing things down. So, when you call regedit, when you call visual basic, it slows things down. Kixtart was made to edit the registry. So, you should be able to do whatever is being done by OutlookDefaultFonts.reg natively in kixtart. Likewise, you should be able to do Outlook signatures natively in kixtart. Many references to that on the site. |
||||||||
|
|
|||||||
Brad - Notice that he's using RUN and not SHELL, so - while there's some brief delay to launch, these processes run asynchronously to the login script. Improves performance, but you can't tell if they are successful. The LoadHive() function is often overlooked and can load many reg values with a single command, similar to running "RegEdit /s file.reg" and could be used to eliminate the RUN commands entirely with little or no change to the REG file. Sparkie - Calls to VB and other external processes all affect performance. It's crucial to bring as many processes internal as possible, and to not duplicate effort during each login. Group common processes together and only run all of them if one particular test fails whenever possible. For example - Test for "User Customization" - if the reg key is not present, do all user customization tasks, rather than individually testing for Outlook, Office, accounting, Acrobat, Flash, and whatever else might be in a per-user customization. Use a date rather than a boolean, and set a flag externally that defines the last time the user customization was changed. If the user's reg value is older than the external date, run all the updates. I've spent a lot of time optimizing our login script, and it's been in service at many companies in one form or another since 1996. Our login script runs so fast I was asked to add a delay option. Timing our script with 5 drive and 3 printer mappings results in 0.88 seconds of process time(seven-eighths of a second). This includes the time to process various authorization tests to determine which of several resources should be mapped. Adding the Outlook signature refresh using the code from the vault adds another half-second. Two key elements of our script are that all data is external to the script in an INI file, and all authorization is performed before any actions are actually processed. One way to optimize your code is to display (or log) the elapsed time, in milliseconds, at various points in your script. Here's an example: Code: $STime = @TICKS ; place this at the top of the script ; ; script commands... 'Task - Elapsed: ' 1.0 * (@TICKS - $STime) / 1000.0 ' seconds' @CRLF ; ; more script commands, then repeat above to show cumulative time Glenn |
||||||||
|
|
|||||||
To follow up on the printers... if you only have lines like the following... Code: $RC=addprinterconnection("server\printer") the script is unfortunately reinstalling the printer drivers each time. Checking to see if the printers are already installed can greatly decrease the time the logon script runs. The solution is to use a UDF like Primapstate() or PrinterConnection(). PrinterConnection is newer and allows you to manage your printers by Share Name instead of by the actual name. So using the example above... Code: if not printerconnection("\\server\printer") $RC=addprinterconnection("\\server\printer") endif or Code: if not printerconnection("\\server\printer") $RC=printerconnection("\\server\printer","add") endif Additional Examples are included in the header of the links below. Primapstate() - http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=83306#Post83306 PrinterConnection - http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=203840#Post203840 How to use UDFs - http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=81943#Post81943 The rest of the UDFs are here - http://www.kixtart.org/forums/ubbthreads.php?ubb=postlist&Board=7&page=1 |
||||||||
|
|
|||||||
an other point with inifile if you use some one for reading configuration ... for one read in an inifile, the windows api loads all the file. if the file is on a local disk, the first read loads the file in the system cache. for next reads, the file is probably still in memory so no need to access to disk. if the file is on a network share, there is no system cache. for each read you need to do, the all file is read through the network !!! Suppose you have a file of 1024 bytes and you need to read 5 keys in a section : locally, the script reads 1024 bytes from disk one time and other reads get data from memory. through the network, the script reads 5 * 1024 bytes. This is always slower, especially if computers are on a WAN. try the simple code below Code: $nb=100 Test( @scriptdir+"\"+@scriptname+".ini", $nb ) Test( "\\servername\sharename"+@scriptname+".ini", $nb ) function test( $inifile, $nb ) $handle = freefilehandle() if open( $handle, $inifile, 1+4 )=0 $=WriteLine( $handle,"[OPTIONS]"+@crlf ) for $i=0 to $nb $=WriteLine( $handle,""+$i+"=toto "+$i+@crlf ) next $=close($handle) endif $start = @ticks $arrKeys = ReadProfileString( $inifile, "OPTIONS", "" ) $arrkeys = split( $arrkeys, chr(10) ) for each $key in $arrKeys if $key $value = ReadProfileString( $inifile, "OPTIONS", $key ) endif next $start = @ticks - $start "executed in " $start " ms" ? del $inifile endfunction This code generates a file of 1205 bytes and the difference is significant you can try differents ini file size by changing $nb. Globally, it is a good thing to copy locally a remote inifile, then use local file. In my login script, i use robocopy or replace /u to get file locally (with these tools, copies are done only if files change). If you don't want to keep files locally, delete them after use. |
||||||||
|
|
|||||||
Thanks guys, some food for thought and good ideas. I'm going over the Kix part first (before the vBscript runs) and change to use lookups such as registry return codes and the printer name pre-check. For the timebeing, we're sticking with our Outlook vBscript because it works for us but maybe I could add some code for Kix to perform a lookup on the existing signature, whether it exists or if any changes.... ....anyone got any ideas on that (I did try some code in the vB script but that sort of defeats the object). |
||||||||
|
|
|||||||
If you dont mind posting your vbscript, I could try to take a look at it and see how hard it would be to convert to kix, or if there is something to check for before running it like you said. |
||||||||
|
|
|||||||
Thanks, we have three vBscript files. I have merged them into one file to see if there was a difference in time running and there wasn't. The first (which is below) is our main default 'new message', we also have a reply one that omits the image and an International one with a different address and telephone number. These sigantures get planted for domain users logging in using PC's and Terminal Server sessions. I've also included after, some other code I was playing around with that checks for the signature folder and whether any changes have been made, though I don't think it works because if I delete the rtf file it's re-creating it. Code: ' ######## New Signature ######## On Error Resume Next Set objSysInfo = CreateObject("ADSystemInfo") Set WshShell = CreateObject("WScript.Shell") strUser = objSysInfo.UserName Set objSysInfo = CreateObject("ADSystemInfo") Set objUser = GetObject("LDAP://" & strUser) Set objGroup1 = GetObject("LDAP://cn=All RCDAs,ou=User Accounts,dc=our domain,dc=local") Set objGroup2 = GetObject("LDAP://cn=All National Office,ou=User Accounts,dc=<our domain>,dc=local") 'map Active Directory objUser to str names' strName = objUser.FullName strNotes = objuser.Info strTitle = objUser.Title strPhone = objUser.TelephoneNumber strMobile = objUser.Mobile strEmail = objUser.mail 'set pointers for image insertion with linked URL' sPicFile = "\\ARTIC\Office2007ProPlus\Scripts\edin4.png" sLinkFile = "http://www.our domain.org/blah.html" 'Use Word (required) to create the format' Set objWord = CreateObject("Word.Application") Set objDoc = objWord.Documents.Add() Set objSelection = objWord.Selection objSelection.Style = "No Spacing" Set objEmailOptions = objWord.EmailOptions Set objSignatureObject = objEmailOptions.EmailSignature Set objSignatureEntries = objSignatureObject.EmailSignatureEntries 'If you get problems with line spacing, use vbNewline instead of Chr(11)' 'Select what is displayed in the Signature based upon the str to ObjUser mappings above' objSelection.Font.Bold = True 'objSelection.Font.Name = "Arial" objSelection.Font.Size = 11 'if (strCred) Then objSelection.TypeText strName & ", " & strCred Else objSelection.TypeText strName & Chr(32) & strNotes & Chr(11) 'if (strName) Then objSelection.TypeText strName & ", " & strNotes & Chr(11) if (strName) Then objSelection.TypeText strName & strNotes & Chr(11) objSelection.Font.Bold = False objSelection.TypeText strTitle & Chr(11) objSelection.TypeText "Our company name" & Chr(11) ' If member of AD group All National Office (as defined above) then plant National Office address if (objGroup2.IsMember(objUser.AdsPath) = True) Then objSelection.TypeText "PO Box address here" & Chr(11) else 'display nothing end if ' If Telephone number is populated in AD then set and plant Internationally defined number (lines 1 and 2 are only required for the International Signature) 'strPhone = right(strPhone,len(strPhone)-1) 'strips off left most digit 'strPhone = "+44 " & strPhone if (objUser.TelephoneNumber) Then objSelection.TypeText "DD: " & strPhone & Chr(11) ' if member of AD group RCDS's (as defined above) do nothing, otherwise plant Mobile number 'if (objGroup1.IsMember(objUser.AdsPath) = True) Then ' CHR(11) 'else ' if (strMobile) Then objSelection.TypeText "Mobile: " & strMobile & Chr(11) 'end if if (strMobile) Then objSelection.TypeText "Mobile: " & strMobile & Chr(11) objSelection.Hyperlinks.Add objSelection.Range, "http://www.our domain",, "Our company Homepage", "www.our domain" With objDoc.Styles("Hyperlink").Font .Name = "Arial" .Bold = False '.Underline = wdUnderlineNone .Color = RGB(227,114,34) End With objSelection.TypeParagraph() objSelection.TypeParagraph() Set objShape1 = objSelection.InlineShapes.AddPicture(sPicFile, True) objDoc.Hyperlinks.Add objShape1.Range, sLinkFile 'add the entire range of what you want displayed and set the global font' Set objSelection = objDoc.Range() objSelection.Font.Name = "Arial" 'Add a siganture entry, name it and assign to new message' objSignatureEntries.Add "Full Signature", objSelection objSignatureObject.NewMessageSignature = "Full Signature" 'Save the content and exit' objDoc.Saved = True objWord.Quit ---------------------------------------- Other code I've been working on. Set FileSysObj = CreateObject("Scripting.FileSystemObject") Set UserObj = GetObject("LDAP://" & objADSysInfo.UserName) ' work in progress check signature existence and exit if exist or not changed strAppData = WshShell.ExpandEnvironmentStrings("%APPDATA%") SigFolder = StrAppData & "\Microsoft\Signatures\" strQuteChr = chr(34) SigFile = SigFolder & UserObj.sAMAccountName & ".htm" 'check existence of signature folder, if not exist create it if not FileSysObj.FolderExists(SigFolder) then FileSysObj.CreateFolder(SigFolder) end if if FileSysObj.FileExists(SigFile) then 'get amended date of file, then compare it to the changed date of the user Set objFile = FileSysObj.GetFile(SigFile) datSigAlt = objFile.DateLastModified intTimeDiff = DateDiff("n", datSigAlt, UserObj.whenChanged) 'if the difference is less than 0 then we do not need to do anything as the sig file is uptodate if intTimeDiff < 0 then wscript.Quit end if 'end work in progress |
||||||||
|
|
|||||||
Creating an Outlook signature with just kix is not that hard. have a look at this thread for a kix version of what you are using. Sure some changes should be made but it is all possible in kix. |
||||||||
|
|
|||||||
Well, I've started the conversion process of my vBscript to Kix. It's steady progress but at least in the longrun it will detract from the 'bandit' vB comments. |
||||||||
|
|
|||||||
Ok, this one is posing problems, I'm using Code... $objLink = $objSelection.Hyperlinks.Add($objSelection.Range.... but cannot change the font colour, I've tried various methods but it isn't having it. |
||||||||
|
|
|||||||
Settings the colour on a hyperlink is a little different than setting the font on regular text. Below is an example of how I did this for our setup. $strmail contains the e-mail address that is taken from AD. The example below is a snippet from a much larger script. We use multiple colours and multiple font sizes. They get set at the top of the script together with the font to be used. This makes it a lot easier to make changes if needed. Code: $fontname = "Arial" $fontmedium = "8" ;Font colour codes can be found by recording a macro in Word while setting the colour for some text. $fontgray = "5855577" ;Gray RGB: 89.89.89 ;Insert and select hyperlink and set font and attributes for the selection. ;Calculate where the hyperlink begins. ;Start selection at total length of all text minus the length of the url and select everything to the end of the text. $objLink = $objSelection.Hyperlinks.Add($objSelection.Range, "mailto:" + $strmail,, "E-mail", $strmail) $Selectionemail = $objDoc.Range($objSelection.End - (Len($strmail) + 1), $objSelection.End) ;Set font, size and underline for selection. $Selectionemail.Font.Name = $fontname $Selectionemail.Font.Size = $fontmedium $Selectionemail.Font.Underline = 0 $Selectionemail.Font.Color = $fontgray |
||||||||
|
|
|||||||
Thanks Mart, I sorted it this morning, though I used your little trick of converting the RGB color to Kix (Word interpretation) using the Macro Recording. I used this code in the end. Code: $objLink = $objSelection.Hyperlinks.Add($objSelection.Range,"http://www.domain.org",, "company name", "www.domain.org") $objLink.Range.Font.Color = "2257635" Getting there but still got a couple of issues which I'm trying to persist with before asking. |
||||||||
|
|
|||||||
Ok, trying to covert this vB to Kix. Code: Set objGroup2 = GetObject("LDAP://cn=a_group,ou=User Accounts,dc=<domain>,dc=local") if (objGroup2.IsMember(objUser.AdsPath) = True) Then objSelection.TypeText "text here" & Chr(11) else 'display nothing end if I've tried this Code: IF INGROUP("???") objSelection.TypeText..... and numerous other permitations but no go. |
||||||||
|
|
|||||||
You may need to list what you tried or what kind of account you are using.... it should be as simple as putting in the Group Name, however if you are looking for a computer in a group, that requires another UDF. for a user... Code: if ingroup("Domain Users") ;do stuff endif |
||||||||
|
|
|||||||
Can't remember what I tried, too many things to try and recall. Here's an example of what should work, but doesn't Code: IF ingroup("usergroup") $objSelection.TypeText("TEXT") ELSE ? ENDIF |
||||||||
|
|
|||||||
Works fine like that for me. Clearing the groupcache might help. To do this run kixtart /f or delete HKEY_CURRENT_USER\Software\KiXtart\TokenCache. |
||||||||
|
|
|||||||
I wish it did for us. Everything else is fine so far. Deleted the Key and it made no difference at all If I use @USERID it's fine, just seems to be ignoring group |
||||||||
|
|
|||||||
What OS are you running on the servers and clients? What kind of group is it? |
||||||||
|
|
|||||||
Server 2003 for the DC's, 2008 for the TS's and Windows XP/7 Clients The group is a Scope = Global, Type = Security |
||||||||
|
|
|||||||
If I recall correctly there has been an issue with some groups not being recognized and there was a fix for it (unsupported by MS) but I cannot recall exactly what it was. Maybe someone else remembers more clearly than I do. If you put a simple: Code: if ingroup("somegroup") ?"In group" else ?"Not in group" endif in a test script and run it does it also fail? |
||||||||
|
|
|||||||
Ahh, that's what I tried, comes back as not in group. Funny thing is our current login script is full of ingroup commands This is a bit worrying, Kix32.exe is 4.12.0.0 |
||||||||
|
|
|||||||
Can you do a test with 4.62? |
||||||||
|
|
|||||||
Still the same with 4.62 |
||||||||
|
|
|||||||
So you're saying if you run your current login script, the InGroup()works, but if you run the same group check in your new script it doesn't? |
||||||||
|
|
|||||||
Ok, I seem to have found the problem. I was running the kix file using the batch file from the command line, when I logoff/logon it seems to work fine. |
||||||||
|
|
|||||||
Sorry but LOL Group membership is assigned at logon. Changes made after logon are not available until you log off and logon again. A nice "feature" of Windows. |
||||||||
|
|
|||||||
Yeah, tell me about it. LOL The funny thing is, I'm saying to myself during the issue 'right, groups are assigned during login, it's part of that group so why aint it working' That's what comes of doing too many things at the same time. |
||||||||
|
|
|||||||
Next thing to do is replace the number it tries to plant from AD |