XML Driven Logon Script

What is a XML Driven Logon Script you ask? It is a VBScript based logon script which behaviour (like mapping network drives, installing printers) is controlled from an xml file. This makes it easy for the none-programmer to build and manage logon scripts within his or hers organisation, since no knowledge of VBScript is needed.

Here is a rundown of the main features of the XML Driven Logon Script:

  • Separation of code and rules. The script file (Logon.vbs) contains all the functions and objects that performs the actions defined in an xml file (logonrules.xml). Unless a new feature is needed, a change to the behaviour of the logon script is done completely in the xml file.
  • Control behaviour of the logon script by defining filters and actions in xml file(s). Build action sets that are selected based on one or more filter, filter by Active Directory security groups, usernames, computer names and more. Actions include ability to map network drives, add network printers, copy files and more. See the documentation for more details on available filters and actions.
  • Logging direct to the executing computers Event Log. All information gathered by the script and all executed actions are logged to an entry in the Event Log on the computer running the script, making it easy to debug and find errors.
  • Friendly Internet Explorer window used to display messages to users. Among other things, the logon script will display a friendly message about each action performed during execution and tell the user how long until his or hers password expire.

The script itself was just recently reorganized to make it more versatile, so there might be a minor bug here and there, but the tests I have performed so far looks very good.

Go to the download section to get the latest version of the script, and take a look at the documentation section for a more in-depth examination of the features and configuration options in the script.

Please post any comments, suggestions, etc., in the comments on this page.

