Graeme Bray

Real World Automation and Deployment

MDT Wizard Panes – Watch your Case

leave a comment »

Just a quick post..

I am in the process of setting up my home lab on some servers that I have here.
– 1 PowerEdge 860
– 1 PowerEdge 2950

Both support 2012 R2. Hyper-V 2012 R2 is running on the 2950.

I set up a MDT Deployment Share on the 860. I tried to use the Hydration Kit for SC2012 that Johan has provided, but I wanted some specific customizations (and no viamonstra). I also wasn’t sure how to set it up to point at a different Hyper-V Host.

I went with what I know. I added a new Wizard Pane to my MDT (DeployWiz_AppProfile.xml) and I set it up so that I could have one task sequence to run each different type of Build that I wanted.

<Wizard>
	<Global>
	</Global>
	<Pane id="ServerRole" title="Server Role">
	<Body><![CDATA[<H1>Select an application profile for this server</H1>
		<div id="myMenu" Class="TreeList">
		
		<table style="width:100%;">
			<tr>
				<td colspan="2">
					<p style="color:DarkBlue; font-size:16px; font-weight:bold; font-family:Veranda, Arial, Helvetica, sans-serif;">
						<img src="MinusIcon1.png" /> <img src="FolderIcon.png" />Generic Builds
					</p>
				</td>
			</tr>
			<tr>
				<td style="width:15;">
				</td>
				<td style="width:500;">
					<input type="radio" name="GEBConfig" value="GEBBase" checked>Base Server <br />
					<input type="radio" name="GEBConfig" value="GEBWeb">Web Server <br />
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<p style="color:DarkBlue; font-size:16px; font-weight:bold; font-family:Veranda, Arial, Helvetica, sans-serif;">
						<img src="MinusIcon1.png" /> <img src="FolderIcon.png" />Infrastructure Servers
					</p>
				</td>
			</tr>
			<tr>
				<td style="width:15;">
				</td>
				<td style="width:500;">
					<input type="radio" name="GEBConfig" value="GEBDC">Domain Controller <br />
					<input type="radio" name="GEBConfig" value="GEBWSUS">WSUS Server <br />
					<input type="radio" name="GEBConfig" value="GEBMDT">MDT Server <br />
				</td>
			</tr>
		</table>]]>
	</Body>
	<Condition><![CDATA[UCase(Property("SkipGEBSettings"))<>"YES" and Property("DeploymentType")<>"REPLACE" and Property("DeploymentType")<>"UPGRADE"]]></Condition>
	</Pane>
</Wizard>

I thought I was done. It looked good. I booted my DC01 VM. I got a strange script error after I entered my credentials in MDT.

Script Error

I looked at the Wizard.hta pane in Notepad++. I saw these lines of code:

		For each refItem in oReference.SelectSingleNode("//Wizard/Pane").ChildNodes
			item.AppendChild refItem.CloneNode(true)
		Next

Odd. I hit F8 to open the CMD window.

I navigated to the logs
cd\
cd MININT\SMSOSD\OSDLogs
Wizard.log

Command Prompt - WinPE

At the bottom of the log, it referenced my closing tag did not match my starting tag.

Error Line
(FYI, I am using CMTrace that does this highlighting. If you don’t have it, I highly recommend it – CM Trace)

I opened my DeployWiz_AppProfile.xml file. I checked my Body tags.

  • Line 5
    <Body>
  • Line 41 –
    </body>

Moral of the story – be sure to verify that your tags are at the proper case.

Written by Graeme Bray

June 1, 2014 at 10:14 pm

Posted in MDT

Tagged with ,

Why you should revisit your code

leave a comment »

I recently had a script sent to me. This script was originally written at the end of 2011, edited in early 2012. Per the comment block at the top the script, it was version 5. It was a good script. It did what was needed for the end users.

It’s now 2014. We’ve upgraded the domain to Forest and Domain Functional Levels of 2008 R2. We’ve upgraded all of the DC’s to 2008 R2 or greater. We don’t need to use the Quest AD CMDlets anymore. They’re deprecated (in my eyes).

Here is the majority of the code snippet (I’ve edited out company information).

#Checks to see if the Quest Add on is installed.  If not installed, Installs it.
$snap_ins = Get-PSSnapin -Name Quest.ActiveRoles.ADManagement

