<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://myitforum.com/cs2/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Maik Koster at myITforum.com</title><link>http://myitforum.com/cs2/blogs/maikkoster/default.aspx</link><description>giving something back after taking a lot :-)</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 SP2 (Build: 31113.47)</generator><item><title>MDT Wizard Studio beta released</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2013/01/13/mdt-wizard-studio-beta-released.aspx</link><pubDate>Sun, 13 Jan 2013 16:34:00 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161700</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161700</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2013/01/13/mdt-wizard-studio-beta-released.aspx#comments</comments><description>&lt;p&gt;The MDT Wizard Editor is probably one of the most useful tool if it comes to editing the Lite Touch Wizard files. It especially simplifies the pretty tedious part of editing the xml files and the embedded HTML content of each wizard pane.&lt;/p&gt;  &lt;p&gt;However the current version of it dates back to October 2009 and with this didn’t support any of the changes, that came with MDT 2012 and MDT 2012 Update 1. One of the major changes between 2010 and 2012 has been, that in contrast to MDT 2010, all wizard panes are now stored in individual files and only referenced in the wizard definition file. While it eases the handling and testing of individual wizard panes, it also made it necessary to always tweak the wizard definition file by hand.&lt;/p&gt;  &lt;p&gt;To ease this job, I’ve started updating the freely available source of the MDT Wizard Editor to work with MDT 2012/MDT 2012 Update1. And also added some features, that I was always missing while using the original MDT Wizard Editor. &lt;/p&gt;  &lt;p&gt;Due to some administrative reasons, we have decided to publish this as a separate, community driven project. &lt;/p&gt;  &lt;p&gt;So I’m proud to announce the first public release of the new &lt;a target="_blank" title="MDT Wizard Studio" href="https://mdtwizardstudio.codeplex.com/"&gt;&lt;b&gt;MDT Wizard Studio&lt;/b&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h3&gt;Features and Enhancements&lt;/h3&gt;  &lt;p&gt;The following features and enhancements are available in the current beta release:&lt;/p&gt;  &lt;p&gt;- Full support for MDT 2012 / MDT 2012 Update 1&lt;/p&gt;  &lt;p&gt;- Open MDT Wizard definition files&lt;/p&gt;  &lt;p&gt;- Create a new MDT Wizard definition file&lt;/p&gt;  &lt;p&gt;- Add a new pane to an existing definition file (still supports Copy&amp;amp;Paste)&lt;/p&gt;  &lt;p&gt;- Import an existing pane &lt;/p&gt;  &lt;p&gt;- Reorder panes by Drag&amp;amp;Drop&lt;/p&gt;  &lt;p&gt;- Rename pane and referenced file&lt;/p&gt;  &lt;p&gt;- Change title of pane&lt;/p&gt;  &lt;p&gt;- Convert old (MDT 2010 and older) wizard definition file into new MDT 2012 format&lt;/p&gt;  &lt;p&gt;- simple Syntax highlighting of VBScript and HTML code elements&lt;/p&gt;  &lt;p&gt;- Edit referenced scripts directly in the wizard&lt;/p&gt;  &lt;p&gt;- Option to hide the navigation bar&lt;/p&gt;  &lt;p&gt;- Resize the Wizard&lt;/p&gt;  &lt;p&gt;- Highlight updated variables during test of wizard &lt;/p&gt;  &lt;p&gt;- copies all referenced files (scripts, images, etc.) on import and testing&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;some screenshots:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML150f398_7C625751.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML150f398" alt="SNAGHTML150f398" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML150f398_thumb_6EEC1E7E.png" border="0" height="426" width="593" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML1530eb6_7ECB3D75.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML1530eb6" alt="SNAGHTML1530eb6" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML1530eb6_thumb_383E27A0.png" border="0" height="349" width="591" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML1536a6c_450857F1.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML1536a6c" alt="SNAGHTML1536a6c" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML1536a6c_thumb_71ED94FF.png" border="0" height="350" width="592" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_2470F272.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_3C2829D8.png" border="0" height="395" width="209" /&gt;&lt;/a&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_08138A85.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_06CEF1A6.png" border="0" height="375" width="305" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;As mentioned, it’s currently a Beta version, so be careful when editing your production wizard definitions. So far it has been tested on all MDT 2012 Update 1 Wizard definitions.&lt;/p&gt;  &lt;p&gt;The MDT Wizard Studio has been published as a ClickOnce release, so the “installation” literally takes you one click. Get the most recent version at. &lt;a title="https://mdtwizardstudio.codeplex.com/releases" href="https://mdtwizardstudio.codeplex.com/releases"&gt;https://mdtwizardstudio.codeplex.com/releases&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;As always, the MDT Wizard Studio is provided “AS IS” without any express or implied warranty of any kind. Be sure to properly test it before using it within your environments. Especially as it’s still a Beta version.&lt;/p&gt;  &lt;p&gt;However feel free to give it a try and I would really appreciate your feedback.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161700" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category></item><item><title>2012 Microsoft® MVP Award – Setup &amp; Deployment</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/10/01/2012-microsoft-174-mvp-award-setup-amp-deployment.aspx</link><pubDate>Mon, 01 Oct 2012 16:23:44 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161512</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161512</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/10/01/2012-microsoft-174-mvp-award-setup-amp-deployment.aspx#comments</comments><description>&lt;p&gt;Just received the following email:&lt;/p&gt;  &lt;p&gt;   &lt;hr /&gt;&lt;/p&gt;  &lt;p&gt;Dear Maik Koster,&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Congratulations! We are pleased to present you with the 2012 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Setup &amp;amp; Deployment technical communities during the past year.&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Thanks to Microsoft for re-awarding me. I really appreciate being part of this community that gives so much.&lt;/p&gt;  &lt;p&gt;Or to say this with Johan Arwidmark: “&lt;a href="http://www.deploymentresearch.com/" target="_blank"&gt;Contributing is Everything&lt;/a&gt;!”&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161512" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MVP/default.aspx">MVP</category></item><item><title>Compare Active Directory computer accounts with Configuration Manager resources</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/09/28/compare-active-directory-computer-accounts-with-configuration-manager-resources.aspx</link><pubDate>Fri, 28 Sep 2012 13:21:17 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161508</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161508</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/09/28/compare-active-directory-computer-accounts-with-configuration-manager-resources.aspx#comments</comments><description>&lt;p&gt;Despite all discovery methods, Health scripts and other cleanup efforts it might be helpful from time to time to simply compare all the computer account objects that we have in Active Directory with our resources in ConfigMgr. &lt;/p&gt;  &lt;p&gt;There are a couple posts available, that demonstrate how to integrate information from Active Directory into SQL reports. See e.g. “&lt;a href="http://smsug.ca/blogs/garth_jones/archive/2008/12/03/how-to-add-ad-data-to-configmgr-reporting.aspx" target="_blank"&gt;How to add AD data to ConfigMgr reporting&lt;/a&gt;” from Garth Jones. As you can see, in his post, Garth shows already how to compare AD accounts with ConfigMgr, so why this post?&lt;/p&gt;  &lt;p&gt;Well, they mainly use the &lt;strong&gt;ADSI provider&lt;/strong&gt; as a linked server and the &lt;strong&gt;OPENQUERY&lt;/strong&gt; SQL command to query AD. However most of them suffer from a limitation, that comes from Active Directory itself and will actually hurt most people in a even slightly larger environments. The ADSI provider will only return 1000 rows per query.&amp;#160; And there is not way to tell the “OPENQUERY” command to return more rows. &lt;/p&gt;  &lt;p&gt;There are a couple ways around this problem:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Increase the limit in Active Directory &lt;/h3&gt;  &lt;p&gt;Naaaaah. If you don’t know exactly what your are doing, don’t do this, as it has effect on all queries against AD! Also this is not a long term fix, as the company might grow, which would require to increase the limit again.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Call OPENQUERY in batches&lt;/h3&gt;  &lt;p&gt;Works, but is pretty complicated.&lt;/p&gt;  &lt;p&gt;You would need to create a T-SQL script that selects only a subset of accounts, e.g. based on the first character of the name. Every time it reaches the limit of 1000 objects in this subset it would need to divide it again, by e.g taking also the next character of the name into consideration and so on. &lt;/p&gt;  &lt;p&gt;If you would like to give this a try, you will find some samples on the internet. I don’t supply a link, as none of them has really fulfilled my needs so far.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Adding a CLR procedure to query AD&lt;/h3&gt;  &lt;p&gt;See &lt;a href="http://blogs.msdn.com/b/ikovalenko/archive/2007/03/22/how-to-avoid-1000-rows-limitation-when-querying-active-directory-ad-from-sql-2005-with-using-custom-code.aspx" target="_blank"&gt;this post from Igor Kovalenko&lt;/a&gt; for more information. He basically uses a pre-compiled dll that you have to register in your SQL Server. Again, this will work, but I’m not a big fan of registering some custom dll’s in my sql server. Especially if it is for such a crucial system like ConfigMgr.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Using LogParser to fill a temporary table&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=24659" target="_blank"&gt;LogParser&lt;/a&gt;?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;YES!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you don’t know LogParser, you might want to have a look on some &lt;a href="http://mlichtenberg.wordpress.com/2011/02/03/log-parser-rocks-more-than-50-examples/" target="_blank"&gt;IIS query examples&lt;/a&gt; that give you a pretty good idea on its capabilities. It’s been initially created to parse IIS log files and haven’t been updated since quite some time (the current download still dates back to 2005), but it’s still some of the most powerful and underestimated tools around. &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=24659" target="_blank"&gt;Download it here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;LogParser uses a SQL like syntax to query from IIS logs (of course), text/XML files, Event logs, the File System, Registry and Active Directory (that’s what we need here). It can even parse network captures from Netmon or Windows trace logs. It writes the output to text/xml files, but can also write directly into SQL tables (what we will use in this post). &lt;/p&gt;  &lt;p&gt;Most importantly, it’s command line based, so pretty easy to automate. However, there is a GUI called &lt;a href="http://www.lizard-labs.net/log_parser_lizard.aspx" target="_blank"&gt;Log Parser Lizzard GUI&lt;/a&gt; available for free, in case you struggle with the syntax.&lt;/p&gt;  &lt;p&gt;After we installed logparser, we can use something like the following to have it crawl through our AD and return a list of computer with some common attributes we might need (line breaks just added for readability):&lt;/p&gt;  &lt;pre class="csharpcode"&gt;logparser.exe &lt;span class="str"&gt;&amp;quot;SELECT cn, 
                      objectpath, 
                      operatingSystem, 
                      operatingSystemServicePack, 
                      LastLogonTimestamp, 
                      pwdLastSet 
               FROM &amp;#39;LDAP://yourdomain.com&amp;#39;&amp;quot;&lt;/span&gt; 
               -objClass:computer &lt;/pre&gt;