44 Responses to “XML Driven Logon Script”

  1. tony Says:

    hi, is it possible to contact you directly? If have some questions.
    would be great to talk to you.

    your script rocks :)

  2. Egil Hansen Says:

    Thanks Tony.

    I just send you a mail, looking forward to hearing from you.

  3. Kenneth Says:

    Hi
    Sorry for spamming you website today, but i’ve got every thin working now i only have one question :D
    is it possible to call a logon.htm page insted of the html inside the .vbs – i would like to ad a logo on the top, and maby put in som tables so i can create a proper layout or is it possible from within the vbs, im sorry but im not used to work with vbs or xml .. Thanks

    Kenneth

  4. Kenneth Says:

    Hi
    i also have a few questions, that i would like to ask, can i also contact you directly?

    Thanks Kennneth

  5. Egil Hansen Says:

    Hi Kenneth

    I’ve been away with exams, sorry for not getting back to you. I would have to make an extra method that would read the content of a .html file and have the IE object print it out, so in a way it is certainly possible to attach a header.html file or similar.

    I am a bit overworked the next days, but I will look into making it possible to attach a html file.

  6. Kenneth Says:

    HI
    actually no need, I’ve managed to get what I wanted using .WriteLN (“link to logo”)

    - I do however have another question – or 2 ..
    1. Using CopyFile, is I possible to just check if a file exist, and no whether or not it has been changed? – it’s for Navision, and it contains Server information, but users personal changes will also be written in this file, and theses settings have to be saved. But I would still like to check if the file is there.

    Also is it possible to use the variable %logonserver% like this (we have 4 servers in 4 different locations) I haven’t been able to get this to work

    But i must say it is really nice your script :)

  7. Egil Hansen Says:

    Hi Kenneth

    Thanks for the feedback. I like the idea of allowing a separate .html file to be inserted at the top of the Internet Explorer window. It should also make it much easier to style the content.

    In regards to the %logonserver% wildcard, yes, I have been planning to add it and a few others, since the script gathers the information anyway.
    However, if you need to point to the \\your-dc\netlogon share, you can simply use the DFS share that is automatically set up, e.g. \\your-fully-qualified-domain-name\netlogon

    Either way, I will add more wildcards as soon as I have a free half hour :)

    In regards to the CopyFile action. If the destination file does not exist, a new one is copied. But I suspect you know that and want a CopyFileIfExists action, which will only copy a file if it exists at the source. Is that what you are looking for?

  8. Kenneth Says:

    cool I’ll use the FQDN.

    about the copying, im rather looking for a CopyFileIfNotExists action.
    here’s challenge today (source and destinations “last modified” file-attribute is different.)
    The file i’m copying is being used to decide screen res. last logon etc. etc.
    so the atributes is changed, and a new file is being copied at next logon

    i hope im making sense?
    Feel free to email me – also in danish if you prefer :D
    Thanks
    Kenneth

  9. Casper Says:

    When ever an error comes up the following message comes up

    “There where one or more error’s during execution.”

    the ‘where’ is without h.

  10. Egil Hansen Says:

    doh, thanks Casper. Weird that nobody have caught that, including myself, before. Been using that sentence for about 2-3 years now :)

  11. Casper Says:

    Talking about “spellingerror” or just a spacebar that didn’t work…

    There’s missing a space in the following:” The difference between when the password was last setand today is 43 days”

    ’setand’ = ’set and’

    Is there a setting in version 4 that makes it possible for the logonscript to ignore the ‘error” – ‘Error: Unable to map x: to \\server\netlogon’.

    I get alot of errors when I’m mapping drives eventhough the map is still mapped. Even from PC’es that have been fully shutdown and have no open files on that serverdrive.

    As you can imagine that equals loads of calls to the IT department for no apparent reason ;)

  12. Egil Hansen Says:

    haha Casper. I see a pattern emerging :)

    I could definitely add a constant at the top of the script that would cause all errors to be suppressed, but I am more interested in figuring out why you are getting the errors. My best guess is that it is when the MapDrive function tries to unmap an existing connection. Have you tried running the script on a computer with no previously mapped drives?

    Update: I just uploaded version 4.00k, try that out and see if it works better Casper.

  13. Casper Says:

    So far it seems to work succesfully.

    Was wondering if there’s an option not to show the loginscreen at all?

    We’ve already set the time of which the logonscreen disapears down to 5 sec instead of 10.

  14. Egil Hansen Says:

    Good to hear Casper. Regarding running the script silent, call the script with the /silent switch, then it will not display a internet explorer window at all. It will still log all execution to the event log on the computer.

    Have a look in the Script settings & command line parameters for more command line parameters.

  15. Sidar Ok Says:

    Really good work, I’ll definitely have a deeper glance. Keep it up.

  16. Egil Hansen Says:

    Hi Sidar

    Thanks, please post any feedback you might have.

  17. Casper Says:

    I have the following code from KIX32 I’d like to convert to your script but I cannot find the description for this.

    Use S: “\\SERVER\SHARE” /user:SERVER\USERNAME /password:PASSWORD

    I know I have to use something like this:

    But cannot find a description about an option to put a username and password with mapDrive.

  18. Egil Hansen Says:

    Hi Casper

    There is no way to specify a user name and password. And you should never do that in a plain text file like the XML rules file, especially since that file is most likely placed in a rather public share like \\Domain\NETLOGON – which renders the point of having a user name and password irrelevant.

    The script assumes the user logging onto computer is part of a domain, which means you can also assign access rights through NTFS ACLs on the shared folder directly, and thus do not need to specify a user name and password. That is by far the recommend way of doing things.

    If the share is on a none Windows server, where you can not authenticate against the domain, and you need the data to be secure, I would look in to setting up a automated copy/move process of the data to a server that can be protected with NTFS security. That way only the copy/move process needs to know the security credentials to the original share.

    Hope this helps, Egil.

  19. marianok Says:

    Hi Egil,
    I was researching in order to write an XML+VBScript based logon script for may company when I run into yours. After a few minutes i decided to adopt yours as it’s already doing most of what I wanted it to.
    Now, I have made a few changes to it and it’s only fair that I offer them back to you.
    The changes I made are:
    1) added a variable for the sitename (so we can use it when specifiying servers) as we are geografically distributed company and we map stuff to the local servers.
    2) Re designed a litle the HTML to add our company logo and put the user information in a table instead of plai text.
    3) modified the group selection in order to pull the group information from multiple domains, and not just the current one.
    4) created a simple XLS to show the current values in a more understandable way.

    If you think that the changes and you think that someone else might like them, let me know (you should have my email in this post) and i’ll send them to you.

  20. Egil Hansen Says:

    Hi marianok

    That is very cool. I always like it when someone build upon then script. You should get a mail from me soon, would love to discuss the additions you have made.

  21. Leao Bras Says:

    Hi,
    I try to map a drive, but have this error:
    Line 463
    Char 9
    Error: This key is already associated with an element of this colletion

    Thanks,

  22. Leao Bras Says:

    I have vbscript error on try the map a drive: line 463, char 9, error: This key is already associated with an element of this collection.
    Thanks,

  23. Leao Bras Says:

    Need help, but Duplicate comment detected; it looks as though you’ve already said that!

  24. Leao Bras Says:

    Map drive : error line 463 char 9 This key is already associated with an element of this collection

  25. Leao Bras Says:

    Sorry about this spam, maybe cache problems :(

  26. Egil Hansen Says:

    Hi Leao:

    The line you are getting the error in, has nothing to do with the mapping of a drive.

    The line of code adds each active directory security group to a dictionary for lookup later, it looks like you have two security groups with the exact same name, something I have never come across before.

    Try testing with a new user, who is not a member of any security groups besides the default Domain Users.

  27. Leao Bras Says:

    Hi,
    It’s true, isn’t not a map drive. I have active the debug mode and make a various tests, and the error occurs when the script try get the distribution group (doesn’t detect distribution group) from a standby dc (not a master dc)… But I have make a restart on all dcs and now it’s work. (estrange)

    How I can use the distribution group to make a filterset? There are exist registry filterset or action?

    Thanks,

  28. Egil Hansen Says:

    You would have to add some code to the GetGroupMembership sub, that would get a list of distribution groups the user is a member of and possibly create a new filter. There is not any existing filter that you can apply I am afraid.

    Alternatively, you can upgrade your distribution groups to security groups. To do that, I am pretty sure you have to have a domain that’s running in 2003 native mode on the forest level.

    Hopo this helps, Egil.

  29. Ken Knicker Says:

    Hello Egil,

    Great work on this script! I had been considering splitting our logon script code from the functions and rules for a while.

    I noticed a couple of minor issues in the ‘ReplaceWildCards’ function and thought you would like to know about it:
    1. %Fonts% is being set twice
    2. %PrintHood% is not set at all

    Also, one other thing: In our environment we have a need to set IPC connections and also to map drives using alternate credentials. I have reworked your ‘MapDrive’ class a bit to accommodate these requirements. If you would like to see the updated code just let me know.

    Best regards,
    Ken

  30. Egil Hansen Says:

    Hi Ken

    Thanks for the feedback. I will drop you a mail later today, would love to see your code. I hope to get a chance to actually update the script with some of the feedback I have been getting from various people the last year.

  31. Oliver Says:

    Dear Egil

    I must admit, your logonscript is one of the best I have seen so far. Is it still under active development ?
    If so could you please add the following features ?

    - %userprofilepath% = Users Profile Path
    - %userhomedirpath% = Users Home-Directory Path
    - %userhomedrive% = Users Home-Directory Drive (e.g. H:)

    Actions:

    RemoveNetworkPrinter = Would remove a specific network printer
    RemoveAllNetworkPrinters = Would remove all network Printers

    Maybe an additional option for AddPrinter would be nice as well (removebeforeadd = true¦false)

    Would it be possible to extend teh TestFilter (for Computers) in a way you could test the OU name a computer object is stored in ? I need this for printer assignment. All PCs in the same OU (Room OU) get a specific Printer assigned.

    Kind regards,
    Oliver

  32. Egil Hansen Says:

    Dear Oliver

    Thank you for the input. I would be pushing the term “active development” if I said that it was. I have received some great input from a few others as well and would love to write an updated version of the script. With a bit of luck I might get to it during the summer, but no guarantees :)

    If you decide to extend the script yourself with some of the functionality you talk about, please send me a copy of what you figure out.

    Regards, Egil.

  33. Oliver Says:

    Dear Egil

    I have implemented most of the stuff I mentioned above

    %userhomedirectory%
    %userhomedrive%
    %userprofilepath%

    New Actions:

    Modified Filters:

    They now can check against the OU where an object (user, group) is stored in.

    “name” can now handle DNs as well. Example

    It auto-detects if it is a real name or a DN and compares accordingly.

    Added internal variables for

    Computer Objects OU
    Users OU

    I had to slightly change the DTD of the XML file.

    Can you send me your email so I can send you back the code ?
    Especially the DTD definition of the “ou” attribute is special. As I am not a XML DOM crack
    I would like to know what a real crack has to say about this implementation and if it could
    be solved easier or cleaner.

    Regards,
    Oliver

  34. Oliver Says:

    Upppsss…. There has been a lot more text but the blog cut it out because I used XML syntax….. :-(
    So send me your email address and I send you the text and code.

    Regards,
    Oliver

  35. Egil Hansen Says:

    Dear Oliver, you should receive a mail shortly, thanks for the work.

  36. Oliver Says:

    Dear Egil

    Your script incl. my modifications works fine so far…

    But I would be interested in the changes from:

    - Ken Knicker (March 9th 200) : http://www.egil.dk/xml-driven-logon-script/#comment-275
    - marianok (October 9th) : http://www.egil.dk/xml-driven-logon-script/#comment-218

    Can you send them to me ?

    Regards,
    Oliver

  37. Jacob Says:

    Hi All

    I am trying this out and it works great. I am trying to create dtd file for the xml file, but strugling a big load on this, is there an dtd file out there for this xml file?

    Thanks all

  38. Egil Hansen Says:

    Oliver:

    I am working on an updated version that will include the updates Ken, Marianok and you provided, hopefully I will be done with it over the weekend.

    If you can wait a little bit, I will have something for you then.

    Jacob:

    There is a DTD included in the XML file right now (at the very top), are you trying to put the DTD in a separate file?

  39. Jacob Says:

    Hi Egil

    Thanks for the reply, found it, stupid me…

  40. James Says:

    Hello Egil,

    Very nice script,

    Is there a way to see if a computer is part of a group not the user?

    TIA
    James

  41. Egil Hansen Says:

    Hi James

    Thanks!

    No, there is not a filter that will look at a computers security group.

    A work around is to assign the script to the computers using group policy, and then use filters when applying group policies.

  42. Ken Knicker Says:

    Hello Egil,

    Saw your comment re: working on an updated version via RSS feed for this thread and thought I would check in and ask how development is going and post a few updates re: our implementation of your script (based on the current version, 4.00k)

    I’ve recently added code to check the domain membership of the workstation. We needed this because we have multiple domains and ran into situations where a workstation is in one domain and the user is in another.

    Another is an update to the routine used to populate the dictionary object with user’s group membership information. It now checks to confirm the entry is not already in dictionary object prior to adding it. I’m pretty certain this is the same thing that Leao Bras described in this post: http://www.egil.dk/xml-driven-logon-script/comment-page-1/#comment-248.

    In our situation, we saw the error on users that are members of a domain which is being replaced. As part of that project, user objects and groups from the original domain were copied to the new domain. Because the new domain is visible to the script, during the AD interrogation step performed by “GetGroupMembership”, the script would report “This key is already associated with an element of this collection.”

    I believe we could have handled this by requiring user and group names to be fully qualified (i.e.: Instead of “myusername”, make it “mydomain\myusername” or “myusername@mydomain.com”). Another option was to include an “On Error Resume Next” just prior to the loop that populates the dictionary object but that’s really not my style :) .

    Other updates we’ve made include:
    - Forcing silent mode for all Citrix sessions
    - Obtaining home drive info to support users logging in via VPN
    - Addition of a “Warning” category for success/fail results. This allows special formatting of events posted to the IE status window but doesn’t prevent the IE window from closing.
    - Ability to handle situations where an attempt to map a drive that is already assigned to a local system drive letter (these are flagged as a “Warning” instead of “Error”). This was done primarily to accommodate logging on to servers via Remote Desktop.

    We’ve begun deploying to users across the enterprise as a replacement for the various logon scripts developed by separate IT groups at different locations — sort of a “one script to rule them all” idea. Things are going well overall.

    Something I’m interested in now is identifying any unused bits, redundancies, and general optimization. Would you be interested in having a look at our latest efforts?

    Thanks,
    Ken

  43. Egil Hansen Says:

    Hi Ken

    It sounds very cool what you are doing.

    I am still working on my new version, it is a total rewrite, based mainly on jscript. Basically I am trying my best to make the new version very modular, so you only include the parts you need. If you for example don’t need to map a network drive, you do not include the code to do that, nor the code to parse the map drive xml.

    The added bonus is that it makes it very easy to add new actions, without touching the core logic of the script.

    If you have the time, please post your version of the script on your blog, I will gladly link to it on this page, so people can get their hands on a more updates version than the one currently on this site.

  44. Casper Says:

    We’re now running a Multi-language version of Windows XP (with DK layout) which shouldn’t have any connection to the problem though the problem didn’t exist on our old DK installation.

    The problem only occurse when the logon script is run with the /silent parameter it seems and what’s worse. It’s only very few machines that gets an error.

    The error message is: “The procedure entry point GetProcessImageFileNameW could not be located in the dynamic link library PSAPI.DLL”

    I’ve tried to google it and the problem exists in a number of applications. I have reason to believe it’s our new IE7 installation that gave us the problem since its one the applications that gives this problem. I just don’t understand why this only happens when I use the “/silent” parametre with your logon script and even why its only on a handfull of PCs?

Leave a Reply