if (!$snap_ins)
{
	Add-PSSnapin Quest.ActiveRoles.ADManagement       
}
#Loads the variable with the data from the Active Directory
$serviceaccounts = Get-QADUser -SizeLimit 0 -SearchRoot 'mydomain.local/MyOU/Accounts/Users'

#Recursively loops through every entry in $serviceaccounts variable
foreach ($account in $serviceaccounts)
{
    $contains = 0
    
    #Stores all the information about the memberships of the service account into the $memberdetails variable
    $memberdetails = Get-QADmemberof $account

    #Recursively loops through each membership per service account
    foreach ($group in $memberdetails)
    {
        #If there exists a membership that starts with "SEC", sets the flag to 1
    	if (($group.Name.StartsWith("SEC")))
    	{	            
    		$Contains = 1                	
    	}      
    }
        #If User has/hasn't a Membership starting with "SEC" then output the correct message
        if ($contains -eq 1)
        {
            write-host $account.name "has the group"
            $yes = $account.name | Out-File -Append $containspath
            $contains = 0
        }
        else
        {
            Write-Host $account.name "Does not have the group" 
            $no = $account.name | Out-File -Append $nocontainspath
        }
    #Resets the variable
    $contains = 0       
}

This was good, in 2011. We didn’t have the ability to run the AD cmdlets. We didn’t have Powershell 3.0, or 4.0, or even 5.0 (Preview – Don’t run in production, duh).

There are approximately 2000 users in this OU location that we were needing to check to see if they had any of a specific group type.

I was asked a question (at this point, I don’t remember what), but I was told that the script “works.” I looked at it and said, I’m going to re-write this. For fun, I took what was said at TechEd, to heart. I wanted to remove the Write-Host, I wanted to improve the run speed, and I wanted to make this script so it could be customized a little easier.

First, I ran Measure-Command on the entire script. Here are the results:
Old Script - Run Time
Yikes. Almost 15 minutes. That’s running sequentially, writing output to the screen. Ick.

I decided, lets re-write the script. I didn’t do it *all* on my own, but I did realize that you cannot do a -like, or -match, or -anything with a wildcard for the MemberOf property of a Get-ADUser.

<#
.SYNOPSIS
   This script will output two sets of data - one providing users in a group, the other providing users *not* in a group.
.DESCRIPTION
   This script provides the ability to take 3 parameters (Domain, GroupName) and will search in
   the specified Domain for that group.  If a SearchBase is specified, it will use that as a modifier and significantly
   speed up the script as you are searching a specific OU.

   This script will output to two different files, each appended with a specific date.

   This script can be modified to suit your specific needs.
.EXAMPLE
   Get-GroupInformation
.EXAMPLE
   Get-GroupInformation -Domain mydomain.local -GroupName SEC-*
.OUTPUTS
   Script will output 2 files to:
    "C:\Admin\Scripts\Audit_$GroupName_Security_Group\
#>
function Get-GroupInformation
{
    [CmdletBinding(DefaultParameterSetName='Parameter Set 1', 
                  SupportsShouldProcess=$true, 
                  PositionalBinding=$false,
                  HelpUri = 'http://www.microsoft.com/',
                  ConfirmImpact='Medium')]
    [OutputType([String])]
    Param
    (
        # Domain - ex: mydomain.local
        [Parameter(ParameterSetName='Domain name')]
        [string]
        $Domain = 'mydomain.local',

        # GroupName - ex: GRP-*
        [Parameter(ParameterSetName='Group name')]
        [string]
        $GroupName = 'SEC-*'
    )

    Begin
    {
        Write-Verbose 'Defining/creating variables'
        $SearchBase = 'OU=Users,OU=Accounts,OU=MyOu,DC=MyDomain,DC=Local'
        $varUserArray = @()

    }
    Process
    {
        Write-Verbose 'Getting list of Users from Active Directory'
        try
        {
            $ADQuery = Get-ADUser -Server $Domain -Properties memberof -Filter * -SearchBase $SearchBase
        }
        catch [System.Net.WebException],[System.Exception]
        {
            Write-Error 'AD Query returned no users.'
        }
        
        Write-Verbose 'Looking through users, creating array with UserName and Groups'
        foreach ($User in $ADQuery) {
            $Groups = $User.memberof -join ';'
            $varUserArray += New-Object psObject -Property @{'User'=$User.name;'Groups'= $Groups}
        } #End ForEach User
    }
    End
    {
        Write-Verbose 'Sorting users and outputting to appropriate Output File'
        $Member = $varUserArray | Where-Object {($_.groups -match $GroupName) } | Select-Object User | Out-File D:\Workspace\Graeme\Output\Member.txt -Force
        $NonMember = $varUserArray| Where-Object {!($_.groups -match $GroupName) } | Select-Object User | Out-File D:\Workspace\Graeme\Output\NonMember.txt -Force
    }
}