&lt;p&gt;Logparser will now write a list of computers in bunches of 10 entries to the default output. In our case the command line window. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50b827b3_720068AC.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML50b827b3" border="0" alt="SNAGHTML50b827b3" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50b827b3_thumb_10D6DC8B.png" width="678" height="170" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we selected the &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms676824%28v=vs.85%29.aspx" target="_blank"&gt;LastLogonTimestamp&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms679430%28v=vs.85%29.aspx" target="_blank"&gt;PwdLastSet&lt;/a&gt; attributes. These attributes give a quite good indication if a computer is still active. But these are Active Directory timestamps so not really handy if we want to upload them to a SQL table for some further investigation, as SQL uses a different date/time format. Now Logparser can also help us here. It doesn’t have a native function for the conversion, but if we know, that Active Directory stores date/time values as a number of 100-nanosecond intervals that have elapsed since the 0 hour on January 1, 1601 in GMT, we can use some logparser native functions to do the conversion for us. So to convert the LastLogonTimestamp, we could use the following:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;TO_TIMESTAMP(ADD(DIV(TO_REAL(LastLogonTimestamp), 10000000.0), TO_REAL(TIMESTAMP(&amp;#39;1601&amp;#39;,&amp;#39;yyyy&amp;#39;))))&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now we add this to the original query and execute this (line breaks just added for readability):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;logparser.exe &lt;span class="str"&gt;&amp;quot;SELECT cn, 
                      operatingSystem, 
                      operatingSystemServicePack, 
                      &lt;strong&gt;TO_TIMESTAMP(ADD(DIV(TO_REAL(LastLogonTimestamp), 10000000.0), 
                          TO_REAL(TIMESTAMP(&amp;#39;1601&amp;#39;,&amp;#39;yyyy&amp;#39;)))) AS [LastLogon], 
                      TO_TIMESTAMP(ADD(DIV(TO_REAL(pwdLastSet), 10000000.0), 
                          TO_REAL(TIMESTAMP(&amp;#39;1601&amp;#39;,&amp;#39;yyyy&amp;#39;)))) AS [PwdLastSet]&lt;/strong&gt; 
               FROM &amp;#39;LDAP://yourdomain.com&amp;#39;&amp;quot;&lt;/span&gt; 
               -objClass:computer&lt;/pre&gt;

&lt;p&gt;and we get a nicely formatted output. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50b7c681_61A4F0F3.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML50b7c681" border="0" alt="SNAGHTML50b7c681" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50b7c681_thumb_007B64D2.png" width="686" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it’s time to export this information directly into a SQL table. So we need to specify the SQL Server, the Database and the table. We can optionally specify a username and password. We also tell it to create the table if it doesn’t exist and to empty it first, before adding new values, in case it already exists (as we might want to execute this regularly (line breaks just added for readability):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;logparser.exe &lt;span class="str"&gt;&amp;quot;SELECT cn, 
                      operatingSystem, 
                      operatingSystemServicePack, 
                      TO_TIMESTAMP(ADD(DIV(TO_REAL(LastLogonTimestamp), 10000000.0), 
                          TO_REAL(TIMESTAMP(&amp;#39;1601&amp;#39;,&amp;#39;yyyy&amp;#39;)))) AS [LastLogon], 
                      TO_TIMESTAMP(ADD(DIV(TO_REAL(pwdLastSet), 10000000.0), 
                          TO_REAL(TIMESTAMP(&amp;#39;1601&amp;#39;,&amp;#39;yyyy&amp;#39;)))) AS [PwdLastSet]
               &lt;strong&gt;INTO tmp_ADComputers&lt;/strong&gt;  
               FROM &amp;#39;LDAP://yourdomain.com&amp;#39;&amp;quot;&lt;/span&gt; 
               -objClass:computer
&lt;strong&gt;               -o:SQL 
               -server:YourSQLServer
               -database:Tempdb 
               -createTable:&lt;span class="kwrd"&gt;&lt;font color="#000000"&gt;ON&lt;/font&gt;&lt;/span&gt;
               -clearTable:ON&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;After we executed logparser, we can open the SQL Management Studio and check our TempDB Database and will find a new table, filled with all computer accounts from AD. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_18329C38.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_0F6293EC.png" width="687" height="203" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Compare with ConfigMgr&lt;/h3&gt;

&lt;p&gt;Now we can add a view to our ConfigMgr Database, that correlates the information from this temporary table with the ConfigMgr resources. The view could look like:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; [cn] &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Computer Name&amp;#39;&lt;/span&gt;
      ,[ObjectPath] &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Path&amp;#39;&lt;/span&gt;
      ,[operatingSystem] &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;OS&amp;#39;&lt;/span&gt;
      ,[operatingSystemServicePack] &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;SP&amp;#39;&lt;/span&gt;
      ,[LastLogon] 
      ,DATEDIFF(dd, [LastLogon], getdate()) &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;days LastLogon&amp;#39;&lt;/span&gt;
      ,[PwdLastSet]
      ,DATEDIFF(dd, [PwdLastSet], getdate()) &lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;days PwdLastSet&amp;#39;&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [tempdb].[dbo].[tmp_ADComputers] 
&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; cn &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;IN&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; name0 &lt;span class="kwrd"&gt;FROM&lt;/span&gt; v_GS_Computer_System) 
&lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; LastLogon&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Which will give you a list of computers that are in AD but not in ConfigMgr, ordered by their last logon timestamp.&lt;/p&gt;

&lt;p&gt;Feel free to take this as a starting point to implement your own, way more advanced queries &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_55071E0A.png" /&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Automating the process&lt;/h3&gt;

&lt;p&gt;So far, this has been a one-time effort and only reflects the AD information from the time we executed the query against AD. Now you probably want to keep this information up to date, which makes it necessary to automate this process.&lt;/p&gt;

&lt;p&gt;There are several ways to automate it. We could run this as a scheduled task. Just wrap the above command in a batch file and execute it on schedule. Easy. Done.&lt;/p&gt;

&lt;p&gt;Instead of using the scheduled tasks of the operating system, we could also make use of the SQL Server itself and have the SQL Agent run a job regularly. For demonstration purposes, we make use of another feature of logparser, and that is its capability to be scripted. During the installation it also registers a couple COM components, that we can use from any script language (VBScript, PowerShell, etc). And as we can natively execute scripts in a SQL Agent Job. we have a perfect fit. You need to make sure, that logparser is also installed on the SQL Server.&lt;/p&gt;

&lt;p&gt;So let’s create a new Job in SQL Management Studio &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_0DB1C818.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_6194CB26.png" width="402" height="249" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and give it a proper name&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50ca53d2_006B3F05.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML50ca53d2" border="0" alt="SNAGHTML50ca53d2" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50ca53d2_thumb_58588FE5.png" width="538" height="482" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we add a new step and select ActiveX Script&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50caf658_700FC74B.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML50caf658" border="0" alt="SNAGHTML50caf658" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML50caf658_thumb_23D7BD9D.png" width="543" height="487" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make it as easy as possible for you and keep this post a bit shorter, you can download a prepared script from CodePlex (&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;Download from here&lt;/a&gt;), that contains all necessary steps to call logparser from VBScript. &lt;/p&gt;

&lt;p&gt;Click on “&lt;strong&gt;Open&lt;/strong&gt;” and point it to the supplied script (&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;WriteADComputerInfoToSQL.vbs&lt;/a&gt;) and the content will pop up in the script window. Now all you need is to adjust some values in the script like giving it the proper domain name, sqlserver name etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_7BC50E7D.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_4C9322E6.png" width="527" height="512" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Define a schedule that fits to your needs and from then the view you have created before is always up to date.&lt;/p&gt;

&lt;p&gt;That’s it. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;As you have seen, this was just a basic scenario. I would be happy to hear/read from your solutions. &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_55071E0A.png" /&gt;&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161508" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Active+Directory/default.aspx">Active Directory</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Database/default.aspx">Database</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/ConfigMgr/default.aspx">ConfigMgr</category></item><item><title>MDT Database version history</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/23/mdt-database-version-history.aspx</link><pubDate>Thu, 23 Aug 2012 15:09:22 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161461</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161461</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/23/mdt-database-version-history.aspx#comments</comments><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As you might know, there is a whole bunch of settings/properties in MDT that drive the processing of MDT. And with every new version of MDT, the amount of settings typically just grows, but sometimes, they also drop the usage of some of them.&lt;/p&gt;  &lt;p&gt;Most of these settings are also available in the Database, that comes with MDT, and most of the new settings will also be published to the database, as soon as you upgrade it. However, sometimes, they also get rid of deprecated ones and you typically won’t recognize it on upgrades as the MDT luckily never actively removes an existing column from the database. But if you create a new database, you suddenly might experience, that something is missing and some custom scripts, stored procedures etc. don’t work anymore.&lt;/p&gt;  &lt;p&gt;This just happened to &lt;a href="http://msitpros.com/?p=1442" target="_blank"&gt;Oddvar Håland Moe&lt;/a&gt;, who tried to implement a Stored Procedure into a new MDT 2012 Update 1 environment. This Stored Procedure, &lt;a href="http://www.deploymentresearch.com/Blog/tabid/62/EntryId/24/Generate-Computernames-in-MDT-2010-based-on-prefix-and-a-sequencenumber.aspx" target="_blank"&gt;created by Johan Arwidmark&lt;/a&gt;, generates computer names based on some values in the database. However, he had do recognize, that it failed (&lt;a href="http://msitpros.com/?p=1442" target="_blank"&gt;see the full blog post here&lt;/a&gt;). &lt;/p&gt;  &lt;p&gt;As there is no publicly available documentation on what exactly has been added and removed during each update, and I have to keep track on it anyway for the &lt;a href="http://mdtwebfrontend.codeplex.com/" target="_blank"&gt;MDT Web FrontEnd&lt;/a&gt;, I thought it might be helpful for at least some of you, to publish this list:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Find the complete Version History starting at MDT 2008 Update 1 (Not many changes before) on CodePlex at: &lt;a title="http://mdtwebfrontend.codeplex.com/wikipage?title=MDT%20Database%20version%20history" href="http://mdtwebfrontend.codeplex.com/wikipage?title=MDT%20Database%20version%20history" target="_blank"&gt;MDT Database Version history&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I will keep it up to date on future versions as well.&lt;/p&gt;  &lt;p&gt;For your convenience, I’ve also added links for each setting to the corresponding documentation of MDT. I find it quite interesting from time to time to just snoop through them and get surprised on what else you can configure on MDT. As there is no updated MDT Documentation from Microsoft available online, I had to refer you mostly to the site of the &lt;a href="http://systemscenter.ru/" target="_blank"&gt;Russian System Center User group&lt;/a&gt;. If one of the link fails, please get back to me and I will update it. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;@MDTTeam could you please make an up-to-date MDT Documentation available online?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;li&gt;&lt;/li&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161461" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Database/default.aspx">Database</category></item><item><title>MDT Monitoring Deep Dive IV – Sending more information</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iv-sending-more-information.aspx</link><pubDate>Tue, 21 Aug 2012 12:57:02 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161456</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161456</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iv-sending-more-information.aspx#comments</comments><description>&lt;p&gt;In my post &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/25/mdt-monitoring-deep-dive-ii-consuming-the-data-yourself.aspx" target="_blank"&gt;MDT Monitoring Deep Dive II – Consuming the data yourself&lt;/a&gt;, I showed you how you can write your own web service, that consumes the MDT monitoring information. The next thing we will cover is, how we can send even more information from MDT and also make use of a pretty hidden feature in this monitoring option I blogged about &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iii-returning-settings-to-a-computer.aspx" target="_blank"&gt;in the last post&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Send additional information&lt;/h3&gt;  &lt;p&gt;As we have seen in the last couple of posts, MDT will automatically send some information about the current deployment status to a web service. Which it then uses to monitor the deployment. It covers some basic information like the current step and step name, any errors or warnings, current IP address, etc. But what if we would like to receive more information like ServiceTag/AssetTag for some custom identification, the Task Sequence ID it’s currently running, the deployment method or probably some custom property. &lt;/p&gt;  &lt;p&gt;Now as we have created a custom web service, it should be a piece of cake. Just add a new parameter to the “&lt;strong&gt;PostSettings&lt;/strong&gt;” method in the web service, and then add this parameter to the web service call in the ZTIUtility.vbs script. &lt;/p&gt;  &lt;p&gt;Well, that works, but you would have to redo this, whenever you want to add a new parameter and also whenever you upgrade or install MDT. While it’s generally a bad idea to change the original MDT files, a single change might be worth the effort, but ending up with multiple versions could create some headache. What I’m going to demonstrate now is a more generic way of adding new properties to our Monitoring.&lt;/p&gt;  &lt;p&gt;Let’s start with the MDT part first. The idea here is to create a new MDT List property, that holds a list of all additional properties, that shall be included in the web service call. We can then add them on the fly, even dynamically based on other values. On each web service call, MDT just loops through this list and adds an entry for each property.&lt;/p&gt;  &lt;p&gt;For reason of simplicity, I call the list “&lt;strong&gt;MonitorProperties&lt;/strong&gt;”. To define them for our deployment, we just add it to our customsettings.ini:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;[Settings]
Priority=Init,....,Default
Properties=MonitorProperties(*)&lt;/pre&gt;

&lt;p&gt;the “(*)” tells MDT, that this custom property shall be treated as a list. Now we can add a couple properties to this new list&lt;/p&gt;

&lt;pre class="csharpcode"&gt;[Init]
MonitorProperties001=ServiceTag
MonitorProperties002=SerialNumber
MonitorProperties003=TaskSequenceID
MonitorProperties004=Model
...&lt;/pre&gt;

&lt;p&gt;So far nothing really fancy. However, we need to make a small change to the ZTIUtility.vbs, otherwise no additional information will be send. In the ZTIUtility.vbs file, we search for the function called “&lt;strong&gt;CreateEvent&lt;/strong&gt;”. In the second part of the function, it’s preparing the web service call (see &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/25/mdt-monitoring-deep-dive-ii-consuming-the-data-yourself.aspx" target="_blank"&gt;This post&lt;/a&gt; for details). Just after MDT has prepared all its original information but right before it’s sending them, we add the following lines (in MDT 2012 and MDT 2012 Update 1 insert it at line 404)&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Add additional parameters specified in MonitorProperties&lt;/span&gt;
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; sMonProp  
&lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; sMonProp &lt;span class="kwrd"&gt;In&lt;/span&gt; oEnvironment.ListItem(&lt;span class="str"&gt;&amp;quot;MonitorProperties&amp;quot;&lt;/span&gt;).Keys
    sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;&amp;quot;&lt;/span&gt; &amp;amp; sMonProp &amp;amp; &lt;span class="str"&gt;&amp;quot;=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(sMonProp)
&lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;It should be pretty self-explaining. It just loops through the list of additional properties and for each property, it just adds the name and the configured value to the URL, which is sent to the web service. With this approach, we can influence what is being sent even during runtime, and it doesn’t have any negative side-effect. If nothing is configured, no changes will be applied.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Updating the web service&lt;/h3&gt;

&lt;p&gt;Well, this was the MDT side of things. Now we need to consume those additional information. To keep things simple, we make use of the &lt;strong&gt;Request.QueryString&lt;/strong&gt; object. It contains the query string from the requested URL and by this gives us a list of all keys and values that have been sent. Now we create two lists, one with the original MDT properties and one that holds the custom ones. In your own solution, you most probably going to have just one, but for demonstration purposes, it’s a nice way of collecting them.&lt;/p&gt;

&lt;p&gt;So all I do is I define a new class that contains all the original MDT properties&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; MDTDefaultMonitoringModel
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; uniqueID &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; computerName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; messageId &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; severity &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; stepName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; currentStep &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Short&lt;/span&gt;?
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; totalSteps &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Short&lt;/span&gt;?
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; id &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; message &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; dartIP &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; dartPort &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; dartTicket &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; vmHost &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; vmName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; Class&lt;/pre&gt;

&lt;p&gt;Then I can use this class as the parameter of my function, making use of a feature of ASP.Net MVC that maps each key from the query string to a corresponding property. Giving us a single object to work with.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; PostEvent(DefaultProps &lt;span class="kwrd"&gt;As&lt;/span&gt; MDTDefaultMonitoringModel) &lt;span class="kwrd"&gt;As&lt;/span&gt; ActionResult

    ...

&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;p&gt;If we use only the default properties, we are done now. To add our custom properties, we could either simply extend the above shown class, or we also make it a bit more generic and keep them in a list. As we need to assemble all parameters for our forwarded call to the original MDT Web service anyway, let’s use it to fill a list with all default properties.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; _DefaultProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;)

...

    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; param &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = &lt;span class="kwrd"&gt;String&lt;/span&gt;.Empty

    &lt;span class="rem"&gt;&amp;#39; Prepare parameter string&lt;/span&gt;
    &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; prop &lt;span class="kwrd"&gt;As&lt;/span&gt; PropertyDescriptor &lt;span class="kwrd"&gt;In&lt;/span&gt; TypeDescriptor.GetProperties(DefaultProps)
        &lt;span class="rem"&gt;&amp;#39; Fill a dictionary with all default MDT properties for performance reasons&lt;/span&gt;
        _DefaultProperties.Add(prop.Name, prop.GetValue(DefaultProps))
        param &amp;amp;= &lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;&amp;quot;&amp;amp;{0}={1}&amp;quot;&lt;/span&gt;, prop.Name, HttpUtility.UrlEncode(_DefaultProperties(prop.Name)))
    Next&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Then we just take the rest and add them to an additional list, that contains our custom properties.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="rem"&gt;&amp;#39; Get additional custom properties&lt;/span&gt;
    &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; prop &lt;span class="kwrd"&gt;In&lt;/span&gt; Request.QueryString.Keys
        &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; _DefaultProperties.ContainsKey(prop) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            _CustomProperties.Add(prop, Request.QueryString(prop))
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    Next&lt;/pre&gt;

&lt;p&gt;Looks like an ugly way of doing this, but as mentioned before, this is only for demonstration purposes. So the main target is, to just get it working. &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_5E41E420.png" /&gt;&lt;/p&gt;

&lt;p&gt;Now we would need to store or use this information somehow. In the next post, we will create a small database, that stores this information for further usage and also gives us the same information like the workbench in a web page. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Returning Settings back to the Client&lt;/h3&gt;

&lt;p&gt;To finalize this post, we want to add the “&lt;strong&gt;GetSettings&lt;/strong&gt;” function to our demo web service. As mentioned &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iii-returning-settings-to-a-computer.aspx" target="_blank"&gt;in my last post&lt;/a&gt;, it’s being queried by the gather process as soon as you switch on the monitoring feature. So without this function, you will regularly see some errors in your logs. &lt;/p&gt;

&lt;p&gt;As we did with the the former function, we could also just pass this information to the original MDT web service and send the result back to the client. But as I found this feature pretty hard to use and configure with the default MDT implementation, let’s preserve this for future usage and just return a sample string for now, to prove that it’s working. For demonstration purposes I return a “&lt;strong&gt;HelloWorld&lt;/strong&gt;” for a custom property called “&lt;strong&gt;MonitorResult&lt;/strong&gt;” &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; GetSettings(uniqueID &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; ActionResult

    &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; XmlResult(&lt;span class="kwrd"&gt;New&lt;/span&gt; GetSettingsResultModel &lt;span class="kwrd"&gt;With&lt;/span&gt; {.MonitorResult = &lt;span class="str"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;})
&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;p&gt;Looking at the log you can see, the gather process is now querying our custom Monitoring web service (which runs here on a different port than the MDT web service) and stores the result in the custom “MonitorResult” property.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_3DBAA46E.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_035F2E8D.png" width="746" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Find the &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/91691" target="_blank"&gt;download&lt;/a&gt; with the compiled web service and the updated ZTIUtility.vbs file &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/91691" target="_blank"&gt;on CodePlex&lt;/a&gt;. The source files can also be found on CodePlex in the &lt;a href="http://mdtcustomizations.codeplex.com/SourceControl/list/changesets" target="_blank"&gt;“Source Code” section&lt;/a&gt;. You might want to use a source control client like TortoiseSVN and point it to &lt;a title="https://mdtcustomizations.svn.codeplex.com/svn/Demo/MDT_MonitoringService/Current" href="https://mdtcustomizations.svn.codeplex.com/svn/Demo/MDT_MonitoringService/Current"&gt;https://mdtcustomizations.svn.codeplex.com/svn/Demo/MDT_MonitoringService/Current&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the next post, we will build upon what we have covered so far and move towards a more useful web service that stores and displays the information.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161456" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Monitoring/default.aspx">Monitoring</category></item><item><title>MDT Monitoring Deep Dive III – Returning settings to a Computer</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iii-returning-settings-to-a-computer.aspx</link><pubDate>Tue, 21 Aug 2012 09:13:20 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161454</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161454</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/08/21/mdt-monitoring-deep-dive-iii-returning-settings-to-a-computer.aspx#comments</comments><description>&lt;p&gt;If you enable the MDT Monitoring, you also enable kind of a “hidden” feature, that will give you just another way of setting properties on computers that are being deployed. &lt;/p&gt;  &lt;p&gt;One of the most important tasks in MDT is the gather process. It collects information locally on the client computer like hardware info etc. It evaluates the rules configured in the customsettings.ini and can also query databases and web services or run additional scripts for this evaluation. Now, since MDT 2012, if you enabled the monitoring, it will also query the MDT Monitoring web service, if it has some additional settings for the client. &lt;/p&gt;  &lt;p&gt;It calls a function called “&lt;strong&gt;GetSettings&lt;/strong&gt;” on the same web service path as it sends the monitoring data to. As a side note, if you create your own web service, as demoed in the previous post, make sure you also implement this function, otherwise you will see some errors in the Gather log. For the demo monitoring web service, we will fix this in the next post.&lt;/p&gt;  &lt;p&gt;Let’s have a quick look in the logs from a very simple gather with debugging enabled (otherwise those web service calls will be “silent”)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_0E048049.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_0CBFE76A.png" width="686" height="254" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;As we can see, it’s calling the “&lt;strong&gt;PostEvent&lt;/strong&gt;” function first to get the unique ID for this deployment. This normally happens before the gather steps runs the first time and is just due to the fact that I started only gather. Then it’s calling the “&lt;strong&gt;GetSettings&lt;/strong&gt;” function with this unique ID, but we don’t get any information back as we haven’t stored any yet.&lt;/p&gt;  &lt;p&gt;One important thing to note here is, that the web service call happens after(!) the gather process has finished processing the customsettings.ini file. This is important to know due to the “&lt;strong&gt;First value wins&lt;/strong&gt;” behavior of most MDT properties.&lt;/p&gt;  &lt;p&gt;Now, how can we store a setting, so that it can be retrieved from the computer? &lt;/p&gt;  &lt;p&gt;Well, there is a PowerShell cmdlet called “&lt;strong&gt;Set-MDTMonitorData&lt;/strong&gt;”, that we can use for this. And this cmdlet has a parameter called “&lt;strong&gt;Setting&lt;/strong&gt;” that takes a hashtable. Please see &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/16/mdt-monitoring-deep-dive-i.aspx" target="_blank"&gt;the first post of this series&lt;/a&gt; for some general information on how to use PowerShell cmdlets to handle monitoring data. &lt;/p&gt;  &lt;p&gt;Now for demonstration purposes, I want to set the &lt;strong&gt;OSDComputerName&lt;/strong&gt; to “&lt;strong&gt;HelloWorld&lt;/strong&gt;” and the &lt;strong&gt;SkipWizard&lt;/strong&gt; to “&lt;strong&gt;YES&lt;/strong&gt;”. For this I use the following PowerShell command:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;Set-MDTMonitorData -path MDT: -MacAddress &lt;span class="str"&gt;&amp;quot;00:11:22:33:44:55&amp;quot;&lt;/span&gt; -Setting @{&lt;span class="str"&gt;&amp;quot;OSDComputerName&amp;quot;&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;;&lt;span class="str"&gt;&amp;quot;SkipWizard&amp;quot;&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;YES&amp;quot;&lt;/span&gt;}&lt;/pre&gt;

&lt;p&gt;where MacAddress is the MacAddress of the Client computer. Now, if we run gather again, we will see, it is now obtaining those values from the web service, giving us just another way to influence our deployments.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_0051C441.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_511FD8A9.png" width="695" height="171" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next post, we will implement this function in our custom web service.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161454" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Monitoring/default.aspx">Monitoring</category></item><item><title>MDT Deployment Wizard goes JQuery – Combining VBScript and JavaScript</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/26/mdt-deployment-wizard-goes-jquery-combining-vbscript-and-javascript.aspx</link><pubDate>Thu, 26 Jul 2012 17:54:03 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161388</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161388</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/26/mdt-deployment-wizard-goes-jquery-combining-vbscript-and-javascript.aspx#comments</comments><description>&lt;p&gt;As you are well aware, JavaScript is, what drives our current online world, make it more dynamic then ever. In opposite to this, VBScript is, what drives almost everything in MDT, giving us full flexibility in our deployments, no matter which version of Windows we are using it on. But what most aren’t aware of is, that those languages easily talk to each other. &lt;/p&gt;  &lt;p&gt;“&lt;strong&gt;Why would I care?”&lt;/strong&gt; you might ask. &lt;/p&gt;  &lt;p&gt;Well, let’s think about the MDT Wizard or hta FrontEnds in general. Pretty often you write them based on VBScript, just because all the referenced files are using VBScript as well. Which is great for some easy dialogs, type in some information, choose from a short list, etc. and then go ahead. But as soon as you get more dynamic, let’s say manipulating the objects like adding Drag&amp;amp;Drop capabilities, fading in new elements to get a better user experience, etc. it gets a lot more difficult. Even worse, if you start doing any asynchronous operations, working with web services etc. On web sites, your are doing this the whole day. You are used to elements, that load and update in the background, without blocking your page. Reading a blog post while you see current information from twitter etc. &lt;/p&gt;  &lt;p&gt;Now if your wizard/frontend queries a database or a web service to e.g. show a list of Task Sequences or applications/packages etc., they need to do exactly the same. And yes, this is all possible in VBScript, but you have to put a lot of effort into it, to code this yourself. When using JavaScript, we have all those existing Frameworks and libraries, we can make use of like &lt;a href="http://www.prototypejs.org/" target="_blank"&gt;Prototype&lt;/a&gt;, &lt;a href="http://jquery.com/" target="_blank"&gt;JQuery&lt;/a&gt;, etc. That do this type of things out of the box. &lt;/p&gt;  &lt;p&gt;What I want to show in this post is, how we can leverage these features from JavaScript in our VBScript based hta. And I use the MDT Wizard as a sample. At the end of this post, we will have a working wizard, that shows us some twitter feeds.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Calling VBScript from JavaScript and vice versa&lt;/h3&gt;  &lt;p&gt;Let’s first start with some easy samples to demonstrate, that we can actually really call VBScript functions from JavaScript and also the other way round. Let’s have a look on this extremely simplified hta:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_4CBF6488.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_313A6285.png" width="660" height="401" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So if we click the button, it will call the function “&lt;strong&gt;GetInput&lt;/strong&gt;”, which is written in JavaScript. This function takes the value of the textbox and pass it to a function called “&lt;strong&gt;WriteOutput&lt;/strong&gt;”, which is written in VBScript, and this one just writes this text to a label. Not really rocket science but it shows how easy it is to combine different scripting languages.&lt;/p&gt;  &lt;p&gt;Now, let’s get a bit more advanced. We reference the &lt;strong&gt;ZTIUtility.vbs&lt;/strong&gt; from MDT and the &lt;a href="http://jquery.com/" target="_blank"&gt;JQuery&lt;/a&gt; library and have access to two different pretty complex libraries.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_2C9431FE.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_0A5C2678.png" width="659" height="430" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In this sample (I will &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/91746" target="_blank"&gt;upload it to CodePlex&lt;/a&gt; as always so no need to type it down from this screenshots &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_53522271.png" /&gt;), I make use of some JQuery specific features. After the document has finished loading, we dynamically bind the click event of the button and execute an anonymous function. In this function, we get the value of the text field, use a MDT function to obfuscate the value (I recently &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/24/extending-the-mdt-documentation-some-goodies-from-ztiutility-vbs-string-and-file-handling.aspx" target="_blank"&gt;blogged about this and other functions from MDT&lt;/a&gt;) slowly fade out an existing value, set a new value and slowly fade it in again.&lt;/p&gt;  &lt;p&gt;As you can see, JQuery is using a much simpler syntax to reference objects in our DOM and allows us to implement some event handling on the fly. And if you ever tried to create some animations like this fading out and it using VBScript, you well, don’t even try it &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_53522271.png" /&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Extending the MDT Wizard&lt;/h3&gt;  &lt;p&gt;OK, this was a small, simple hta. How about something more complex? Let’s extend the MDT Wizard and let it make use of this functionality. What I would like to achieve is having a wizard pane, that allows me to display tweets from Twitter. &lt;/p&gt;  &lt;p&gt;Another advantage of JQuery is its PlugIn architecture. So even if something is missing in JQuery, you can be sure there is a plugin available, that does exactly what you are missing. So for our example, I use a &lt;a href="http://tweet.seaofclouds.com/" target="_blank"&gt;Twitter PlugIn from SeaOfClouds called Tweet&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;After downloading JQuery and Tweet, we open the wizard.hta from MDT and reference this two scripts, plus the stylesheet that comes with Tweet to make it look a bit more pretty. Depending on the version of mshta, we also might need to add the &lt;a href="http://www.json.org/js.html" target="_blank"&gt;JSON2 javascript&lt;/a&gt;, to have JSON support.&lt;/p&gt;  &lt;p&gt;Now we need to create a new wizard pane. This pane contains just a textbox to type in some search string, a button to start the search and a div that will be used to store the tweets. In the XY part we tell it to execute a function called “getTweets()”.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Wizard&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Pane&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Twitter&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDT JQuery sample&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;[CDATA[
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;How To use JQuery for an interactive Deployment Wizard&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;tweets&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtsearch&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;search&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Search&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;onClick&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;getTweets()&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;query&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

        ]]&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Initialization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;getTweets()&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Initialization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Pane&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Wizard&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;In the wizard.hta, I add a new JavaScript part to define this “&lt;strong&gt;getTweets()&lt;/strong&gt;” function. The function binds the Tweets plugin to the div we have specified in the wizard pane. Each time it is called, it will get the value from the textbox, replace it with some default text if nothing has been entered and then call Twitter to get some Tweeds.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &amp;lt;script type=&lt;span class="str"&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt;&amp;gt;
        $(&lt;span class="kwrd"&gt;function &lt;/span&gt;() {

            $.support.cors = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        });

        &lt;span class="kwrd"&gt;function&lt;/span&gt; getTweets() {

            &lt;span class="kwrd"&gt;var&lt;/span&gt; searchstring;
            searchstring = $(&lt;span class="str"&gt;&amp;#39;#txtsearch&amp;#39;&lt;/span&gt;).val();

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (searchstring == &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;) {
                searchstring = &lt;span class="str"&gt;&amp;quot;Maik Koster&amp;quot;&lt;/span&gt;;
                $(&lt;span class="str"&gt;&amp;#39;#txtsearch&amp;#39;&lt;/span&gt;).val(searchstring);
            }

            $(&lt;span class="str"&gt;&amp;quot;#query&amp;quot;&lt;/span&gt;).tweet({
                avatar_size: 32,
                count: 4,
                query: searchstring,
                refresh_interval: 60,
                loading_text: &lt;span class="str"&gt;&amp;quot;searching twitter...&amp;quot;&lt;/span&gt;
            });

        };&lt;/pre&gt;

&lt;p&gt;The line with “&lt;strong&gt;$.support.cors = true;”&lt;/strong&gt; is used to solve a small problem we might experience when calling an external URL. As with most scripting languages used within a browser, JavaScript has the “&lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy" target="_blank"&gt;Same Origin Policy&lt;/a&gt;”. As we start the hta locally on the computer, it might not really “want” to talk to Twitter as it’s not “local”. But JQuery can also help us here and this one-liner gets around this problem.&lt;/p&gt;

&lt;p&gt;If everything went well, we now can start the MDT wizard with the following line&lt;/p&gt;

&lt;pre class="csharpcode"&gt;mshta.exe wizard.hta &lt;span class="str"&gt;&amp;quot;{PathToWizard}\wizard.hta&amp;quot;&lt;/span&gt; /definition:MDTWizard_Twitter.xml&lt;/pre&gt;

&lt;p&gt;and then should see some Tweets&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML505fd3c_19CF127A.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML505fd3c" border="0" alt="SNAGHTML505fd3c" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML505fd3c_thumb_46B44F88.png" width="694" height="510" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now you can use the text box to search in Twitter&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML5205700_5F9FFA00.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML5205700" border="0" alt="SNAGHTML5205700" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML5205700_thumb_14E90C66.png" width="696" height="511" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/91746" target="_blank"&gt;download this demo project from CodePlex&lt;/a&gt;. It’s not really a production ready sample, but hopefully gives you some new ideas. I will soon post an interesting solution that is based on this idea. If you have any feedback, please get back to me.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161388" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Boot+Wizard/default.aspx">Boot Wizard</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/hta/default.aspx">hta</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/vbscript/default.aspx">vbscript</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Development/default.aspx">Development</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/JavaScript/default.aspx">JavaScript</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>MDT Monitoring – Deep Dive II – Consuming the data yourself</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/25/mdt-monitoring-deep-dive-ii-consuming-the-data-yourself.aspx</link><pubDate>Wed, 25 Jul 2012 14:34:15 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161374</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161374</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/25/mdt-monitoring-deep-dive-ii-consuming-the-data-yourself.aspx#comments</comments><description>&lt;p&gt;As mentioned &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/16/mdt-monitoring-deep-dive-i.aspx" target="_blank"&gt;in my last post&lt;/a&gt;, MDT 2012 comes with an interesting monitoring option. It installs a web service, where events are being posted to and which the workbench queries to get the current status of all running and recently finished deployments.&lt;/p&gt;  &lt;p&gt;But as we also got aware, it’s posting a lot more information as visible in the workbench. So if you would like to see all the stuff that’s going on there and would like to do some more advanced processing/reporting on this stuff, you are reading the correct blog post &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2681CC64.png" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;How does MDT post the events to the web service?&lt;/h3&gt;  &lt;p&gt;First we need to know exactly, what MDT does, when it’s posting the events, so that we are able to consume and process them properly. To get this information, we open the &lt;strong&gt;ZTIUtility.vbs&lt;/strong&gt; (the MDT core library) and search for a function called “&lt;strong&gt;CreateEvent&lt;/strong&gt;”&lt;/p&gt;  &lt;p&gt;The first half of this function contains the logic that implements the &lt;strong&gt;EventShare&lt;/strong&gt; property. Let’s skip this for now.&lt;/p&gt;  &lt;p&gt;The second half is the more interesting part. It creates a web service object, builds a list of parameters to supply, calls the web service and stores the unique ID for further usage during this deployment. Let’s have a look on the latter three. &lt;/p&gt;  &lt;p&gt;Building the parameters (originally only three lines of code, just made it a bit more readable):&lt;/p&gt;  &lt;pre class="csharpcode"&gt;sID = oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;UUID&amp;quot;&lt;/span&gt;) &amp;amp; &lt;span class="str"&gt;&amp;quot;,&amp;quot;&lt;/span&gt; &amp;amp; Join(oEnvironment.ListItem(&lt;span class="str"&gt;&amp;quot;MacAddress&amp;quot;&lt;/span&gt;).Keys, &lt;span class="str"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;)

sLine = &lt;span class="str"&gt;&amp;quot;uniqueID=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;LTIGUID&amp;quot;&lt;/span&gt;) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;computerName=&amp;quot;&lt;/span&gt; &amp;amp; oUtility.ComputerName 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;messageID=&amp;quot;&lt;/span&gt; &amp;amp; &lt;span class="kwrd"&gt;CStr&lt;/span&gt;(iEventID)
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;severity=&amp;quot;&lt;/span&gt; &amp;amp; &lt;span class="kwrd"&gt;CStr&lt;/span&gt;(iType) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;stepName=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;_SMSTSCurrentActionName&amp;quot;&lt;/span&gt;) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;currentStep=&amp;quot;&lt;/span&gt; &amp;amp; sCurrentStep 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;totalSteps=&amp;quot;&lt;/span&gt; &amp;amp; sTotalSteps 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;id=&amp;quot;&lt;/span&gt; &amp;amp; sID 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;message=&amp;quot;&lt;/span&gt; &amp;amp; sMessage 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;dartIP=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;DartIP001&amp;quot;&lt;/span&gt;)
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;dartPort=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;DartPort001&amp;quot;&lt;/span&gt;) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;dartTicket=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;DartTicket&amp;quot;&lt;/span&gt;) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;vmHost=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;VMHost&amp;quot;&lt;/span&gt;) 
sLine = sLine &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;amp;vmName=&amp;quot;&lt;/span&gt; &amp;amp; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;VMName&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Which gives us a list of all the values that are being posted.&lt;/p&gt;

&lt;p&gt;Now it calls the web service and stores the result&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Call the web service&lt;/span&gt;

oService.WebService = oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;EventService&amp;quot;&lt;/span&gt;) &amp;amp; &lt;span class="str"&gt;&amp;quot;/MDTMonitorEvent/PostEvent?&amp;quot;&lt;/span&gt; &amp;amp; sLine
oService.Method = &lt;span class="str"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;
oService.Quiet = &lt;span class="kwrd"&gt;true&lt;/span&gt;
&lt;span class="kwrd"&gt;Set&lt;/span&gt; oResult = oService.Query&lt;/pre&gt;

&lt;p&gt;This tells us, that it adds “&lt;strong&gt;MDTMonitorEvent&lt;/strong&gt;” to the path of our &lt;strong&gt;EventService&lt;/strong&gt; property and that it assumes a function called &lt;strong&gt;PostEvent&lt;/strong&gt;. It’s using the HTTP Get method. And executes this web service quietly. As this is hard-coded and we don’t want to implement any changes in the MDT scripts, we should remember this when create out own web service.&lt;/p&gt;

&lt;p&gt;Finally, it takes the GUID, contained in the result and stores it in the property LTIGUID, which will then be used in any future web service call for this deployment.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Remember the returned GUID value&lt;/span&gt;

&lt;span class="kwrd"&gt;If&lt;/span&gt; oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;LTIGUID&amp;quot;&lt;/span&gt;) &amp;lt;&amp;gt; oResult.DocumentElement.Text &lt;span class="kwrd"&gt;then&lt;/span&gt;
    oEnvironment.Item(&lt;span class="str"&gt;&amp;quot;LTIGUID&amp;quot;&lt;/span&gt;) = oResult.DocumentElement.Text
&lt;span class="kwrd"&gt;End&lt;/span&gt; if&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Nothing fancy so far. So let’s create our own web service.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Create a web service&lt;/h3&gt;

&lt;p&gt;I’ve published already a couple samples on how to create a custom web service. E.g. in “&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2011/04/07/easily-access-information-from-any-database-and-publish-it-via-a-web-service-part-2-the-web-service.aspx" target="_blank"&gt;Easily access information from any database and publish it via a web service – Part 2 – The Web Service&lt;/a&gt;”. &lt;/p&gt;

&lt;p&gt;Using Visual Studio 2010 (Express edition should also work), we create a new, empty ASP.Net MVC 3 project. For web services I typically prefer the “old-style” asmx based web services, but as the web service call is hardcoded in MDT, pointing to a fixed URL, it would become a bit more complicated with re-routing etc. so I use something, that supports this out of the box. We could also use plain ASP.Net or WCF projects, or whatever you prefer. I chose MVC 3 as it’s pretty easy to implement and we can also use it easily to add some reporting to it. &lt;/p&gt;

&lt;p&gt;Now, as MDT uses &lt;strong&gt;MDTMonitorEvent&lt;/strong&gt; in the URL, we keep it simple and use the same. So let’s add a new Controller to our MVC 3 project, called “&lt;strong&gt;MDTMonitorEventController&lt;/strong&gt;” (be sure to have the &amp;quot;Controller” at the end of the name as MVC is driven by certain conventions). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_45C47337.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_6B4DF098.png" width="641" height="439" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function MDT is using is called “&lt;strong&gt;PostEvent&lt;/strong&gt;”. So we add a new function to our controller and call it “&lt;strong&gt;PostEvent&lt;/strong&gt;” as well. And also add all the parameters, that we have seen above while evaluating the ZTIUtility.vbs. This way, we can make use of the default routing in MVC, so &lt;strong&gt;“/MDTMonitorEvent/PostEvent&lt;/strong&gt;” will point to the controller and our action we have just created and consume all the information MDT is sending to us.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; PostEvent(uniqueID &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   computerName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   messageId &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   severity &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   stepName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   currentStep &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Short?&lt;/span&gt;,
                   totalSteps &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Short?&lt;/span&gt;,
                   id &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   message &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   dartIP &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   dartPort &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   dartTicket &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   vmHost &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;,
                   vmName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; ActionResult

    &lt;span class="rem"&gt;&amp;#39; Make sure we have a unique ID for this deployment&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;.IsNullOrEmpty(uniqueID) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        uniqueID = Guid.NewGuid.ToString
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;


    &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; XmlResult(uniqueID)

&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;So far, it’s not really doing much. It’s just creating a new GUID if there isn’t a uniqueID supplied and then returning this uniqueID wrapped in XML, as MDT expects it this way. In case you’ve used MVC 3 before and wonder about this ActionResult, the XMLResult has been taken from the &lt;a href="http://mvccontrib.codeplex.com/" target="_blank"&gt;MVCContrib project&lt;/a&gt;. It just converts a given object into XML and returns it. I’ll supply the whole project for download on CodePlex at the end of this post. So no need to worry.&lt;/p&gt;

&lt;p&gt;That’s actually already enough to run the project in Visual Studio (or deploy it to a test directory in IIS) and open the path to our &lt;strong&gt;MDTMonitorEvent/PostEvent&lt;/strong&gt; function. If we do this, we should see, that it returns a GUID (remember, we create a new one, if we don’t supply one?)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLda5f24_29D33E3F.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTMLda5f24" border="0" alt="SNAGHTMLda5f24" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLda5f24_thumb_53D33C67.png" width="655" height="126" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now every time we refresh the page, we get a new GUID. For verification, we supply a GUID as parameter “&lt;strong&gt;uniqueID&lt;/strong&gt;” and should see, that the function returns the same GUID:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLdc1e8c_6E9F6273.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTMLdc1e8c" border="0" alt="SNAGHTMLdc1e8c" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLdc1e8c_thumb_2671A697.png" width="659" height="116" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Get the MDT Workbench monitoring part working again&lt;/h3&gt;

&lt;p&gt;We are now ready to get the information from MDT. And are able to do whatever we want with it. Store it in a database, write it to a log file, do some evaluation, etc. But if our deployments post to this function instead of the MDT built-in one, the workbench won’t show anything. Which is ok, if we have our own monitoring solution. But it would also be nice, if we just seamlessly integrate our solution and everything else still works as before.&lt;/p&gt;

&lt;p&gt;There are a couple options to achieve this. &lt;/p&gt;

&lt;p&gt;We could write a second web service, that returns the data to the workbench. But that means, we would need to re-invent something, that is already being done by the MDT web service. And it’s actually pretty tough to tell the workbench to get the information from a different place or in a slightly different way as a lot of it is hardcoded.&lt;/p&gt;

&lt;p&gt;So how about just passing this information back to the original MDT web service? &lt;/p&gt;

&lt;p&gt;This way we can consume the data we want, while not really touching anything that comes out of the box and the monitoring tab in the Workbench will still work.&lt;/p&gt;

&lt;p&gt;As this is just a Proof-Of-Concept, it’s not pretty and more like a hack, but it’s working. So we just add the following lines to our “&lt;strong&gt;PostEvent&lt;/strong&gt;” function that will just prepare all the information we received, and forward it to the MDT Web service:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Forward information to original MDT service&lt;/span&gt;
&lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; param &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;

    &lt;span class="rem"&gt;&amp;#39; Prepare parameters&lt;/span&gt;
    param = &lt;span class="str"&gt;&amp;quot;uniqueID=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(uniqueID)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;computerName=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(computerName)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;messageID=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(messageId)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;severity=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(severity)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;stepName=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(stepName)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;currentStep=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(currentStep)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;totalSteps=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(totalSteps)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;id=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(id)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;message=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(message)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;dartIP=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(dartIP)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;dartPort=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(dartPort)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;dartTicket=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(dartTicket)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;vmHost=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(vmHost)
    param &amp;amp;= &lt;span class="str"&gt;&amp;quot;&amp;amp;vmName=&amp;quot;&lt;/span&gt; &amp;amp; HttpUtility.UrlEncode(vmName)

    &lt;span class="rem"&gt;&amp;#39; Create URL&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; BaseURL &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = WebConfigurationManager.AppSettings(&lt;span class="str"&gt;&amp;quot;MDTMonitoringURL&amp;quot;&lt;/span&gt;) &amp;amp; &lt;span class="str"&gt;&amp;quot;/MDTMonitorEvent/PostEvent?&amp;quot;&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; URL &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Uri(BaseURL &amp;amp; param)

    &lt;span class="rem"&gt;&amp;#39; Send data &lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; client &lt;span class="kwrd"&gt;As&lt;/span&gt; WebClient = &lt;span class="kwrd"&gt;New&lt;/span&gt; WebClient()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; data &lt;span class="kwrd"&gt;As&lt;/span&gt; Stream = client.OpenRead(URL)

    &lt;span class="rem"&gt;&amp;#39; Read uniqueID from MDT&lt;/span&gt;
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; reader &lt;span class="kwrd"&gt;As&lt;/span&gt; StreamReader = &lt;span class="kwrd"&gt;New&lt;/span&gt; StreamReader(data)
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; MDTXMLResult &lt;span class="kwrd"&gt;As&lt;/span&gt; XmlDocument = &lt;span class="kwrd"&gt;New&lt;/span&gt; XmlDocument

    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; xmlString &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = reader.ReadToEnd
    reader.Close()
    MDTXMLResult.LoadXml(xmlString)
    &lt;span class="kwrd"&gt;If&lt;/span&gt; MDTXMLResult.ChildNodes.Count &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        uniqueID = MDTXMLResult.ChildNodes(0).InnerText
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;


&lt;span class="kwrd"&gt;Catch&lt;/span&gt; exc &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception
    Trace.WriteLine(&lt;span class="str"&gt;&amp;quot;Exception: &amp;quot;&lt;/span&gt; &amp;amp; exc.Message)
&lt;span class="kwrd"&gt;End&lt;/span&gt; Try&lt;/pre&gt;

&lt;p&gt;To keep it a little bit easier to configure, we store the information about the original MDT Monitoring web service in the web.config in an application setting (MDTURL). &lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTURL&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://localhost:9800&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Just use the same URL, that MDT is using in the &lt;strong&gt;EventService&lt;/strong&gt; property (stored in your customsettings.ini):&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLe7cec7_5071A4BF.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTMLe7cec7" border="0" alt="SNAGHTMLe7cec7" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLe7cec7_thumb_69F931EC.png" width="660" height="545" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this sample, it’s installed on the same computer, so I can use “Localhost” instead.&lt;/p&gt;

&lt;p&gt;Now if we run our project again and open the URL as shown before and supply a couple more parameters, it should pass this information to our workbench. And Voila!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLed59b8_6CBEE6DF.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTMLed59b8" border="0" alt="SNAGHTMLed59b8" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLed59b8_thumb_201AAA3C.png" width="667" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Process the information&lt;/h3&gt;

&lt;p&gt;OK, so far, we don’t do anything with the information we now can get from MDT beside forwarding it to MDT again. This is, ehm, well, not optimal. It works for a demonstration, but let’s at least save this information to a file, so we can see what event are being sent during a deployment.&amp;#160; Then we can extend our solution later.&lt;/p&gt;

&lt;p&gt;To keep this easy, I use my preferred logging solution &lt;a href="http://nlog-project.org/" target="_blank"&gt;NLog&lt;/a&gt;, that I posted already about in “&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2010/07/07/add-logging-to-your-applications-nlog-for-beginners.aspx" target="_blank"&gt;Add logging to your applications. NLog for beginners.&lt;/a&gt;”. Adding this to the project is now easier than ever before, as it is available via &lt;a href="http://nuget.codeplex.com/" target="_blank"&gt;Nuget&lt;/a&gt; and so can be added to your project from within Visual Studio. Just install Nuget if you haven’t already. Then right click in your project and choose “Manage NuGet Packages …” and search for NLog. I recommend installing NLog and also the NLog Schema for IntelliSense. This will make it easier to create the NLog config file.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML263298b_05DA4118.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML263298b" border="0" alt="SNAGHTML263298b" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML263298b_thumb_43F35BC9.png" width="717" height="265" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the installation has been finished, you will see a new “NLog.config” file in your project root. Open it and define a new File target and a new rule to write all Info messages to this file. E.G. similar to this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;utf-8&amp;quot;&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;nlog&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.nlog-project.org/schemas/NLog.xsd&amp;quot;&lt;/span&gt;
      &lt;span class="attr"&gt;xmlns:xsi&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="rem"&gt;&amp;lt;!-- &lt;/span&gt;
&lt;span class="rem"&gt;  See http://nlog-project.org/wiki/Configuration_file &lt;/span&gt;
&lt;span class="rem"&gt;  for information on customizing logging rules and outputs.&lt;/span&gt;
&lt;span class="rem"&gt;   --&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;targets&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;xsi:type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;File&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Info&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;fileName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;${basedir}/logs/Info_${shortdate}.log&amp;quot;&lt;/span&gt; 
            &lt;span class="attr"&gt;layout&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;${longdate}: ${message}&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;targets&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;logger&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;*&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;level&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Info&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;writeTo&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Info&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;nlog&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The installation of NLog also adds a snippet to Visual Studio that eases the creation of log entries. So if we now open our MDTMonitorEventController class and type “&lt;strong&gt;nlogger&lt;/strong&gt;” followed by a double tab, it will be expanded to the following line &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; logger &lt;span class="kwrd"&gt;As&lt;/span&gt; NLog.Logger = NLog.LogManager.GetCurrentClassLogger()&lt;/pre&gt;

&lt;p&gt;And now you can use this object to write log entries. As mentioned, we just want to log some information about each event. So we simply add the following lines to the end of our “PostEvent” function, that will log some information like computername or the current step. Again, this is a Demo, so please be kind with me &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2681CC64.png" /&gt;&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;&amp;#39; Log the information for demonstration purposes&lt;/span&gt;
logger.Info(&lt;span class="str"&gt;&amp;quot;{0} - {1} ({2}/{3}) - {4} ({5}) - {6}&amp;quot;&lt;/span&gt;, computerName, stepName, currentStep, totalSteps, message, messageId, uniqueID)&lt;/pre&gt;

&lt;p&gt;If we test this again as described before, we should now see those entries in the files created in the logs folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLaa0cbf_625D9CB2.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTMLaa0cbf" border="0" alt="SNAGHTMLaa0cbf" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLaa0cbf_thumb_0C5D9ADB.png" width="643" height="249" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and also the latest entry in the workbench&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_5FD46AF4.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_5848FB87.png" width="646" height="58" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Configure MDT to use a different web service&lt;/h3&gt;

&lt;p&gt;Now as we can theoretically (and hopefully practically) consume the data that comes from MDT, we need to know, how we can configure MDT to talk to our own web service. Which is actually pretty easy. &lt;/p&gt;

&lt;p&gt;First, we need to deploy our web project to IIS or you download the sample project from CodePlex and add it as a new application to IIS (only tested on Server 2008 R2). &lt;/p&gt;

&lt;p&gt;Above you have seen the “&lt;strong&gt;EventService&lt;/strong&gt;” property in the &lt;strong&gt;customsettings.ini&lt;/strong&gt;. All we need to do is changing this to the path to our own web service like “&lt;a href="http://YourWebServer/YourWebDirectory"&gt;http://YourWebServer/YourWebDirectory&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Now when you start a new deployment, you should see it in the workbench as before and also should be able to see each individual event in the log file. In the screenshots below, I was running a Deployment of a Domain Controller based on &lt;a href="http://www.deploymentresearch.com/Blog/tabid/62/EntryId/57/The-Hydration-Kit-for-ConfigMgr-2012-RTM-is-available-for-download.aspx" target="_blank"&gt;Johan Arwidmarks Hydration Kit for ConfigMgr 2012&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the workbench before the Task Sequence starts&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_1E59B89B.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_3D9C5F6E.png" width="603" height="76" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choosing a Task Sequence&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_1CA8ECC7.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_1B6453E8.png" width="613" height="458" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then some time into the process&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_13007E91.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_43B3863C.png" width="623" height="460" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workbench just shows the current status&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_621DC725.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_01606DF9.png" width="622" height="92" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But as you can see in the log, a lot more has happened already&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLb6a131_47712B0C.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTMLb6a131" border="0" alt="SNAGHTMLb6a131" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTMLb6a131_thumb_53FED828.png" width="726" height="405" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the deployment has finished, we have something like 70 entries in the log file, so enough information to work with. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;I’ve published the compiled files to CodePlex (&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/91691" target="_blank"&gt;download here&lt;/a&gt;) again, and in one of the next posts, we are going to extend this solution, so we actually do more with it then just logging each step. I will also publish the source code soon. As always, this solution is provided AS IS. As it’s currently just a demonstration project, it’s only meant for testing. Please get back to me if you have any questions or feedback.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161374" width="1" height="1"&gt;</description></item><item><title>MDT Monitoring – Deep Dive I</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/16/mdt-monitoring-deep-dive-i.aspx</link><pubDate>Mon, 16 Jul 2012 13:35:27 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161350</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161350</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/16/mdt-monitoring-deep-dive-i.aspx#comments</comments><description>&lt;p&gt;The new monitoring feature is probably one of the most interesting and underestimated features of MDT 2012. In this version, its just some “initial” implementation, but it has great potential and in contrast to other custom extensions that have been available before, it’s tightly integrated and working out-of-the-box with support from Microsoft.&lt;/p&gt;  &lt;p&gt;What I won’t cover in this post is how to set it up and troubleshoot. As there has been some great posts already that cover all this in every detail. Please check &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/b/mniehaus/archive/2012/03/09/mdt-2012-new-feature-monitoring.aspx" target="_blank"&gt;Introduction into MDT 2012 Monitoring&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;and&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/b/mniehaus/archive/2012/05/10/troubleshooting-mdt-2012-monitoring.aspx" target="_blank"&gt;Troubleshooting MDT 2012 Monitoring&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;from the Mr. MDT Michael Niehaus himself. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Reasons to monitor your deployments&lt;/h3&gt;  &lt;p&gt;Automating deployments, doing this as zero-touch as possible has some huge advantages. But with this automation arise some requirements. One of the main reasons to automate such processes is to get rid of manual work. But this also means, that there isn’t necessarily someone in front of the computer, being able to react on problems or errors. Also, even if MDT is pretty easy to set up and use, the whole solution can be pretty complex at certain areas. And if something happens it can require some advanced skills to get a problem fixed. This means, it becomes a requirement, to keep track on deployments. Track problems and errors during deployments, to be able to fix them either immediately so this computer can be deployed as requested. But also get aware on smaller issues or problems, that might become a problem in future or in large scale deployments. We might want to know common problems, to have solutions available for the tech support. We might want track how long it takes on different machines, maybe even track the time of individual time consuming steps, to improve the overall time it takes but also to get aware, if the time on the whole deployment or individual steps increases over time, which might indicate a problem. Maybe to many updates, that should be integrated in the Reference image now. Better to get aware of this, before we reach the expected SLAs. &lt;/p&gt;  &lt;p&gt;So lets have a deeper look on what &lt;strong&gt;MDT Monitoring&lt;/strong&gt; does in the current version, where it supports us and where it still lacks some capabilities.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Monitoring options&lt;/h3&gt;  &lt;p&gt;First, there has always (well, not always, but since quite some time) been some kind of “central” logging/monitoring options within MDT. &lt;/p&gt;  &lt;p&gt;We have the possibility to have the logs copied to a central share at the end of the deployment, using the MDT &lt;a title="http://systemscenter.ru/mdt2012.en/slshare.htm" href="http://systemscenter.ru/mdt2012.en/slshare.htm" target="_blank"&gt;SLShare&lt;/a&gt; property. Or we can use the &lt;a title="http://systemscenter.ru/mdt2012.en/slsharedynamiclogging.htm" href="http://systemscenter.ru/mdt2012.en/slsharedynamiclogging.htm" target="_blank"&gt;SLShareDynamicLogging&lt;/a&gt;, which writes all the logs at runtime to this share. Having the logs available is great, but also requires you to parse those logs for errors, warning, problems, etc. and if used in larger deployments, its becoming even more difficult to keep track. &lt;/p&gt;  &lt;p&gt;There is also the “&lt;a href="http://systemscenter.ru/mdt2012.en/eventshare.htm" target="_blank"&gt;EventShare&lt;/a&gt;” property available. Its basically the predecessor of the current MDT Monitoring. We can specify a central network share and certain events are written to this share, where they can be picked up by a central monitoring solution. This could be a solution like SCOM, but Daniel Oxley, one of &lt;a href="http://blogs.technet.com/b/deploymentguys/" target="_blank"&gt;the Deployment Guys&lt;/a&gt;, wrote a small hta, that can monitor this share and give us some information. Please see &lt;a title="http://blogs.technet.com/b/deploymentguys/archive/2010/11/25/simple-deployment-monitoring.aspx" href="http://blogs.technet.com/b/deploymentguys/archive/2010/11/25/simple-deployment-monitoring.aspx" target="_blank"&gt;Simple deployment monitoring&lt;/a&gt; for more information.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;MDT 2012 Monitoring&lt;/h3&gt;  &lt;p&gt;With MDT 2012, there is now another option we can use, which is built into the Deployment Workbench (Please see links at the beginning on how to install and configure it). The MDT team actually extended their already existing function, that writes events to the &lt;a href="http://systemscenter.ru/mdt2012.en/eventshare.htm" target="_blank"&gt;EventShare&lt;/a&gt;, to write the same events also to a web service (There was someone before, that said web services are cool &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_569FF4F1.png" /&gt;), that comes with the workbench. This web service gets a lot more information then we had available before using the EventShare. On every event, it sends the following information to the web service&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;ID&lt;/strong&gt;(s) of the computer – a comma separated list of the UUID and all Mac Addresses&lt;/p&gt;  &lt;p&gt;- a &lt;strong&gt;unique ID&lt;/strong&gt;, that identifies each individual deployment&lt;/p&gt;  &lt;p&gt;- The current &lt;strong&gt;computer name&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;- the &lt;strong&gt;Message ID, &lt;/strong&gt;&lt;strong&gt;severity&lt;/strong&gt; and the &lt;strong&gt;message&lt;/strong&gt; text&lt;/p&gt;  &lt;p&gt;- The current Task Sequence &lt;strong&gt;step&lt;/strong&gt; &lt;strong&gt;Nr&lt;/strong&gt;, &lt;strong&gt;step name&lt;/strong&gt; and the &lt;strong&gt;total amount of steps&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;- DaRT information (&lt;strong&gt;IP Address, Port&lt;/strong&gt; and &lt;strong&gt;Ticket&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;- Virtual Machine information (&lt;strong&gt;Host name&lt;/strong&gt; and &lt;strong&gt;VM name&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The web service, installed by the Workbench consumes this information, does some processing like calculating the current progress, the processing time, etc. and makes this information available in the Workbench. On certain events, it will also log this information into the event log of the computer running the monitoring web service, which we could use to bind some tasks to those events. &lt;/p&gt;  &lt;p&gt;In the workbench, we can now see the progress of each running or recently finished/failed deployment. Additionally it will also allow us to connect to the remote computer, using Remote Desktop, VM Connection or DaRT Remote Control, depending on the supplied information and current phase. Very helpful if you experience any issues, that require you to get a hand on the remote computer.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Event logging&lt;/h3&gt;  &lt;p&gt;As mentioned, the web service will write certain events to the event log. Those events are:&lt;/p&gt;  &lt;p&gt;- a Deployment has started (EventID &lt;strong&gt;41016&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;- a Deployment completed successfully (EventID &lt;strong&gt;41015&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;- a Deployment failed (EventID &lt;strong&gt;41014&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;- an error occurred (EventID &lt;strong&gt;3&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;- a warning occurred (EventID &lt;strong&gt;2&lt;/strong&gt;)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_50E4DB4B.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_1AFFE631.png" width="550" height="204" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So we could create tasks that run on those events, coming from “&lt;strong&gt;MDT_Monitor&lt;/strong&gt;”, e.g. send an email, if a deployment completed.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;More events&lt;/h3&gt;  &lt;p&gt;But those are just a few of the events, that are being posted the web service. On any step that has been processed, an event will be posted. On long running steps, also the heartbeat (typically 5 min), so one can see if it’s still running. Now one would think, that those events would be ideal for e.g. the time monitoring. But this information isn’t available out of the box. The web service stores only the very last event as the workbench is mainly used to show the current status. It’s not meant for any advanced reporting, so there is also no need to store any historical information. But we will get to the additional events in a later post.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Get the current Monitoring information&lt;/h3&gt;  &lt;p&gt;Now let’s have a look on the information that is available. The easiest way is using the &lt;strong&gt;MDT Workbench&lt;/strong&gt; in the “&lt;strong&gt;Monitoring&lt;/strong&gt;” node and as shown by Michael Niehaus in the posts I’ve linked at the beginning. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_20DA89CA.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_7D5DE564.png" width="549" height="168" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;However, there are two additional ways to read this information. &lt;/p&gt;  &lt;p&gt;As it is a web service, you can read the information using your favorite browser and point it to &lt;a href="http://localhost:9801/MDTMonitorData/"&gt;http://localhost:9801/MDTMonitorData/&lt;/a&gt; (replace localhost with the name to your MDT server) and you will get an &lt;a href="http://www.odata.org/" target="_blank"&gt;ODATA&lt;/a&gt; feed as response, where you could then dig deeper into the different entities like&lt;/p&gt;  &lt;p&gt;&lt;a href="http://localhost:9801/MDTMonitorData/Computers/"&gt;http://localhost:9801/MDTMonitorData/Computers/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;or&lt;/p&gt;  &lt;p&gt;&lt;a href="http://localhost:9801/MDTMonitorData/ComputerIdentities/"&gt;http://localhost:9801/MDTMonitorData/ComputerIdentities/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The response you see seems a bit freaky, but it’s pretty easy to read and handle, when you need to write some custom code.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_220EFCDC.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_6A0D08F8.png" width="553" height="521" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you look closely, you will see, that the above screenshot shows, that some information is missing, that is being posted to the web service, namely the message id, severity and the message itself. Instead it contains some calculated values like “&lt;em&gt;PercentComplete&lt;/em&gt;” or Start and Endtime.&lt;/p&gt;  &lt;p&gt;However, as MDT is completely based on PowerShell, you can also use it to show this information. To do so, we just add the MDT cmdlet&lt;/p&gt;  &lt;pre class="csharpcode"&gt;Add-PSSnapin &lt;span class="str"&gt;&amp;#39;Microsoft.BDD.PSSNAPIN&amp;#39;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Then we attach the Deployment Share as new drive&lt;/p&gt;

&lt;pre class="csharpcode"&gt;New-PSDrive -Name MDT -Root &lt;span class="str"&gt;&amp;#39;C:\DeploymentShare&amp;#39;&lt;/span&gt; -PSProvider MDTPROVIDER&lt;/pre&gt;

&lt;p&gt;Now we can use the Get-MDTMonitorData function to read the information&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-MDTMonitorData -Path MDT:&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML3a3e4107_6C09BC27.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML3a3e4107" border="0" alt="SNAGHTML3a3e4107" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML3a3e4107_thumb_3788E9DF.png" width="562" height="295" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Basically the same information we have seen before. There is also a function called &lt;strong&gt;Set-MDTMonitorData&lt;/strong&gt;, which one could think, that it can be used to add information to the web service, but this is just for testing purposes. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Processing the events&lt;/h3&gt;

&lt;p&gt;So, what can we do, if we want to make use of this information for other purposes? Or better to say, what about using all the information that is being posted and not just the ones, that MDT is storing for us?&lt;/p&gt;

&lt;p&gt;It’s using a web service. So how about writing our own solution, that consumes this events? I’ll guide you through the details on how to do that in the next post.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161350" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Monitoring/default.aspx">Monitoring</category></item><item><title>New features in MDT 2012 – Download files from the internet</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/11/new-features-in-mdt-2012-download-files-from-the-internet.aspx</link><pubDate>Wed, 11 Jul 2012 18:55:53 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161337</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161337</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/11/new-features-in-mdt-2012-download-files-from-the-internet.aspx#comments</comments><description>&lt;p&gt;Sometimes it would be nice to be able to download some files from the internet or intranet during deployments. Maybe to get some updated tools like &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897557.aspx" target="_blank"&gt;bginfo.exe&lt;/a&gt; or store some configuration or wizard files outside of your boot image etc.&lt;/p&gt;  &lt;p&gt;This is quite easy to achieve for files that are located on a network share, as MDT has some built-in support for this since quite some time already and I’ve recently blogged about the available functions for File-handling (see &lt;a title="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/24/extending-the-mdt-documentation-some-goodies-from-ztiutility-vbs-string-and-file-handling.aspx" href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/24/extending-the-mdt-documentation-some-goodies-from-ztiutility-vbs-string-and-file-handling.aspx" target="_blank"&gt;Extending the MDT Documentation - Some goodies from ZTIUtility.vbs – String and File handling&lt;/a&gt; for more information). There are also a couple scripts available, that can do this for you and take away the need to script this yourself. One sample would be the &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/18/publishing-zticustomconfiguration-wsf-a-script-to-solve-some-common-tasks-in-mdt-deployments.aspx" target="_blank"&gt;ZTICustomConfiguration&lt;/a&gt; script, that I published recently.&lt;/p&gt;  &lt;p&gt;However all of them only cover typical file/folder operations on the same computer or from a network share. None of them support you to download something via http or ftp from the internet. But with MDT 2012 it finally also got some (basic) support for this scenario as well. &lt;/p&gt;  &lt;p&gt;In the Utility class, which is globally available using “&lt;strong&gt;oUtility&lt;/strong&gt;”, you can find a new function called “&lt;strong&gt;InternetFileDownload&lt;/strong&gt;”. This function takes two parameters. First is the path to the file to download (e.g. “&lt;a title="Bginfo.exe" href="http://live.sysinternals.com/Bginfo.exe" target="_blank"&gt;http://live.sysinternals.com/Bginfo.exe&lt;/a&gt;”) and the path to the target location, where the file shall be placed. Just be aware, that it requires the full path including the filename. So to download the mentioned BGInfo and store them e.g. in the temp directory locally on the computer you can call the following line within one of your scripts:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;oUtility.InternetFileDownload &lt;span class="str"&gt;&amp;quot;http://live.sysinternals.com/Bginfo.exe&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;%TEMP%\Bginfo.exe&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;As this is just some basic implementation, it’s a bit limited. It doesn’t support username and password, like the web&amp;#160; service calls do. It requires you to specify the path and filename for the target, so it doesn’t re-use the original file name from the download if only the folder is specified. There is not much error handling, so if something fails, it will just tell you that it failed, but not really why. And finally, you have to implement this function in your own script. &lt;/p&gt;

&lt;p&gt;For your convenience, I’ve published a simple wrapper file to CodePlex (&lt;a href="http://mdtcustomizations.codeplex.com/releases/edit/37245" target="_blank"&gt;Download ZTIDownloadInternetFile.wsf&lt;/a&gt;) that will allow you to call this function from within your task sequence. It takes the same parameters as described above. It will also have the same limitations as described, as I didn’t wanted to rewrite this core function, just give you easier access to it. But I’m pretty sure, that the MDT team will continue to work on this functionality and give us some more features. &lt;/p&gt;

&lt;p&gt;So to download the same file as shown above, you could now simply add a new “&lt;strong&gt;Run Command Line&lt;/strong&gt;” step to your Task Sequence (after you dropped the &lt;a href="http://mdtcustomizations.codeplex.com/releases/edit/37245" target="_blank"&gt;ZTIDownloadInternetFile.wsf&lt;/a&gt; script in your MDT Scripts folder) that executes the following command:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;cscript.exe &lt;span class="str"&gt;&amp;quot;%ScriptRoot%\ZTIDownloadInternetFile.wsf&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;http://live.sysinternals.com/Bginfo.exe&amp;quot;&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;%Temp%\Bginfo.exe&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_0001C521.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_65552907.png" width="688" height="289" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn’t really support more complex scenarios, but works quite well to quickly get one or a few files from the internet or a local web server. &lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161337" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/vbscript/default.aspx">vbscript</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category></item><item><title>Handling lists in MDT web service calls – Adding Computers / Users to Active Directory groups</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/05/handling-lists-in-mdt-web-service-calls-adding-computers-users-to-active-directory-groups.aspx</link><pubDate>Thu, 05 Jul 2012 08:08:35 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161316</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161316</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/07/05/handling-lists-in-mdt-web-service-calls-adding-computers-users-to-active-directory-groups.aspx#comments</comments><description>&lt;p&gt;A common question if it comes to deployments is, how to add a computer (or user) to one or several Active Directory groups. As you probably know, I generally prefer using web services for any Active Directory related task, as this avoids a lot of typical issues like permission problems, adding ADSI to the WinPE etc. Luckily the &lt;a href="http://mdtcustomizations.codeplex.com/documentation" target="_blank"&gt;Deployment Web Service&lt;/a&gt;, which is freely available on &lt;a href="http://mdtcustomizations.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt;, has some appropriate functions that allow us to fulfill this task.&lt;/p&gt;  &lt;p&gt;Adding a computer (or user) to a single group is pretty easy and can be done with a simple/single web service call. But how about adding the computer to a list of groups? Especially if we don’t know the amount of groups in advance? Which leads to the more generic question, how can I execute a web service function, if I have a bunch of similar values to supply and I actually would need to call the web service once per value? Do I need a huge amount of more or less redundant/equal steps in my Task Sequence?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Adding a computer / user to one AD group&lt;/h3&gt;  &lt;p&gt;Let’s start with the easy task and add the computer to one AD group only. It’s pretty straight forward and pretty similar to other web service calls, that I’ve demonstrated already on this blog. What we need is a custom property that stores our AD Group and the definition on how to call the web service. So these are the necessary entries in the customsettings.ini to make this work&lt;/p&gt;  &lt;pre class="csharpcode"&gt;[Settings]
Priority=Init,Default
Properties=ADGroup


[Init]
ADGroup=MySecureADGroup


[Default]


[AddComputerToADGroup]
WebService=http://YourWebServer/YourWebDirectory/AD.asmx/AddComputerToGroup
Parameters=ADGroup,OSDComputerName
ADGroup=Groupname
OSDComputerName=Computername&lt;/pre&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

&lt;p&gt;As you can see, we create a custom property called “&lt;strong&gt;ADGroup&lt;/strong&gt;”. During the gather step, this will be filled with the value “&lt;strong&gt;MySecureADGroup&lt;/strong&gt;” (while it’s processing the Init section). The section “&lt;strong&gt;AddComputerToADGroup&lt;/strong&gt;” contains the definition on how to call the web service. We don’t add it to the “&lt;strong&gt;Priority&lt;/strong&gt;” line, as we don’t want to execute this web service function during the gather step, as the computer account most likely doesn’t exists at that step.&lt;/p&gt;

&lt;p&gt;So what we need is a script, that reads this definition and executes the web service function. As you (hopefully) know, I’ve supplied a generic script for this purpose, that can be executed from a “&lt;strong&gt;Run Command Line&lt;/strong&gt;” step in the task sequence. It’s called “&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;ZTI_ExecuteWebservice.wsf&lt;/a&gt;” and also available &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;on CodePlex&lt;/a&gt;. Please see &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2010/10/08/executing-web-services-a-generic-mdt-script.aspx" target="_blank"&gt;this Blog Post&lt;/a&gt;, for a more detailed &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2010/10/08/executing-web-services-a-generic-mdt-script.aspx" target="_blank"&gt;description&lt;/a&gt; on what it can do.&lt;/p&gt;

&lt;p&gt;After we dropped this script in our MDT Scripts folder (or the Scripts folder in our ConfigMgr MDT Package) and updated the customsettings.ini, all we need is to add another “&lt;strong&gt;Run Command Line&lt;/strong&gt;” step to our Task Sequence. I would recommend to add this pretty late in the Task Sequence. At least after we have joined the domain &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2D684288.png" /&gt;&lt;/p&gt;

&lt;p&gt;The command line should execute the following command:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;cscript.exe &lt;span class="str"&gt;&amp;quot;%ScriptRoot%\ZTI_ExecuteWebservice.wsf&amp;quot;&lt;/span&gt; /wsSection:AddComputerToADGroup&lt;/pre&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_64CE53B6.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_6389BAD7.png" width="574" height="344" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We just call the script and tell it in which section it finds the necessary information. That’s actually all you need to add the computer to the specified AD Group. And as with all properties in MDT, you can get this information either static or based on some dynamic rules, even from a database or another web service.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Adding a computer / user to multiple AD groups&lt;/h3&gt;

&lt;p&gt;Now, as that was pretty simple, let’s tackle the problem on how to add it to multiple groups. MDT allows you to define List properties, that can be filled with values. Some built-in examples would be “&lt;strong&gt;Applications&lt;/strong&gt;”, “&lt;strong&gt;Packages&lt;/strong&gt;” or “&lt;strong&gt;Role&lt;/strong&gt;”. Now you can also define one of those List properties as a parameter for the web service call. A pretty common scenario for this is the &lt;strong&gt;MacAddress&lt;/strong&gt; property which can also store several values and is pretty often used in Web service and Database calls. On default, MDT uses only the first value of the list. So if we create a custom list that stores our AD Groups, we would only be able to add it to the first one.&lt;/p&gt;

&lt;p&gt;That means, we need to find a way to iterate through a list and execute the web service for each single entry. To solve this problem, I’ve updated the mentioned script (so be sure to &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;download the most recent version&lt;/a&gt;, if you used it already). It now has an additional argument, that can be supplied either directly via command line or via customsettings.ini. It’s called “&lt;strong&gt;wsProcessLists&lt;/strong&gt;”. If it’s not set at all or set to “&lt;em&gt;False&lt;/em&gt;” or “&lt;em&gt;No&lt;/em&gt;”, everything will behave like before. Only the first value would be used. If you set it to “&lt;em&gt;True&lt;/em&gt;” or “&lt;em&gt;Yes&lt;/em&gt;”, it will iterate over the list (if there is any) and execute the configured web service function for each entry.&lt;/p&gt;

&lt;p&gt;So assume the following customsettings.ini&lt;/p&gt;

&lt;pre class="csharpcode"&gt;[Settings]
Priority=Init,Default
Properties=ADGroup(*)


[Init]
ADGroup001=MySecureADGroup1
ADGroup002=MySecureADGroup2
ADGroup003=MySecureADGroup3


[Default]


[AddComputerToADGroup]
WebService=http://YourWebServer/YourWebDirectory/AD.asmx/AddComputerToGroup
Parameters=ADGroup,OSDComputerName
ADGroup=Groupname
OSDComputerName=Computername&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Only slightly different to the one I showed before. The property is now a list property ( defined by this&lt;strong&gt; (*)&lt;/strong&gt; ) and we add a couple more values to it. Nothing else has changed. Now all we need to change in the command line is adding the mentioned argument:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;cscript.exe &lt;span class="str"&gt;&amp;quot;%ScriptRoot%\ZTI_ExecuteWebservice.wsf&amp;quot;&lt;/span&gt; /wsSection:AddComputerToADGroup /wsProcessLists:True&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;If we now execute the task sequence, the new computer account will be a member of all configured AD groups. We can use the same functionality to add it to several ConfigMgr collections, etc. Each web service call will be logged, and the script will also write some additional information for better troubleshooting if you enable the debugging in MDT.&lt;/p&gt;

&lt;p&gt;Here two screenshots from the BDD.log (I enabled debugging, so we can see a bit more). It’s using the customsettings.ini just shown. In the first screenshot, it’s using the default MDT behavior. As you can see, only one call is executed and the computer is only added to the first group we have added to the list:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML376622_2E3082A5.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML376622" border="0" alt="SNAGHTML376622" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML376622_thumb_25CCAD4E.png" width="814" height="392" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now in the second screenshot, we have called the script with &lt;strong&gt;“/wsProcessLists:True&lt;/strong&gt;”, and we see that the web service is called three times:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML3cafbf_3A8E8001.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SNAGHTML3cafbf" border="0" alt="SNAGHTML3cafbf" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML3cafbf_thumb_72EC810C.png" width="819" height="395" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That should be simple enough, shouldn’t it?&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;However, there are two small limitations on that functionality&lt;/p&gt;

&lt;p&gt;1. It’s processing only the first list property it finds in the list of parameters. So if you have several of them, be sure to order them appropriately in the web service definition.&lt;/p&gt;

&lt;p&gt;2. The list must have a different name, than the corresponding web service parameter. The script is mapping each value directly to this parameter, which doesn’t work, if they have the same name.&lt;/p&gt;

&lt;p&gt;Also, if you would like to process the results, be aware that these are independent calls, so only the value from the last execution would be stored (or from the first run, if you told the script to not overwrite any existing values).&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Happy testing and as always, this script and information is provided &lt;strong&gt;AS IS&lt;/strong&gt;. Be sure to test it thoroughly and whatever happens, it will be your fault alone &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2D684288.png" /&gt;.&lt;/p&gt;

&lt;p&gt;If you found this script helpful, please get back to &lt;a href="http://mdtcustomizations.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt; and give it a proper rating. If you found an issue with it or would like to have some more functionality implemented, just start a &lt;a href="http://mdtcustomizations.codeplex.com/discussions" target="_blank"&gt;discussion&lt;/a&gt;. I’m happy about any feedback.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161316" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Webservice/default.aspx">Webservice</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Active+Directory/default.aspx">Active Directory</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category></item><item><title>Offline Domain Join with MDT</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/25/offline-domain-join-with-mdt.aspx</link><pubDate>Mon, 25 Jun 2012 07:54:35 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161266</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161266</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/25/offline-domain-join-with-mdt.aspx#comments</comments><description>&lt;p&gt;Windows 7 and Windows Server 2008 R2 come with a new feature called “Offline Domain Join”. With this, you get the possibility to join a computer or member server to the domain, even if that computer/server currently isn’t connected to the domain. Why would I need that, you might ask. Well, think about remote workers or remote technicians, that might only have a VPN connection to your network. Or you have (or are) an external company (OEM, etc.), preparing the new computers at a remote location and you want to have them read to go, without anyone locally doing the domain join afterwards or some script that runs automatically after the first restart.&lt;/p&gt;  &lt;p&gt;For this, Windows 7 and Windows Server 2008 R2 come with a small tool called “&lt;strong&gt;DJoin.exe&lt;/strong&gt;”. It must be called with elevated privileges. DJoin allows you to either provision a new computer account and store this information in a textfile (or a Base 64 encoded blob), or use this textfile to prepare the current computer to join the domain using the specified textfile on next reboot (e.g. after it has been delivered).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Provision a new computer&lt;/h3&gt;  &lt;p&gt;To provision a new computer account, you can specify the Domain&amp;#160; to join, the name of the new computer account and optionally the OU where the computer account shall be created. &lt;/p&gt;  &lt;p&gt;Lets create a Demo computer:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a66d019_1C9999B8.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML2a66d019" border="0" alt="SNAGHTML2a66d019" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a66d019_thumb_135D5E77.png" width="705" height="124" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you don’t have DC with Server 2008 R2 available, you need to specify the parameter “/DOWNLEVEL”. However after &lt;strong&gt;DJoin.exe&lt;/strong&gt; has finished successfully, we will have a small text file, that contains the Offline domain join information, that are necessary to join a computer with this name to the domain. If you look at the file, you will see some &lt;a href="http://en.wikipedia.org/wiki/Base64" target="_blank"&gt;Base 64 encoded information&lt;/a&gt;. As this is pretty sensitive information, you should keep this file protected.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a6bc81d_1FEB0B93.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML2a6bc81d" border="0" alt="SNAGHTML2a6bc81d" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a6bc81d_thumb_605DA842.png" width="724" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Offline Domain Join – manually&lt;/h3&gt;  &lt;p&gt;Now we can use this text file and the &lt;strong&gt;DJoin.exe&lt;/strong&gt; on another computer, to join it to the domain. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a718267_159694DB.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML2a718267" border="0" alt="SNAGHTML2a718267" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML2a718267_thumb_286B1885.png" width="728" height="128" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;On next reboot, the computer will be joined to the domain. So you could run this as last step of your preparation, before the computer is being sent to its target location. And if it boots there, its already a member of the domain.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Offline Domain Join – automatically using DJoin.exe&lt;/h3&gt;  &lt;p&gt;So far, nothing really fancy. OK, the offline domain join itself is pretty cool, but still requires some manual steps. And as a frequent reader of this blog, you most probably want to have this automated. &lt;/p&gt;  &lt;p&gt;Let’s first automate the domain join via the text file that’s being created. Automating the creation of the text files is pretty easy. All you need is a list of computers names, and then just parse this list with e.g. PowerShell and call djoin.exe for each entry as show above. Then we need a small script, that is called from our Task Sequence and executes &lt;strong&gt;DJoin.exe&lt;/strong&gt; appropriately. &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;Find the script on CodePlex&lt;/a&gt;. It expects the file to be named with the computer name and will find it at any “default” location, e.g. in the Tools or Servicing folder. After next reboot (typically after the Task Sequence has completed) the computer will be a domain member.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_6D373CB9.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_1D7E1170.png" width="609" height="296" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Offline Domain Join – Automatically using Unattend.xml&lt;/h3&gt;  &lt;p&gt;That works, but still requires some manual work. However, there is a second way to do this, which doesn’t require the text file itself. As actually all we need is the Base 64 encoded Blob. How could we get this blob without the file? Well, one way could be to store this blob in a custom property in the database. Now this database just needs to be available from everyone, that does the deployment. Or imagine you have a publicly available web service (with proper authentication and authorization &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_6ED7E2C0.png" /&gt; ) that takes a computer name and spits out the required blob. Then this web service could be called from the OEM during the preparation of the computer and we have all the information we need to join this computer to the domain.&lt;/p&gt;  &lt;p&gt;Now that blob needs to be added to the Unattend.xml file. MDT is already updating the Unattend.xml file with all your settings. So one would think it shouldn’t be to hard to get this done. Sadly, it’s not working out of the box as MDT doesn’t know about how to add this information. We would need to update the original ZTIConfigure.xml file with the necessary mapping information. But I really hate to change the original files as I would have to redo it on every update, it could interfere with other scripts, etc. Luckily, I just published a script, that is, beside other helpful tasks, also able to update xml files (see &lt;a href="http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/18/publishing-zticustomconfiguration-wsf-a-script-to-solve-some-common-tasks-in-mdt-deployments.aspx" target="_blank"&gt;ZTICustomConfiguration.wsf – a script to solve common tasks in MDT Deployments&lt;/a&gt; for more information and samples). We just need to download it from CodePlex and drop it in the MDT scripts folder.&lt;/p&gt;  &lt;p&gt;We update the ZTICustomConfiguration.xml file with a section that will update the Unattend.xml file as required for our offline domain join. It will only be processed, if we are in the PREINSTALL Phase and if the OfflineDomainJoinBlob has a value.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configurationset&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ODJ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;operations&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="rem"&gt;&amp;lt;!-- Updates the unattend.xml file for an offline domain join--&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%OSDAnswerFilePath%&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;All&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;PHASE&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;PREINSTALL&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OfflineDomainJoinBlob&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;notempty&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//settings[@pass=&amp;quot;specialize&amp;quot;]/component[@name=&amp;quot;Microsoft-Windows-UnattendedJoin&amp;quot;]/Identification]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//settings[@pass=&amp;quot;specialize&amp;quot;]/component[@name=&amp;quot;Microsoft-Windows-UnattendedJoin&amp;quot;]]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;position&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;child&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Identification&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Provisioning&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;AccountData&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%OfflineDomainJoinBlob%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;AccountData&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Provisioning&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Identification&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;operations&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configurationset&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now we need to update our CustomSettings.ini. We create a new custom property called &lt;strong&gt;OfflineDomainJoinBlob&lt;/strong&gt; (Used in the xml seen above). And also configure it to reach out to our web service that returns this blob and store the value in this property. But this could also be a database call or a script that reads the text file and extracts the blob etc. As always, there isn’t only one way of doing things.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;[Settings]
Priority=Init,GetODJBlob,Default
Properties=ConfigurationSet(*),OfflineDomainJoinBlob


[Init]
ConfigurationSet001=ODJ


[Default]


[GetODJBlob]
WebService=http://YourWebServer/DeploymentWebService/AD.asmx/GetOfflineDomainJoinBlob
Parameters=OSDComputerName,MachineObjectOU
OSDComputerName=ComputerName
MachineObjectOU=OUPath
OfflineDomainJoinBlob=string&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Then we add a new step to our Task Sequence, just right after the “Configure” step, that calls our ZTICustomConfiguration.wsf script. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_407E5D13.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_344CBD1F.png" width="709" height="345" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;What will happen during the deployment is the following. &lt;/p&gt;

&lt;p&gt;1. At the very beginning, MDT will run the Gather and evaluate our customsettings.ini. It will create the custom properties we have specified, it will set the values we have specified and it will also call the web service and store the blob in the property &lt;strong&gt;OfflineDomainJoinBlob&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2. &lt;strong&gt;ZTICustomConfiguration.wsf&lt;/strong&gt; will be called just after the Configure step has already updated the &lt;strong&gt;Unattend.xml&lt;/strong&gt; file. If the &lt;strong&gt;OfflineDomainJobBlob&lt;/strong&gt; property has a value assigned, it will remove all information about an online domain join and replace it with the offline domain join information. &lt;/p&gt;

&lt;p&gt;3. After the first reboot, Windows setup will evaluate the &lt;strong&gt;Unattend.xml&lt;/strong&gt; file and by this automagically join the domain that isn’t available yet.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;As always, all scripts and files can be found on CodePlex (&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/37245" target="_blank"&gt;Download here&lt;/a&gt;). But you don’t get everything for free this time. The updated web service that is used during this sample will be published, after the next 20 reviews of the &lt;a href="http://mdtcustomizations.codeplex.com/" target="_blank"&gt;MDT Customizations project on CodePlex&lt;/a&gt;. &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_6ED7E2C0.png" /&gt; Interested to see how long that takes.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161266" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Microsoft+Deployment/default.aspx">Microsoft Deployment</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Active+Directory/default.aspx">Active Directory</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/vbscript/default.aspx">vbscript</category></item><item><title>Extending the MDT Documentation - Some goodies from ZTIUtility.vbs – String and File handling</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/24/extending-the-mdt-documentation-some-goodies-from-ztiutility-vbs-string-and-file-handling.aspx</link><pubDate>Sun, 24 Jun 2012 16:05:39 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161265</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161265</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/24/extending-the-mdt-documentation-some-goodies-from-ztiutility-vbs-string-and-file-handling.aspx#comments</comments><description>&lt;p&gt;The Microsoft Deployment Toolkit comes with a pretty extensive and almost complete documentation, which is even more remarkable, as it’s a free tool. &lt;/p&gt;  &lt;p&gt;But even this almost complete documentation, it’s lacking some information that might be helpful for some of you. I’ll start with two things that are available in the ZTIGather.vbs. Why should you care? Well, ZTIGather.vbs is more or less THE core script, that is referenced by almost any other scripts. It holds all the publicly available classes for Logging, environment handling etc. But it also contains two classes, that are only mentioned with one sentence each in the documentation. But can be really helpful if you need to do some advanced things in the customsettings.ini (as you probably know, you can use all available vbscript functions during the gather process, so these will be available too as ZTIUtility.vbs is referenced during that step) or if you write your own scripts, that most probably also reference the ZTIUtility.vbs. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;String Handling&lt;/h3&gt;  &lt;p&gt;The “Strings” class, which is globally available using the object “&lt;strong&gt;oStrings&lt;/strong&gt;” has the following helpful functions:&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;isNullOrEmpty (Value)&lt;/strong&gt; –&amp;gt; Returns &lt;em&gt;True&lt;/em&gt;, if the supplied value is either Null or an empty string. &lt;em&gt;False&lt;/em&gt;, if not.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;AddToList (List, Item, Delimiter)&lt;/strong&gt; –&amp;gt; Adds a new item to a delimited list of items. E.G. &lt;strong&gt;AddToList (“One,Two,Three”, “Four”, “,”)&lt;/strong&gt; will return &lt;em&gt;“One,Two,Three,Four”.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;HexWidth (Value, length)&lt;/strong&gt; –&amp;gt; Returns the supplied value as hex value of the specified length. E.G. &lt;strong&gt;HexWidth (2748, 8)&lt;/strong&gt; returns &lt;em&gt;00000ABC&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;HexWidthByte (Value, Length)&lt;/strong&gt; –&amp;gt; Returns the first byte of the supplied value as hex value of the specified length. E.G. &lt;strong&gt;HexWidthByte (A, 8)&lt;/strong&gt; returns &lt;em&gt;00000041&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;IsWhiteSpace (Char)&lt;/strong&gt; –&amp;gt; Returns &lt;em&gt;True&lt;/em&gt;, if the supplied Character can be interpreted as a “Whitespace”, so a real space, Tab, VerticalTab, LineFeed, FormFeed or CariageReturn.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;TrimAllWS (String)&lt;/strong&gt; –&amp;gt;&amp;#160; Removes all Whitespaces from the supplied string. E.G. &lt;strong&gt;TrimAllWS (“&lt;a href="http://www.deploymentresearch.com/" target="_blank"&gt;Contributing is everything …&lt;/a&gt;”)&lt;/strong&gt; returns “&lt;em&gt;&lt;a href="http://www.deploymentresearch.com/" target="_blank"&gt;Contributingiseverything…&lt;/a&gt;&lt;/em&gt;”&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;RightAlign (String, Length)&lt;/strong&gt; –&amp;gt; Returns a string of the given length, with the supplied string aligned to the right. If Length is lower than the total length of the supplied string, only a substring counted from right will be returned.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;LeftAlign (String, Length)&lt;/strong&gt; –&amp;gt; Returns a string of the given length with the supplied string. Is the length is lower than the total length of the supplied string, only a substring counted from left will be returned. If it’s larger, Spaces will be appended to the supplied string.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;ForceAsString (Value)&lt;/strong&gt; –&amp;gt; Returns the supplied value as a string. If the supplied value can’t be interpreted as a string, an empty string will be returned. Arrays will be converted into a space delimited list of items.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;ForceAsArray (Value, Delimiter)&lt;/strong&gt; –&amp;gt; Returns the supplied value as an array. If the supplied value is a string of delimited items (like from &lt;strong&gt;AddToList&lt;/strong&gt; or &lt;strong&gt;ForceAsString&lt;/strong&gt;), it will split this string at each delimiter into array items.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;GenerateRandomGUID&lt;/strong&gt; –&amp;gt; Returns a new &lt;em&gt;GUID&lt;/em&gt;. Very helpful if you need a unique value. &lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;base64Encode (Value)&lt;/strong&gt; –&amp;gt; Returns the supplied value as &lt;a href="http://en.wikipedia.org/wiki/Base64" target="_blank"&gt;Base64&lt;/a&gt; encoded string. That’s how e.g. the values of all MDT properties are stored in the &lt;strong&gt;Variables.dat&lt;/strong&gt; to survive a reboot.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;base64Decode (Value)&lt;/strong&gt; –&amp;gt; Returns the original (decoded) value of the supplied Base64 encoded string. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So if you need a unique string of 6 characters for a computer name, all you need to do is adding the following to your customsettings.ini&lt;/p&gt;  &lt;pre class="csharpcode"&gt;[Settings]
Priority=Init,...,Default

[Init]


[Default]
OSDComputerName=XYZ-#Mid(oStrings.GenerateRandomGUID,2,6)#&lt;/pre&gt;

&lt;p&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Which will then create something similar to &lt;strong&gt;XYZ-855CDD&lt;/strong&gt; during the Gather step.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_7B9B38FB.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_64F8EAB4.png" width="531" height="57" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;File Handling&lt;/h3&gt;

&lt;p&gt;ZTIUtility.vbs also comes with a publicly available class, that does some common file and folder handling. The following functions are available using the object “&lt;strong&gt;oFileHandling&lt;/strong&gt;”. All Functions will log their activity in the log file.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;RemoveFolder (Path)&lt;/strong&gt; –&amp;gt; Removes the folder specified by the path. It will also remove all files and subfolders. Call &lt;strong&gt;RemoveFolderEx (Path, False)&lt;/strong&gt; to disable the logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;DeleteFile (Filepath)&lt;/strong&gt; –&amp;gt; Deletes the specified File. Call &lt;strong&gt;DeleteFileEx (FilePath, False)&lt;/strong&gt; to disable logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;MoveFile (FilePath, DestinationPath)&lt;/strong&gt; –&amp;gt; Moves the specified file to the specified new Destination. Call &lt;strong&gt;MoveFileEx (FilePath, DestinationPath, False)&lt;/strong&gt; to disable logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;CopyFile (FilePath, DestinationPath, Overwrite)&lt;/strong&gt; –&amp;gt; Copies the specified to the specified location. If Overwrite is set to True, an existing file will be overwritten, if set to False, not. Use &lt;strong&gt;CopyFileEx (FilePath, DestinationPath, Overwrite, False)&lt;/strong&gt; to disable logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;CopyFolder (FolderPath, DestinationPath, Overwrite)&lt;/strong&gt; –&amp;gt; Copies the specified folder to the specified Path. If Overwrite is set to True, an existing folder will be overwritten, if set to False not. Use &lt;strong&gt;CopyFolder (FolderPath, DestinationPath, Overwrite, False)&lt;/strong&gt; to disable logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;MoveFolder (FolderPath, DestinationPath)&lt;/strong&gt; –&amp;gt; Moves the specified Folder to the specified path. User &lt;strong&gt;MoveFolder (FolderPath, DestinationPath, False)&lt;/strong&gt; to disable logging.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;NormalizePath (Path)&lt;/strong&gt; –&amp;gt; Returns the “complete” path of the supplied path. If you e.g. specify only a file name, the complete path including drive will be returned.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;GetTempFile&lt;/strong&gt; –&amp;gt; Returns the path to a temporary file at the current temporary folder that could be used. It does not create the temporary file, just returns a unique name that can be used to create one. Use &lt;strong&gt;GetTempFileEx (Extension)&lt;/strong&gt; to return a new temporary file name with the specified extension. On default it will be “tmp”.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;GetTempFolder&lt;/strong&gt; –&amp;gt; Returns the path to the current Temporay folder.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;GetWindowsFolder&lt;/strong&gt; –&amp;gt; Returns the path to the current Windows Folder. Should be identical to %WinDir%.&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;CheckFileVersion (FileName, MinVersion)&lt;/strong&gt; –&amp;gt; Returns &lt;em&gt;True&lt;/em&gt; if the specified File has at least the specified version or greater. Returns &lt;em&gt;False&lt;/em&gt; if less or if the File can’t be found.&lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161265" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/vbscript/default.aspx">vbscript</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT+2012/default.aspx">MDT 2012</category></item><item><title>Publishing ZTICustomConfiguration.wsf – a script to solve some common tasks in MDT Deployments</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/18/publishing-zticustomconfiguration-wsf-a-script-to-solve-some-common-tasks-in-mdt-deployments.aspx</link><pubDate>Mon, 18 Jun 2012 13:28:00 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161244</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161244</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/18/publishing-zticustomconfiguration-wsf-a-script-to-solve-some-common-tasks-in-mdt-deployments.aspx#comments</comments><description>&lt;p&gt;There are a couple things, that are quite common in most deployments. Very often you need to delete a couple files, copy some folders, remove or update some registry keys, maybe update a XML or INI file etc. What a lot of people typically do is to write some kind of cleanup-script that runs at the end of their task sequence and removes unnecessary shortcuts, updates the registry to disable some auto-update features or whatever. Group Policy Preferences or Group Policies would probably often be a better choice for most of the scenarios, but lets skip them for a moment.&lt;/p&gt;  &lt;p&gt;What I would like to publish today is a generic script, that covers all these common tasks, and allows you to configure them in a simple to use xml file. It ties nicely into MDT with all their logging and error handling etc. Lets have a quick run-through on what it can do, and then look at some samples on how to use it. &lt;/p&gt;  &lt;h3&gt;What can it do?&lt;/h3&gt;  &lt;p&gt;- Create, copy, move and delete files and folders&lt;/p&gt;  &lt;p&gt;- Create, update, delete and read(!) registry settings including mounting of offline hives&lt;/p&gt;  &lt;p&gt;- Create, update, delete and read XML, INI and simple text files&lt;/p&gt;  &lt;p&gt;- Use MDT properties, environment variables and even VBScript functions as values, for path or file names, etc.&lt;/p&gt;  &lt;p&gt;- restrict execution based on rules&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h3&gt;How to use it?&lt;/h3&gt;  &lt;p&gt;- &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/89738" target="_blank"&gt;Download the script and xml file from CodePlex&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;- Drop them in the MDT scripts folder, or add them to your MDT scripts package source folder in ConfigMgr&lt;/p&gt;  &lt;p&gt;- Update the ZTICustomConfiguration.xml file according to your specific needs (see samples section in the file or this blog post for more information)&lt;/p&gt;  &lt;p&gt;- Test your changes (will publish a blog post about how to test this script without a full deployment pretty soon)&lt;/p&gt;  &lt;p&gt;- Optionally create a new list property within MDT and add all configuration sets, that you would like to have processed (&lt;a href="http://mdtcustomizations.codeplex.com/releases/view/89738" target="_blank"&gt;see sample customsettings.ini in the download&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;- Add a “Run command line” step to your Task Sequence and have it execute “cscript.exe %ScriptRoot%\ZTICustomConfiguration.wsf”&lt;/p&gt;  &lt;p&gt;- Refresh the Deployment Share / Update the ConfigMgr package&lt;/p&gt;  &lt;p&gt;- Execute the Task Sequence&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h3&gt;The configuration file&lt;/h3&gt;  &lt;p&gt;The execution of this script is driven by a xml file called “ZTICustomConfiguration.xml”. It should be placed in the MDT scripts folder, together with the script file ZTICustomConfiguration.wsf. This xml file can contain several so called “configuration sets”. And you can tell the script what set(s) shall be processed and in which order. So you could have one common configuration file for all your Task Sequences, but just process some of these configurations depending on the Task Sequence or other prereqs. There is one “Default” configuration set, that will be processed if nothing else is configured. &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h3&gt;The Rules&lt;/h3&gt;  &lt;p&gt;All actions at any level, from the whole configuration set down to an individual action, can be bound to rules. However, there is no necessity to specify rules, in this case everything will just be processed. Rules can be used to either include and/or exclude computers from processing something. And by combining those include and exclude rules, you will be able to cover even pretty complex scenarios. All rules rely on the evaluation of MDT properties. So mainly, if they contain a specific value, if they are empty, etc. We will see some samples in a minute. It might sound a bit limiting, but there are a couple hundred predefined MDT properties, ready to use and you can still define your own. And as the script allows you to read e.g. keys/values from the registry or a file into a MDT property, actually almost any information from a computer can be used for the evaluation.&lt;/p&gt;  &lt;p&gt;As a sample, to e.g. run a certain set of actions only for Win 7 64 Bit, you could specify the following Rules:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OSVersion&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Win7Client&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Architecture&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;X64&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;We could write the same by excluding the x86 architecture&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OSVersion&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Win7Client&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Architecture&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;X86&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;I guess you get the point. &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2F40AD2B.png" /&gt;&amp;nbsp; &lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Currently the script supports the following operators (see the ZTICustomConfiguration.xml file for complete Syntax)&lt;/p&gt;

&lt;p&gt;- equals&lt;/p&gt;

&lt;p&gt;- startswith&lt;/p&gt;

&lt;p&gt;- endswith&lt;/p&gt;

&lt;p&gt;- contains&lt;/p&gt;

&lt;p&gt;- notcontains&lt;/p&gt;

&lt;p&gt;- empty&lt;/p&gt;

&lt;p&gt;- notempty&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;Registry operations&lt;/h3&gt;

&lt;p&gt;Let’s start with some often used necessity and update the registry. As you might be aware, on default, a normal User, even a PowerUser can’t install Printer drivers on Windows 7 64 Bit. Yes, there is a GroupPolicy,&amp;nbsp; but hence, we want to fix this permanently during our deployment. This is a sample on what we would need to configure, to get this done:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="rem"&gt;&amp;lt;!-- Allow users to install drivers for the printers/scanners on Windows 7 64 Bit --&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OSVersion&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Win7Client&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Architecture&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;X64&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;&amp;lt;!-- Allow Devices Classes--&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_DWORD&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;00000001&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{48721B56-6795-11D2-B1A8-0080C72E74A2}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\3&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{49CE6AC8-6F86-11D2-B1E5-0080C72E74A2}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\4&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{4658EE7E-F050-11D1-B6BD-00C04FA372A7}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\5&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{4D36E971-E325-11CE-BFC1-08002BE10318}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DriverInstall\Restrictions\AllowUserDeviceClasses\6&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;{4D36E979-E325-11CE-BFC1-08002BE10318}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="rem"&gt;&amp;lt;!-- Switch off PointAndPrint restriction --&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint\Restricted&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_DWORD&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;00000000&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint\InForest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_DWORD&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;00000000&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint\TrustedServers&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_DWORD&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;00000000&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The same way, we created/updated a registry key or value, we can also delete one. But how about reading a value and storing it in a MDT property so it can be used later? Le’s say we want to read the &lt;b&gt;BIOSVersion&lt;/b&gt; from the registry into a custom MDT property called “&lt;b&gt;MyBIOSVersion&lt;/b&gt;”.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\SYSTEM\CurrentControlSet\Control\SystemInformation\BIOSVersion&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;read&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MyBIOSVersion&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;That’s it. Now we could use this value to process some other rules etc. But the values and names we use, don’t need to be static. At almost any place we can make use of environment variables, MDT properties, even vbscript functions if we want to. Let’s tattoo some deployment info to the registry:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="rem"&gt;&amp;lt;!-- tattoo only in the full OS --&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OSVersion&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;equals&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;WinPE&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Deployment Method&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%DeploymentMethod%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Deployment Type&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%DeploymentType%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Task Sequence ID&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%TaskSequenceID%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Task Sequence Name&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%TaskSequenceName%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Task Sequence Version&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%TaskSequenceVersion%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HKLM\Software\Microsoft\Deployment 4\Demo&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_SZ&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#Left(&amp;quot;%OSVersion%&amp;quot;,3)#&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;As you can see, we use a couple MDT properties and store their values in the Registry. In the last key, we store just the first three characters from the “OSVersion” property in the registry. Again, I guess you can imagine, that there will be a lot more advanced functions, that can be used with. This is not limited to values, you can use them in the path also.&lt;/p&gt;

&lt;p&gt;The final thing I want to show on registry operations, is the possibility to mount a hive first, before updating it. That’s a pretty common task if you want to make some changes on the default profile. Let’s see how we can load the default user registry and disable Desktop Cleanup&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="rem"&gt;&amp;lt;!-- Disable Desktop Cleanup in default User profile --&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;hive&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%USERPROFILE%\..\Default User\NTUSER.DAT&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\CleanupWiz\NoRun&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;REG_DWORD&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;1&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;hive&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;registry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The script will take care about loading and unloading the hive and redirecting the keys. &lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;File and Folder operations&lt;/h3&gt;

&lt;p&gt;The next pretty common thing is executing some file and/or folder operation like moving a folder from a network share to the local computer, copying some files to the default/administrator profile, removing some unwanted shortcuts. etc. Let’s create, copy, move and delete some files and folders&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;folder&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;folder&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderCopyTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;folder&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderCopyTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderMoveTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;copy&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;folder&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderMoveTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderDeleteTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;move&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;folder&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FolderDeleteTest&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileCopyTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileCopyTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileMoveTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;copy&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileMoveTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileDeleteTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;move&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileDeleteTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, it’s pretty easy to define what to do and again, you can make use of all Environment variables and MDT properties.&lt;/p&gt;

&lt;p&gt;Now to something more fancy. We can also create and edit files. Most easy thing is a simple text file. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FiletxtTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;First Line&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Second Line&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FiletxtTest.txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txt&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Third Line&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Current User: %Username%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;SystemRoot: %SystemRoot%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;writeline&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This will create a new textfile (overwrite=”true” will overwrite any existing file) and write a couple lines of text to it. Then we append a couple more lines with some dynamic content (overwrite=”false” will append the lines if the file exists already). &lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;INI files&lt;/h3&gt;

&lt;p&gt;OK, that wasn’t really that fancy. How about ini files?&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileIniTest.ini&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ini&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileIniTest.ini&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ini&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;EnvironmentVariables&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Username&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%Username%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;SystemRoot&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%SystemRoot%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Temp&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#Left(&amp;quot;%Temp%&amp;quot;,5)#&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Architecture&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            64 Bit
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ProgramFiles(x86)&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;empty&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Architecture&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            32 Bit
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;condition&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ProgramFiles(x86)&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;notempty&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;DeleteSection&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestKey1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;TestValue&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestKey2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;TestValue2&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestKey1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;read&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyINI1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;key&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestKey2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;read&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyINI2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileIniTest.ini&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ini&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;DeleteSection&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This looks a bit more complicated. So what does it do? Well, first it creates a new ini file. Then it updates this file with two new sections. A section called “EnvironmentVariables” and one called “DeleteSection”. It writes a couple values to both sections. For demonstration purposes I even added a rule when we write the key “Architecture”. So rules can really be applied at any level. In the part that creates the “DeleteSection” you will also see to entries, that read the value of a particular key and store it in a MDT property. The overwrite=”false” simulates the MDT default behaviour, that MT properties will only be set, if there isn’t already a value. But you can always overrule this by setting overwrite=”true”. Finally, the DeleteSection will be deleted again.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;So just ask &lt;a href="http://www.deploymentresearch.com/" target="_blank"&gt;Johan Arwidmark&lt;/a&gt; about changing the customsettings.ini at runtime &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2F40AD2B.png" /&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The code that does the modification of INI files originally comes from Michael Murgolo, a Microsoft consultant, and has been cannibalized a bit to fit into this script. But he has done all the heavy lifting. See the original Blog Post and script file at: &lt;a title="http://blogs.technet.com/b/deploymentguys/archive/2010/07/15/reading-and-modifying-ini-files-with-scripts.aspx" href="http://blogs.technet.com/b/deploymentguys/archive/2010/07/15/reading-and-modifying-ini-files-with-scripts.aspx" target="_blank"&gt;Reading and Modifying INI Files with Scripts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;XML Files&lt;/h3&gt;

&lt;p&gt;Finally, we can also make changes to an XML file. But not only changes, as shown before, we can also read from an XML file:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileXMLTest.xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;DemoRoot&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;DemoRoot&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileXMLTest.xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[/DemoRoot]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;occurence&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo1]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;110&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;operation&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test2&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute2&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test3&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;read&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyXML1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyXML2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyXML2&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#Left(&amp;quot;%MDTDemoPropertyXML2%&amp;quot;,4)#&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo3]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//DemoRoot]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;position&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;child&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;WithChild&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;AndSome&lt;/span&gt; &lt;span class="attr"&gt;attributes&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;AndSome&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;WithChild&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;position&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;firstchild&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Blablabla&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Woah, that’s a lot to read. Let’s go through it step by step. First we create a new xml file with a “DemoRoot” root element.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileXMLTest.xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;DemoRoot&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;DemoRoot&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The file will now look like this&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_59ACDE48.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_26DCD7D4.png" border="0" height="94" width="281" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we update this file we just created and want to add a new node to is. The &lt;a href="http://msdn.microsoft.com/en-us/library/ms256471" target="_blank"&gt;xpath&lt;/a&gt; defines where to create the new node. On default it will be created as a new child to the node defined by the &lt;a href="http://msdn.microsoft.com/en-us/library/ms256471" target="_blank"&gt;xpath&lt;/a&gt;. Optionally we can specify “position” attribute, to create it as “firstchild” or “append” or “prepend” it to that node.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;%Temp%\CustomConfigurationDemo\FileXMLTest.xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[/DemoRoot]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Demo3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Now the XML file will look like&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_45B34BB2.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_24BFD90B.png" border="0" height="121" width="309" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;OK, now we delete the “Demo1” node and update the “Demo2” node with a new value and some attributes&lt;/p&gt;

&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;occurence&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo1]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;110&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;operation&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test2&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute2&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Test3&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The xml file now looks like&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_0360336F.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_4D7B3E54.png" border="0" height="93" width="491" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Where is the “TestAttribute2” that we just added? Well, we immediately deleted it again. Does that make sense at all? Not really, but it’s fun &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2F40AD2B.png" /&gt;&lt;/p&gt;

&lt;p&gt;Let’s read a value now and re-use it&lt;/p&gt;

&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;read&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyXML1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;TestAttribute&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MDTDemoPropertyXML2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//Demo2]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MyAttribute&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#Left(&amp;quot;%MDTDemoPropertyXML2%&amp;quot;,4)#&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;attribute&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Here we store the value of the Node (&lt;b&gt;110&lt;/b&gt;) in the MDT property “&lt;b&gt;MDTDemoPropertyXML1&lt;/b&gt;” (what a stupid name). And the value of the attribute “&lt;b&gt;TestAttribute&lt;/b&gt;” (&lt;b&gt;Test2&lt;/b&gt;) into the MDT property “&lt;b&gt;MDTDemoPropertyXML2&lt;/b&gt;” (not getting better). Finally, we create a new attribute called “&lt;b&gt;MyAttribute&lt;/b&gt;” and add the first 4 characters of the MDT Property “&lt;b&gt;MDTDemoPropertyXML2&lt;/b&gt;” in it (&lt;b&gt;Test&lt;/b&gt;). Sounds confusing? Naaaah, let’s have a look on the xml:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_410D1B2B.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_0B282611.png" border="0" height="84" width="583" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;And a couple more steps that create, update, and delete some nodes. &lt;/p&gt;

&lt;p&gt;While that’s not really a good real-life example, it demonstrates the possibilities. A real-life sample could be to update the unattend.xml file to support an offline domain join (a detailed blog post about it will be published soon), which currently isn’t something that’s supported by MDT out of the box. So that’s the configuration that could be used for this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;      &lt;span class="rem"&gt;&amp;lt;!-- Updates the unattend.xml file for an offline domain join--&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt; &lt;span class="attr"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;{TODO:Path_to_Unattend.xml}\unattend.xml&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;update&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xml&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rule&lt;/span&gt; &lt;span class="attr"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;OfflineDomainJoinBlob&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;operator&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;notempty&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//settings[@pass=&amp;quot;specialize&amp;quot;]/component[@name=&amp;quot;Microsoft-Windows-UnattendedJoin&amp;quot;]/Identification]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;operation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[//settings[@pass=&amp;quot;specialize&amp;quot;]/component[@name=&amp;quot;Microsoft-Windows-UnattendedJoin&amp;quot;]]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xpath&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt; &lt;span class="attr"&gt;position&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;child&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Identification&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Provisioning&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;AccountData&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;%OfflineDomainJoinBlob%&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;AccountData&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Provisioning&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Identification&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;node&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;file&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;If the “&lt;b&gt;OfflineDomainJoinBlob&lt;/b&gt;” property has a value it will remove all the other domain/workgorup information and add some new nodes to the unattend.xml file, which will allow the computer to be joined to the domain, while not being connected to the network. As said, that’s something I will publish pretty soon.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;Integrating in MDT&lt;/h3&gt;

&lt;p&gt;Normally all you need to execute this script is putting the script and the XML file in the MDT scripts folder (MDT scripts package in ConfigMgr). And then add a “Run Command Line” step to your task sequence, that executes “cscript.exe %ScriptRoot%\ZTICustomConfiguration.wsf”. Where you add the step, depends on the actions, that are being executed. If it’s some kind of clean-up script, it’s probably best to put it somewhere at the end. If it updates the unattend.xml, it should probably be somehwere before the “Configure” step, etc. Due to the Rules, you can also call it several times during the Task Sequence. You would then just make sure, that your steps only run at the appropriate phase.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/image_30B1A372.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" src="http://myitforum.com/cs2/blogs/maikkoster/image_thumb_45728A4F.png" border="0" height="488" width="628" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Optionally, you can specify what configuration sets shall be processed. To do this, you need to add a new list property to MDT. You do this by adding the following to your customsettings.ini&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    [Settings]
    Priority=Init,...
    Properties=ConfigurationSet(*)

    [Init]
    ConfigurationSet001=Demo&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Configuration(*) creates a new MDT list property. And then you simply add all the configuration sets you would like to have processed. If you don’t specify one, the Configuration Set “Default” will be processed if available.&lt;/p&gt;

&lt;p&gt;The script will also accept these additional properties:&lt;/p&gt;

&lt;p&gt;- CCSkipFolder –&amp;gt; Set to “YES” to skip all folder jobs&lt;/p&gt;

&lt;p&gt;- CCSkipFile –&amp;gt; Set to “YES” to skip all file jobs&lt;/p&gt;

&lt;p&gt;- CCSkipRegistry –&amp;gt; Set to “YES” to skip all registry jobs&lt;/p&gt;

&lt;p&gt;-- CCSkipLoadHive –&amp;gt; Set to “YES” to skip loading of additional registry hives&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;What about a FrontEnd?&lt;/h3&gt;

&lt;p&gt;Why do I need to fiddle around with an XML file? Why isn’t there a nifty frontend for this?&lt;/p&gt;

&lt;p&gt;Good question, as I simply haven’t found the time yet to create one and it would probably look awful. So if there is anyone interested in tackling this task, he/she would get my full support on it. So feel free to contact me or just get used to XMLNotepad, Notepad++ or any other nice text-editor with XML capabilities. &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_2F40AD2B.png" /&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;I still consider this script Beta, even if I use it already since quite some time. So please go to &lt;a href="http://mdtcustomizations.codeplex.com/releases/view/89738" target="_blank"&gt;CodePlex and download the files&lt;/a&gt;. Have a look on the supplied xml file, which is used as some initial documentation as well. Implement and test your changes. And give it a try. If something doesn’t work as expected or you have some good ideas on how to extend this solution or make it a bit more comfortable, just get back to me. The next blog post will be about testing and troubleshooting this script and the xml file. &lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161244" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Custom+Scripts/default.aspx">Custom Scripts</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/vbscript/default.aspx">vbscript</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/ConfigMgr/default.aspx">ConfigMgr</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/XML/default.aspx">XML</category></item><item><title>Searching for Drivers in MDT</title><link>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/05/searching-for-drivers-in-mdt.aspx</link><pubDate>Tue, 05 Jun 2012 14:40:12 GMT</pubDate><guid isPermaLink="false">8e8f7986-475c-475d-bdc9-a1b3a63b955b:161218</guid><dc:creator>maikkoster</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://myitforum.com/cs2/blogs/maikkoster/rsscomments.aspx?PostID=161218</wfw:commentRss><comments>http://myitforum.com/cs2/blogs/maikkoster/archive/2012/06/05/searching-for-drivers-in-mdt.aspx#comments</comments><description>&lt;p&gt;Today I had an interesting question. Someone wanted to be able to see all the PnP IDs of the imported drivers so he could easily check if a specific device was already supported. While this information is available in the properties of each driver, its not shown in a column of the workbench. And even if it would be available as a column, it wouldn’t be easy to read as a single driver typically supports a whole bunch of PNP IDs.&lt;/p&gt;  &lt;p&gt;Now as everything in MDT is available via PowerShell, it should be possible to get this information. Let’s dig through this a bit.&lt;/p&gt;  &lt;p&gt;First we open a PowerShell prompt, load the MTD Module and mount the Deployment Share&lt;/p&gt;  &lt;pre class="csharpcode"&gt;Add-PSSnapIn Microsoft.BDD.PSSnapIn 
New-PSDrive -Name &lt;span class="str"&gt;&amp;quot;MDT&amp;quot;&lt;/span&gt; -PSProvider MDTProvider -Root &lt;span class="str"&gt;&amp;quot;C:\MyDeploymentShare&amp;quot;&lt;/span&gt; &lt;/pre&gt;





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

&lt;p&gt;The Drivers are found in the “Out-of-Box Drivers” folder on the deployment share. Let’s just list them for now. The R&lt;strong&gt;ecurse&lt;/strong&gt; parameter will just give us all drivers in all subfolders as well.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ChildItem -path &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers&amp;quot;&lt;/span&gt; –Recurse&lt;/pre&gt;
&lt;span class="str"&gt;
  &lt;br /&gt;&lt;/span&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4bde2a2a_203272E9.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML4bde2a2a" border="0" alt="SNAGHTML4bde2a2a" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4bde2a2a_thumb_423ACEAF.png" width="751" height="344" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as you can see, I’ve only imported a few drivers into the deployment share for demonstration purposes. The result, is also not really helpful, as it returns a list of Driver Names with version and also all Folder names. To get rid of the folders and only list the Drivers, we could add a filter that removes them like&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ChildItem -path &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers&amp;quot;&lt;/span&gt; –Recurse | &lt;span class="kwrd"&gt;where&lt;/span&gt; {!$_.PSIsContainer}&lt;/pre&gt;

&lt;p&gt;But we want it functional for now, not pretty &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://myitforum.com/cs2/blogs/maikkoster/wlEmoticon-winkingsmile_4FFCEEDD.png" /&gt;. A single driver might cover different models or maybe MDT picked the wrong name etc. Let’s have a look on the properties of one of the Driver 

  &lt;br /&gt;&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ItemProperty &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers\Intel Net E1K5132.INF 11.6.92.0&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be02588_21A36930.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML4be02588" border="0" alt="SNAGHTML4be02588" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be02588_thumb_589D4769.png" width="751" height="346" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, that’s a bit better. We see properties like “&lt;em&gt;Manufacturer&lt;/em&gt;”, “&lt;em&gt;Version&lt;/em&gt;”, “&lt;em&gt;Platform&lt;/em&gt;”, “&lt;em&gt;Class&lt;/em&gt;”, “&lt;em&gt;OSVersion&lt;/em&gt;” and “&lt;em&gt;PNPId&lt;/em&gt;”. Most of them are also shown in the Workbench, but not all. Now back to the first query and return the result as a table with some more properties (Yeah, still with folders, ignore them for now)&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ChildItem -Path &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers&amp;quot;&lt;/span&gt; -Recurse | Format-Table -Property Manufacturer, Name, Version, PNPId&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be479814_336FD730.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML4be47981[4]" border="0" alt="SNAGHTML4be47981[4]" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be479814_thumb_65F334A2.png" width="753" height="357" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hm, getting better, but still not good. Let’s filter for all Intel Network Drivers and remove a couple columns&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ChildItem -Path &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers&amp;quot;&lt;/span&gt; -Recurse | Where {$_.Class -eq &lt;span class="str"&gt;&amp;quot;Net&amp;quot;&lt;/span&gt; -and $_.Manufacturer -like &lt;span class="str"&gt;&amp;quot;*Intel*&amp;quot;&lt;/span&gt;} | Format-Table -Property Name, PNPId&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be5315b_26F18E3A.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML4be5315b" border="0" alt="SNAGHTML4be5315b" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be5315b_thumb_077F37A7.png" width="756" height="227" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, and the same way, we can now filter for a specific device. Let’s say an &lt;strong&gt;Intel 82567LM-3 Gigabit Adapter&lt;/strong&gt; with Device ID “&lt;strong&gt;PCI\VEN_8086&amp;amp;DEV_10DE&amp;amp;SUBSYS_10DE8086&lt;/strong&gt;”.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Get-ChildItem -Path &lt;span class="str"&gt;&amp;quot;MDT:\Out-of-Box Drivers&amp;quot;&lt;/span&gt; -Recurse | &lt;span class="kwrd"&gt;where&lt;/span&gt; {$_.PNPId -like &lt;span class="str"&gt;&amp;quot;*PCI\VEN_8086&amp;amp;DEV_10DE&amp;amp;SUBSYS_10DE8086&amp;quot;&lt;/span&gt;*} | ft -Property Name, Platform, OSVersion&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be7697a_1B882E63.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SNAGHTML4be7697a" border="0" alt="SNAGHTML4be7697a" src="http://myitforum.com/cs2/blogs/maikkoster/SNAGHTML4be7697a_thumb_71C4B36F.png" width="756" height="183" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And as we see, we already have a couple drivers imported that will support this device on different Platforms and OS Versions.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;There is still some room for improvement. We could encapsulate this in a custom function, maybe also optionally supply a selection profile etc. But that has to wait until I find some sparetime (or a PowerShell magician who probably codes this in a few minutes). Now back to some coding on the Web FrontEnd, the next release is more than overdue but the monitoring grew a bit more than expected. &lt;/p&gt;&lt;img src="http://myitforum.com/cs2/aggbug.aspx?PostID=161218" width="1" height="1"&gt;</description><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/MDT/default.aspx">MDT</category><category domain="http://myitforum.com/cs2/blogs/maikkoster/archive/tags/Powershell/default.aspx">Powershell</category></item></channel></rss>