October, 2009

  • Michael Niehaus' Windows and Office deployment ramblings

    MDT 2010 Wizard Example: Role Selection

    • 8 Comments

    We have seen lots of requests over the past couple of years for a wizard pane that allows you to select from a list of roles that should be applied to a machine, where those roles are defined in the MDT database.  There are a few examples of this available on the web, implemented in different ways.  I’ll throw another one into the mix, this one using an ADO.NET Data Services web service to get the needed data.  (If you didn’t read my previous posting about this setup, click here.)

    <?xml version="1.0" encoding="utf-8"?>
    
    <Wizard>
    
      <Global>
    
        <CustomStatement><![CDATA[
    
    ' ***************************************************************************
    
    ' File:	Roles.xml
    
    ' Author:	Michael Niehaus
    
    ' Version:	1.0
    
    ' Purpose:	Display a list of roles from the MDT database, retrieved
    
    '	using an ADO.NET Data Services.web service.  One
    
    '	or more roles can be selected.  After they have been
    
    '	chosen, CustomSettings.ini needs to be re-processed
    
    '	to pick up the new settings.  Ideally this would be done
    
    '	after the wizard is complete (just in case someone 
    
    '	navigated back to the screen after initially making
    
    '	changes), but that requires changing LiteTouch.wsf.
    
    '
    
    ' NOTE:	Be sure to modify the web service URL below
    
    '
    
    ' ***************************************************************************
    
    Function InitializeRoleList
    
    	Dim sScript
    
    	Dim oDataService
    
    	Dim oRole
    
    	Dim sRoles
    
    	' Make sure that ZTIDataAccess.vbs is available since it isn't loaded by Wizard.hta
    
    	sScript = oFSO.OpenTextFile(oUtility.ScriptDir & "\ZTIDataAccess.vbs", 1, false).ReadAll
    
    	On Error Resume Next
    
    	ExecuteGlobal sScript
    
    	On Error Goto 0
    
    	' Call the web service
    
    	Set oDataService = New WebService
    
    	oDataService.WebService = "http://localhost:62932/MDTDatabase.svc/RoleIdentity"
    
    	oDataService.Method = "REST"
    
    	Set oResult = oDataService.Query
    
    	' Process the roles to populate the list of checkboxes
    
    	sRoles = ""
    
    	For each oRole in oResult.SelectNodes("//d:Role")
    
    		sRoles = sRoles & "<input type=checkbox name=Roles id=Roles enabled value='" & oRole.Text & "'>" & oRole.Text & "</input><br>"
    
    	Next
    
    	' If no roles were found, set the div to indicate that
    
    	If sRoles = "" then
    
    		sRoles = "<label class=errmsg style='display: inline;' >No roles could be found."
    
    	End if
    
    	' Update the pane
    
    	RoleList.InnerHTML = sRoles
    
    End Function
    
    Function ValidateRoleList
    
    	' Flush the value to variables.dat, before we continue.
    
    	SaveAllDataElements
    
    	SaveProperties
    
    	' Process full rules (needed to pick up the role settings, apps, etc.)
    
    	sCmd = "wscript.exe """ & oUtility.ScriptDir & "\ZTIGather.wsf"""
    
    	oItem = oShell.Run(sCmd, , true)
    
    	ValidateRoleList = True
    
    End Function
    
    ]]></CustomStatement>
    
      </Global>
    
      <Pane id="Roles">
    
        <Body><![CDATA[<H1>Select the roles to be assigned to this computer.</H1>
    
    <br>
    
    <div class=TreeList id=RoleList style="height: expression( GetDynamicListBoxSize(this) );">
    
    <label class=errmsg style="display: inline;" >Loading roles...
    
    <!-- List goes here -->
    
    </div>
    
    ]]></Body>
    
        <Validation><![CDATA[ValidateRoleList]]></Validation>
    
        <Initialization><![CDATA[setTimeout GetRef("InitializeRoleList"), 0]]></Initialization>
    
      </Pane>
    
    </Wizard>

    While this is set up as a stand-alone wizard, you can insert this into an existing deployment wizard using the MDT Wizard Editor by following these steps:

    1. Launch the MDT Wizard Editor.
    2. Open the DeployWiz_Definition_ENU.xml file.
    3. Click on the “Global” pane.  Click “Add” on the “Settings” pane and choose to add a new “CustomStatement”.
    4. Select the new “CustomStatement” at the end of the “Settings” list.
    5. Select the VBScript code above (from the first comment line to the last End Function line) and copy it to the clipboard.
    6. Paste the copied VBScript code into the text box in the MDT Wizard Editor.  Edit the web service URL to specify your ADO.NET Data Services web service URL.
    7. Select a wizard pane (the new pane will be inserted after this one, so select appropriately).
    8. Select all the text above from “<Pane” through “</Pane>” and copy it to the clipboard.
    9. Right-click on the selected pane name in the MDT Wizard Editor and choose “Paste”.

    What, your MDT Wizard Editor doesn’t have a “Paste” option?  Well, you need to download a new version from http://mdtwizardeditor.codeplex.com/, as I just added the paste capability tonight (along with other general usability improvements – I forced myself to actually use the program to create the rules wizard pane above and fixed all the behaviors I didn’t like while I was at it).

    A few notes to mention:

    • Because the wizard runs after CustomSettings.ini has been processed, the role settings, applications, etc. wouldn’t be processed as the “Gather” process isn’t run again.  To work around this, I added logic above to run ZTIGather.wsf again.  This could add a delay when clicking “Next”, so you might choose to do this later (possibly by modifying LiteTouch.wsf).  The other problem with running ZTIGather.wsf from this wizard pane:  If you navigate back to this wizard pane and uncheck an item, it’s too late – the settings for that role have already been added into the task sequence environment.
    • The MDT 2010 wizard hypertext application (Wizard.hta) doesn’t load the ZTIDataAccess.vbs script needed to make web service calls from a wizard pane.  To work around this, I added logic above to dynamically load the file.  The other alternative would be to edit Wizard.hta to tell it to include the file.
    • The role list is populated asynchronously so that the wizard doesn’t appear to be hung.  This is done by the “setTimeout” initialization statement above.  Note that the “Next” (or “Finish”) button will be enabled even while this is happening, so if you don’t want to wait you can probably go ahead and click the button to move on to the next pane.
    • If you don’t have the ADO.NET Data Services web service set up and working, don’t expect this wizard pane to somehow magically fix it :-)
  • Michael Niehaus' Windows and Office deployment ramblings

    Using the MDT database from a web service without writing code

    • 2 Comments

    One of the new features in the .NET Framework 3.5 SP1 is ADO.NET Data Services.  This enables you to expose the contents of a data source, e.g. a SQL Server database, through something that looks roughly like an RSS feed, accessed in a similar manner to a web service.  That’s nice but why do you care as an IT pro?  Well, it’s a convenient way of making the contents of the MDT database available to programs or scripts without forcing them to use ADO to access SQL Server directly.

    The best part of ADO.NET Data Services:  You really don’t need to write any code.  Just walk through a few Visual Studio 2008 wizards and you’re done – almost.  There are two lines of code that I added, one to day that all the selected tables and rows can be accessed read-only, and a second that generates detailed errors if something doesn’t work.  The basic process is described at http://msdn.microsoft.com/en-us/data/cc745957.aspx.  (So I lied – you have to write two lines of code.)

    The harder part of this is deploying the resulting ADO.NET Data Services project to an IIS server.  You need to have .NET 3.5 SP1 installed, then IIS and ASP.NET need to be installed.  You might need to run “ServiceModelReg.exe –i” to get the ADO.NET Data Services and WCF logic registered in IIS, see http://msdn.microsoft.com/en-us/library/ms732012.aspx for details.  You will definitely need to edit the database connection string in the Web.Config file to point to your server (and optionally the instance) as well as the database (Initial Catalog) that needs to be used.  And you might need to grant access to SQL Server, the database, and the database tables and views.  (See http://msdn.microsoft.com/en-us/library/ms998320.aspx if SQL Server is on the same machine.)  Really, it’s not that bad :-)

    The actual ADO.NET Data Services files need to all be dropped in a directory.  After doing this, set up an application in IIS that points to this directory.  At that point, if everything is set up right, you should be able to access the the web service via a browser.  To test it out, try a URL like this:

    http://yourserver/YourApplicationName/MDTDatabase.svc

    If that gives you a list of objects available in the database (you might need to tell IE not to display the result in RSS Reader view to see the real contents – in IE8, that’s configured on the “Content” tab from the “Feeds and Slices” settings dialog), you know at least IIS, .NET, and ADO.NET are fine.  Then try a more specific URL to request all the computer records:

    http://yourserver/YourApplicationName/MDTDatabase.svc/ComputerIdentity

    That should result in something that looks like this:

    image

     

    Yes, kind of weird looking, but pretty easy to consume in a script.  So that’s the next step – making use of this data.  More on that in the next posting.

    The full solution (Visual Studio project, source, binaries, etc.) is attached.

  • Michael Niehaus' Windows and Office deployment ramblings

    New version of the MDT Wizard Editor is available

    • 0 Comments

    For those of you who customize the MDT wizards, you may want to check out the new version of the MDT Wizard Editor at http://mdtwizardeditor.codeplex.com.  The latest version 2.0, uploaded today, includes a few fixes (e.g. properly encoding XML file entries in CDATA sections), adds support for MDT 2010, and includes a few new features.

    The first change you will notice is that there is now a menu bar:

    image

     

    Use the “File” menu to open menu definition files (XML files), save your changes, and to exit the program.  Use the “Wizard” menu to test a wizard definition file after you have made changes.

    The testing process is the most significant change in this new version.  It will gather information from the machine (running ZTIGather, as long as it can find it) and then display all of the variable values before starting the wizard:

    image

    You can modify variables, remove variables, add variables – whatever you would like to do.  When you are ready to run the wizard, click the “Run” button.  Once you have completed the wizard, the dialog will be updated to show you the variables that were set after the wizard completed:

    image

    In this case, you can see the additional variables that were defined for keyboards, applications, BitLocker, etc.

    If you find any issues with this release, or if you have any suggestions on how to improve the release (subject to my available time), please use the CodePlex “Issue Tracker” to submit new items.

  • Michael Niehaus' Windows and Office deployment ramblings

    MDT 2010 New Feature #21: Copying extra folders

    • 0 Comments

    When MDT 2010 replicates content to a linked deployment share, you can choose whether to copy “standard folders” as part of that replication process.  These folders (Scripts, Tools, $OEM$, USMT) might be required by one or more of the task sequences being replicated, so we give you that option.  In the case of media, we always copy these four standard folders; you don’t get a choice as we assume everything in those folders is required by the current deployment share and therefore is also required by the media.

    We have periodically received requests to allow for the replication of additional folders to linked deployment shares, as well as the inclusion of additional folders when creating media.  As a result of those requests, we added a mechanism for specifying a list of extra folders.  But there’s one challenge for that:  We didn’t provide a user interface for configuring those, so you have to use PowerShell to do it.  Unfortunately the documentation doesn’t even mention that this is possible, so consider this blog entry a documentation addendum :-)

    From a PowerShell session, you would first need to load the MDT PowerShell snap-in (“Add-PSSnapIn Microsoft.BDD.PSSnapIn”) and then connect to the deployment share (simplest way is “Restore-MDTPersistentDrive” to get all the drives connected that you use in the Deployment Workbench).  In the case of linked deployment shares, you can get all the current properties like so:

    image

    Then setting the ExtraFolders property (which is empty by default) is achieved using “Set-ItemProperty”:

    image

    Because the ExtraFolders property is a list (array), you always need to specify the values as I did, using the PowerShell syntax of @(“Value1”, “Value2”).  If you only have a single value, it would look like @(“Value1”).

    Media works the same way:

    image

    The folders you specify need to exist at the top level of the deployment share.  In my examples above, my deployment share is “C:\DeploymentShare” so the folders that must exist are “C:\DeploymentShare\MyFolder1” and “C:\DeploymentShare\MyFolder2”.  Make sure you specify folders that actually exist – otherwise you’ll get errors when MDT tries to copy those folders.

    After doing this, you’ll notice an additional line in the output, highlighted below, telling you how many extra folders were copied:

    image

Page 1 of 1 (4 items)