Get-GroupInformation

This provided the exact same results. Bingo. This script took….
New Script - Run Time

4 Seconds!

Wow. Plus, with the new script you get some of the standard cmdlet options (Verbose for one), and it’s more easily edited.

*Note* – It is very possible that the script may not work correctly. I haven’t fully tested, but I was so blown away by the time results, that it had to be said…and posted.

Written by Graeme Bray

May 30, 2014 at 4:59 am

Posted in PowerShell

Tagged with

MDT – Server 2012 R2 Pre-Capture Disk Cleanup

leave a comment »

As a result of going to TechEd, I learned a few disk cleaning techniques from Mikael Nystrom.  One of these was to run the following command during the Build & Capture Task Sequence.  This adds about 15 minutes on to the build time, but it can save (in my case) 700MB of space.  It may not end up being much, but in the server world, it can mean a lot.  (Disclosure, I have only tested on Server 2012 R2 U1)

Command: (Run Elevated) DISM.exe /online /cleanup-image /StartComponentCleanup /ResetBase

Used Space Before:

Image

 

Used Space After:

Image

 

I will shamelessly admit that I have taken one script from Mikael and edited them for use in my environment.  After all, why re-create something when there are already working examples?  I do leave all of the credit at the top of the script, so no issues there.

<job id=”Config-Server2012DiskCleanup”>
<script language=”VBScript” src=”..\..\scripts\ZTIUtility.vbs”/>
<script language=”VBScript”>
‘//—————————————————————————-
‘// Purpose: Used to Configure and reset the Base for Windows Server 2012 R2
‘// Usage: cscript Config-Server2012DiskCleanup.wsf [/debug:true]
‘// Version: 1.0 – 7 Sep 2011 – Mikael Nystrom
‘//
‘// This script is provided “AS IS” with no warranties, confers no rights and 
‘// is not supported by the authors or Deployment Artist. 
‘//
‘//—————————————————————————-
‘//—————————————————————————-
‘// Global constant and variable declarations
‘//—————————————————————————-
Option Explicit
Dim iRetVal
‘//—————————————————————————-
‘// End declarations
‘//—————————————————————————-
‘//—————————————————————————-
‘// Main routine
‘//—————————————————————————-
On Error Resume Next
iRetVal = ZTIProcess
ProcessResults iRetVal
On Error Goto 0
‘//—————————————————————————
‘//
‘// Function: ZTIProcess()
‘//
‘// Input: None
‘// 
‘// Return: Success – 0
‘// Failure – non-zero
‘//
‘// Purpose: Perform main ZTI processing
‘// 
‘//—————————————————————————
Function ZTIProcess()
Dim sCommand
Dim sConfigname
sConfigName = “Config-Server 2012 Disk Cleanup”
oLogging.CreateEntry sConfigName & “: Starting ” & sConfigName, LogTypeInfo

‘//Run a command
sCommand = “dism.exe /online /cleanup-image /startcomponentcleanup /resetbase”
oLogging.CreateEntry sConfigName & “: Running ” & sCommand, LogTypeInfo
iRetVal = oUtility.RunwithHeartbeat(sCommand)
oLogging.CreateEntry sConfigName & “: Return code from command = ” & iRetVal, LogTypeInfo

oLogging.CreateEntry sConfigName & “: Finished ” & sConfigName, LogTypeInfo
End Function

</script>
</job>

I will find a place to post the .wsf file online, but in the mean time, there it is

Written by Graeme Bray

May 20, 2014 at 8:01 pm

Posted in Uncategorized

Tagged with

MDT – State Restore for Multiple Task Sequences

leave a comment »

As a Windows Engineer, one of the most difficult things about maintaining my deployments is consistency.  I maintain our legacy builds (Server 2003 – Std/Ent, x86/x64) as well as our current builds (2008 R2 Std/Ent, 2012 R2 Std).  My biggest problem is ensuring that our builds are the same no matter the OS (from 2008 through 2012 – who really cares about 2003 at this point).  One thing that Microsoft has done with MDT and Windows Server in general is make the OS Roles/Features and compatibility similar.

Task sequences are the lifeblood of the MDT Build Process. Consistency between the MDT Builds for each OS version (for example, 2008 R2 Std/Ent, or 2012 R2 Std) should be paramount in the Windows Server world. The average Windows Admin should strive to have an OS that looks identical each time it is deployed, no matter if it is Development, Production, or QA. This can be accomplished by building a State Restore phase of the that can be copied from a main task sequence to each subsequent one. Building this so that you can copy the entire State Restore phase will greatly reduce the time you spend configuring your task sequences.

To do this, each different OS you build will need to have a group created for the step you would like to perform (for example, a Role installation). You would then create a subgroup with the specific label of the OS (Ex: Server 2008 R2, Server 2012 R2) with a WQL Query.

Here’s an example of my Web (IIS) group:

Image

And here is my WQL (WMI) query for Server 2008 R2:

Image

The two queries that I use are:

SELECT * FROM Win32_OperatingSystem WHERE Name LIKE “%Windows Server 2008 R2%”

SELECT * FROM Win32_OperatingSystem WHERE Name LIKE “%Windows Server 2012%”

If you want to get more specific than just all 2012, then you can specify “%Windows Server 2012 R2%”.  Personally, my company never plans to deploy Server 2012 (And why would you at this point?  Its like Windows 8, why not skip right to 8.1?

Once I’ve got my folder templates created, I copy them to whatever place I need them, whether its my Role installs or specific applications that are only needed on 2008 or 2012.  This works very well to group items so you can see at first glance what is being installed for each OS.

Once this is complete, I select the “State Restore” phase grouping and right click to “Copy”.  I’ll open each of my other two task sequences (after testing the first of course) and remove my old State Restore and Paste the new one.

Voila, I never have to compare Task Sequences, nor make my updates more than once.

Work smarter, not harder, especially to maintain consistency.

Written by Graeme Bray

April 25, 2014 at 1:11 am

Posted in MDT

Tagged with

Unable to mount the WIM/DISM was unable to set the system root

leave a comment »

My company has recently started to deploy Server 2012 R2.  Before we could do this, the security team had to develop the policies to apply to the systems before we were allowed to do so.  Naturally, this leads to some times where we have to troubleshoot issues due to restrictive policies.  I started the process to deploy a new MDT server to replace one of my 2008 MDT systems that hosts WDS to attempt to get past the issue documented here.

I built my MDT Server, with 2013, ADK, and copied my old Deployment Share over to get the process started.  I updated my bootstrap.ini file to show the proper server name and tried to build a new boot image.  *BAM!*  I was hit with an error as soon as it started.

Unable to mount the wim, so the update process cannot continue.

Image

 

I looked and searched high and low for the cause.  I removed policies, thinking I knew what the issue was.  I *couldn’t* find it.  I took a break and came back to it by adding policies one at a time to see what broken my process.

I was able to get past this issue by changing the following setting:

Computer Configuration/Policies/Windows Settings/Security Settings/Local Policies/User Rights Assignments

  • Backup Files and Directories – Add Administrators back in
  • Restore Files and Directories – Add Administrators back in

These two policy settings had only Backup Operators as to provide for the least rights possible.

This should alleviate the first issue.


 

Once I fixed this issue, I (re-applied group policy, logged out/in) attempted to re-build my WIM file.  I was hit by the next errors.

  • DISM Imaging Servicing Utility has stopped working
  • DISM was unable to set the system root (target path) for the Windows PE image, so the update process cannot continue.
    • Exit Code = -1073741819
    • DISM /Set-TargetPath failed, rc = -1073741819

Image

Image

 

Well…crap.  Back to looking.  I had an idea what the issue may be by looking at my event logs.  In my (fast scrolling, due to advanced auditing) security logs, I was able to see some Task Category entries for Process Creation.  I can’t claim to know what all of this means, but I did see that it was attempting to get a new Token for WIM build.

Process Information:
New Process ID: 0x1010
New Process Name: C:\Windows\System32\cmd.exe
Token Elevation Type: TokenElevationTypeFull (2)
Creator Process ID: 0x918
Process Command Line:

Token Elevation Type indicates the type of token that was assigned to the new process in accordance with User Account Control policy.

Type 1 is a full token with no privileges removed or groups disabled. A full token is only used if User Account Control is disabled or if the user is the built-in Administrator account or a service account.

Type 2 is an elevated token with no privileges removed or groups disabled. An elevated token is used when User Account Control is enabled and the user chooses to start the program using Run as administrator. An elevated token is also used when an application is configured to always require administrative privilege or to always require maximum privilege, and the user is a member of the Administrators group.

Type 3 is a limited token with administrative privileges removed and administrative groups disabled. The limited token is used when User Account Control is enabled, the application does not require administrative privilege, and the user does not choose to start the program using Run as administrator.

Tokens Eh?  I remember seeing a policy for that!

Computer Configuration/Policies/Windows Settings/Security Settings/Local Policies/User Rights Assignments

  • Create Token Object

I added Administrators, applied policy, logged out/in.  No dice.  I read a little more.

 

Computer Configuration/Policies/Windows Settings/Security Settings/Local Policies/User Rights Assignments

  • Create global objects – Add Administrators.

Bingo! Our setting was LOCAL SERVICE, NETWORK SERVICE only.  I adjusted this setting, I was able to build my WIM’s successfully.

I hope this blog post is useful for someone else!

 

 

Written by Graeme Bray

March 26, 2014 at 2:21 pm

Posted in MDT

Tagged with

MDT 2013 – Roles and Features

leave a comment »

This post focuses mainly on 2008 R2 (Std/Ent) and 2012 R2 as the OS Roles and Features are relatively similar and most software works between each OS.  The OS Roles and Features install via MDT is a nice addition, but it does have some caveats.  You should be sure to select *only* the roles you need.

For Example:

IIS – You want to install the following roles:

  • Static Content
  • Default Document
  • Directory Browsing
  • HTTP Errors

If you select Common HTTP Features and only the features listed above, it will install all features.

Image

 

Secondly, if you have to install a feature that has dependencies, the Roles and Features section will not do that for you.  If you are installing the WSUS Role via the Task Sequence, you will need to select the IIS Features that it needs. (For Reference).

Be sure to select the proper OS (2008 R2, 2012 R2, 7, 8.1, etc)

Written by Graeme Bray

March 23, 2014 at 5:12 pm

Posted in MDT

Tagged with

Installing the SolarFlare Drivers and Software

leave a comment »

My company has recently purchased some SolarFlare 10GbE Network Adapters.  For the most part, these cards provide a basic install like most other utilities (Dell Drivers, VMWare Tools, McAfee, etc..)

I did run into a couple of caveats when installing the software.

  1. Do not extract the install package.
  2. The return code appears to be 18.  I’ve done one test and gotten a RC of 19.
  3. The install will force a reboot if not specified. (Include REBOOT=Suppress in your install line)

Caveat #1

The driver file to download is named: SF-107785-LS-4_Solarflare_Windows_x64_64-bit_Driver_Package.exe

Rename this file to setup.exe rather than extracting.  If you extract, you get the following error:

Image

Caveat #2

I added the following to my code: (iRetVal = 18) or (iRetVal = 19). This allowed the install to complete successfully.  I am following up with SolarFlare to find out why.  I will update with any response.

Note #1

I added a WQL query for my Group in MDT to only install this software if the HardWareID of PCI\VEN_1924% was in the system.  This will check WMI to see if the device is in the system.  This DeviceID is specific for the SolarFlare SFN6122F.

Query: SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE ‘PCI\\VEN_1924%’

Image

Note #2

I did not write the code to include any architecture checks as these cards are only going to run under a 64-bit OS.  If it is, you can add a If oEnvironment.Item(“Architecture”) = “X64″ then section.

Recommendation #1

As a recommendation, when installing any software that touches the network stack (Broadcom BACS, SolarFlare, VMTools), copy these to a temp folder and install from there.  The software installs better when its local with less issues.

Now…the Code!

A basic flow of the code…

  • Set destination folder to C:\temp
  • Create folder if it doesn’t exist
  • Copy Source folder to C:\temp\Source
  • Run setup.exe to install all features (SolarFlare User Guide – Page 123 for the ADDLOCAL info)
  • Sleep for a few seconds, just in case the install hasn’t finished
  • Cleanup
  • Be sure to include a reboot step in your Task Sequence.
<job id="Install-SolarFlareSoftware">
<script language="VBScript" src="..\..\scripts\ZTIUtility.vbs"/>
<script language="VBScript"> 

'//----------------------------------------------------------------------------
'// Solution: Hydration
'// Purpose: Used to install the SolarFlare Drivers and Software
'// Usage: cscript Install-SolarFlareSoftware.wsf [/debug:true]
'// Version: 1.0 - 27 May 2011 - Mikael Nystrom
'//
'// This script is provided "AS IS" with no warranties, confers no rights and 
'// is not supported by the authors or Deployment Artist. 
'//
'//----------------------------------------------------------------------------

'//----------------------------------------------------------------------------
'// Global constant and variable declarations
'//---------------------------------------------------------------------------- 

Option Explicit 

Dim iRetVal 
Dim sApplicationName

'//----------------------------------------------------------------------------
'// End declarations
'//---------------------------------------------------------------------------- 

'//----------------------------------------------------------------------------
'// Main routine
'//---------------------------------------------------------------------------- 

On Error Resume Next
iRetVal = ZTIProcess
ProcessResults iRetVal
On Error Goto 0 

'//---------------------------------------------------------------------------
'//
'// Function: ZTIProcess()
'//
'// Input: None
'// 
'// Return: Success - 0
'// Failure - non-zero
'//
'// Purpose: Perform main ZTI processing
'// 
'//---------------------------------------------------------------------------
Function ZTIProcess() 
	Dim sSourceDir, sFile
	Dim sDestFolder

	sApplicationName = "SolarFlare Software"
	
	oLogging.CreateEntry "Install-" & sApplicationName & ": Starting " & sApplicationName & " installation", LogTypeInfo
	
	'//Set Destination Folder
	sDestFolder = "c:\temp\"
	
	'//Set Source Install Directory
	sSourceDir = oUtility.ScriptDir
	sSourceDir = sSourceDir & "\Source"
	
	'//Check that folder exists, if not, create it.
	oLogging.CreateEntry "Install-" & sApplicationName & ": Check that " & sDestFolder & " exists.", LogTypeInfo
	if not oFSO.FolderExists (sDestFolder) then
		oFSO.CreateFolder sDestFolder
	End If
	
	'//Copy folder from MDT share to C:\Temp
	oLogging.CreateEntry "Install-" & sApplicationName & ": Copy from  " & sSourceDir & " to " & sDestFolder, LogTypeInfo
	oFSO.CopyFolder sSourceDir, sDestFolder
	
	'//Sleep for 2 seconds to allow copy to finish
	wscript.sleep 2000
	
	sFile = sDestFolder & "Source\setup.exe"
	
	'// Check if file/folder exists
	If not oFSO.FileExists(sFile) then
		oLogging.CreateEntry "Install-" & sApplicationName & ": " & sFile & " was not found, unable to install " & sApplicationName & "", LogTypeError
		ZTIProcess = Failure
		Exit Function
	End if
		
	'// Create log entry to show file being run
	oLogging.CreateEntry "" & sFile & " /quiet /Install ADDLOCAL=CoreDrivers,OptimizeTCP,SNMP,NetworkAdapterManager,CommandLineTools,Launcher REBOOT=Suppress", LogTypeInfo
	
	iRetVal = oUtility.RunWithHeartbeat("" & sFile & " /quiet /Install ADDLOCAL=CoreDrivers,OptimizeTCP,SNMP,NetworkAdapterManager,CommandLineTools,Launcher REBOOT=Suppress")
	
	if (iRetVal = 0) or (iRetVal = 3010) or (iRetVal = 18) or (iRetVal = 19) then
		ZTIProcess = Success 
	Else 
		ZTIProcess = Failure
	End If
	
	wscript.sleep 2000
	
	'// Disable Zone Checks
	oEnv("SEE_MASK_NOZONECHECKS") = 1 

	'//Folder Cleanup
	oFSO.DeleteFolder sDestFolder & "Source"
	
	oLogging.CreateEntry "Install-" & sApplicationName & ": Return code from command = " & iRetVal, LogTypeInfo
	oLogging.CreateEntry "Install-" & sApplicationName & ": Finished " & sApplicationName & " installation", LogTypeInfo
	
End Function 

</script>
</job>

I’ll try to update the post to show the code better, but you get the gist of it.

As always, thanks to Johan (http://www.deploymentresearch.com) and Mikael (http://www.deploymentbunny.com) for providing the base VBScript to edit.

Helpful Links: Microsoft WMI Code Creator

Written by Graeme Bray

March 23, 2014 at 5:33 am

Posted in MDT

Follow

Get every new post delivered to your Inbox.