cMDT.psm1
enum Ensure { Absent Present } [DscResource()] class cMDTApplication { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Name [DscProperty(Key)] [string]$ShortName [DscProperty(Mandatory)] [string]$Version [DscProperty(Mandatory)] [string]$Publisher [DscProperty(Mandatory)] [string]$Language [DscProperty(Mandatory)] [string]$CommandLine [DscProperty(Mandatory)] [string]$WorkingDirectory [DscProperty(Mandatory)] [string]$ApplicationSourcePath [DscProperty(Mandatory)] [string]$TempLocation [DscProperty(Mandatory)] [string]$DestinationFolder [DscProperty(Mandatory)] [string]$Enabled [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty()] [bool]$Debug [void] Set() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.ApplicationSourcePath # Set file name based on name, version and type $filename = "$((Get-FileNameFromPath -Path $this.ApplicationSourcePath -Separator $separator))_$($this.Version).zip" If ($this.Debug) { Invoke-Logger -Message "Download file: $filename" -Severity D -Category "cMDTApplication" -Type SET } # Set folder name as file name without version $foldername = (Get-FileNameFromPath -Path $this.ApplicationSourcePath -Separator $separator).Split(".")[0] If ($this.Debug) { Invoke-Logger -Message "Folder name: $foldername" -Severity D -Category "cMDTApplication" -Type SET } # Determine if file path is an SMB or weblink and should be downloaded [bool]$download = $True If (($separator -eq "/") -Or ($this.ApplicationSourcePath.Substring(0,2) -eq "\\")) { $targetdownload = "$($this.TempLocation)\$($filename)" } Else { $targetdownload = "$($this.ApplicationSourcePath)_$($this.Version).zip" ; $download = $False } If ($this.Debug) { Invoke-Logger -Message "Target download: $targetdownload" -Severity D -Category "cMDTApplication" -Type SET } # Set temporary extraction folder name $extractfolder = "$($this.TempLocation)\$($foldername)" If ($this.Debug) { Invoke-Logger -Message "Extract folder: $extractfolder" -Severity D -Category "cMDTApplication" -Type SET } # Set reference file name to enable versioning $referencefile = "$($this.PSDrivePath)\Applications\$($this.DestinationFolder)\$((Get-FileNameFromPath -Path $this.ApplicationSourcePath -Separator $separator)).version" If ($this.Debug) { Invoke-Logger -Message "Reference file: $referencefile" -Severity D -Category "cMDTApplication" -Type SET } # Determine if application should be present or not if ($this.ensure -eq [Ensure]::Present) { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTApplication" -Type SET } # Check if application already exist in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTApplication" -Type SET } if ($present) { # Upgrade existing application If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTApplication" -Type SET } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.ApplicationSourcePath)_$($this.Version).zip'" -Severity D -Category "cMDTApplication" -Type SET } # Start download Invoke-WebDownload -Source "$($this.ApplicationSourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTApplication" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTApplication" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } If ($this.Debug) { Invoke-Logger -Message "Invoke-ExpandArchive -Source $targetdownload -Target '$($this.PSDrivePath)\Applications\$($this.DestinationFolder)'" -Severity D -Category "cMDTApplication" -Type SET } # Expand archive to application folder in MDT Invoke-ExpandArchive -Source $targetdownload -Target "$($this.PSDrivePath)\Applications\$($this.DestinationFolder)" # If downloaded If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $targetdownload" -Severity D -Category "cMDTApplication" -Type SET } # Remove downloaded archive after expansion Invoke-RemovePath -Path $targetdownload } } else { # Import new application If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path $($this.path) -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTApplication" -Type SET } # Create path for new application import Invoke-CreatePath -Path $this.path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTApplication" -Type SET } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.ApplicationSourcePath)_$($this.Version).zip'" -Severity D -Category "cMDTApplication" -Type SET } # Start download of application Invoke-WebDownload -Source "$($this.ApplicationSourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTApplication" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTApplication" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } If ($this.Debug) { Invoke-Logger -Message "Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder" -Severity D -Category "cMDTApplication" -Type SET } # Expand archive Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $extractfolder" -Severity D -Category "cMDTApplication" -Type SET } # Check if expanded folder exist $present = Invoke-TestPath -Path $extractfolder If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTApplication" -Type SET } # If expanded folder does not exist If (-not($present)) { Write-Error "Cannot find path '$extractfolder' because it does not exist." ; Return } # If downloaded If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $targetdownload" -Severity D -Category "cMDTApplication" -Type SET } # Remove downloaded archive after expansion Invoke-RemovePath -Path $targetdownload } # Call MDT import of new application $this.ImportApplication($extractfolder) If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $extractfolder" -Severity D -Category "cMDTApplication" -Type SET } # Remove expanded folder after import Invoke-RemovePath -Path $extractfolder If ($this.Debug) { Invoke-Logger -Message "New-ReferenceFile -Path $referencefile -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTApplication" -Type SET } # Create new versioning file New-ReferenceFile -Path $referencefile -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath } If ($this.Debug) { Invoke-Logger -Message "Set-Content -Path $referencefile -Value $($this.Version)" -Severity D -Category "cMDTApplication" -Type SET } # Set versioning file content Set-Content -Path $referencefile -Value "$($this.Version)" } else { # Remove existing application If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.path)\$($this.name)' -Recurse -Levels 3 -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTApplication" -Type SET } # Remove application and traverse folder path where empty Invoke-RemovePath -Path "$($this.path)\$($this.name)" -Recurse -Levels 3 -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } } [bool] Test() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.ApplicationSourcePath If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTApplication" -Type TEST } # Check if application already exists in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath # If application exists and should be present if (($present) -and ($this.ensure -eq [Ensure]::Present)) { If ($this.Debug) { Invoke-Logger -Message "Compare-Version -Source '$($this.PSDrivePath)\Applications\$($this.DestinationFolder)\$($this.ApplicationSourcePath.Split($($separator))[-1]).version' -Target $($this.Version)" -Severity D -Category "cMDTApplication" -Type TEST } # Verify version against the reference file $match = Compare-Version -Source "$($this.PSDrivePath)\Applications\$($this.DestinationFolder)\$((Get-FileNameFromPath -Path $this.ApplicationSourcePath -Separator $separator)).version" -Target $this.Version If ($this.Debug) { Invoke-Logger -Message "Match: $match" -Severity D -Category "cMDTApplication" -Type TEST } # If versioning file content do not match if (-not ($match)) { If ($this.Debug) { Invoke-Logger -Message "$($this.Name) version has been updated on the pull server" -Severity D -Category "cMDTApplication" -Type TEST } Write-Verbose "$($this.Name) version has been updated on the pull server" $present = $false } } # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { If ($this.Debug) { Invoke-Logger -Message "Return $present" -Severity D -Category "cMDTApplication" -Type TEST } return $present } else { If ($this.Debug) { Invoke-Logger -Message "Return -not $present" -Severity D -Category "cMDTApplication" -Type TEST } return -not $present } } [cMDTApplication] Get() { return $this } [void] ImportApplication($Source) { If ($this.Debug) { Invoke-Logger -Message "Import-MicrosoftDeploymentToolkitModule" -Severity D -Category "cMDTApplication" -Type FUNCTION } # Import the required module MicrosoftDeploymentToolkitModule Import-MicrosoftDeploymentToolkitModule If ($this.Debug) { Invoke-Logger -Message "New-PSDrive -Name $($this.PSDriveName) -PSProvider 'MDTProvider' -Root $($this.PSDrivePath) -Verbose:$($false)" -Severity D -Category "cMDTApplication" -Type FUNCTION } # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false If ($this.Debug) { Invoke-Logger -Message "If (-not(Invoke-TestPath -Path $($this.path) -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)))" -Severity D -Category "cMDTApplication" -Type FUNCTION } # Verify that the path for the application import exist If (-not(Invoke-TestPath -Path $this.path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath)) { If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path $($this.path) -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTApplication" -Type FUNCTION } # Create folder path to prepare for application import Invoke-CreatePath -Path $this.path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } If ($this.Debug) { Invoke-Logger -Message "Import-MDTApplication -Path $($this.Path) -Enable $($this.Enabled) -Name $($this.Name) -ShortName $($this.ShortName) -Version $($this.Version) -Publisher $($this.Publisher) -Language $($this.Language) -CommandLine $($this.CommandLine) -WorkingDirectory $($this.WorkingDirectory) -ApplicationSourcePath $($Source) -DestinationFolder $($this.DestinationFolder) -Verbose" -Severity D -Category "cMDTApplication" -Type FUNCTION } # Initialize application import to MDT Import-MDTApplication -Path $this.Path -Enable $this.Enabled -Name $this.Name -ShortName $this.ShortName -Version $this.Version ` -Publisher $this.Publisher -Language $this.Language -CommandLine $this.CommandLine -WorkingDirectory $this.WorkingDirectory ` -ApplicationSourcePath $Source -DestinationFolder $this.DestinationFolder -Verbose } } [DscResource()] class cMDTApplicationBundle { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$BundleName [DscProperty(Mandatory)] [string[]]$BundledApplications [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty()] [string]$Version = [string]::Empty [DscProperty()] [string]$Publisher = [string]::Empty [DscProperty()] [string]$Language = [string]::Empty [DscProperty()] [string]$Hide = $false [DscProperty()] [string]$Enable = $true [DscProperty()] [string]$Folder = 'Applications' [void] Set() { # Call function to check if bundle exist $present = $this.ApplicationBundleExists() # Call function to check if bundle needs to be updated $bundleNeedsUpdate = $this.ApplicationBundleNeedsUpdate() # Determine if bundle should be present or not if ($this.Ensure -eq [ensure]::Present -and $present -eq $false) { if ($bundleNeedsUpdate) { # Update bundle $this.UpdateApplicationBundle() } else { # Create bundle $this.CreateApplicationBundle() } } elseif ($this.Ensure -eq [ensure]::Absent -and $present -eq $true) { # Remove bundle $this.RemoveApplicationBundle() } } [bool] Test() { # Call function to check if bundle exist $present = $this.ApplicationBundleExists() # Return boolean from test method if ($this.Ensure -eq [ensure]::Present) { return $present } else { return -not $present } } [cMDTApplicationBundle] Get() { return $this } [bool] ApplicationBundleExists() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Check if bundle exist $bundle = Get-ChildItem "$($this.PSDriveName):" -Recurse | Where-Object {$_.Name -eq "$($this.BundleName)" -and $_.NodeType -eq 'Application'} if ($bundle) { # Check if bundle needs to be updated if ($this.ApplicationBundleNeedsUpdate()) { return $false } return $true } return $false } [bool] ApplicationBundleNeedsUpdate() { # Import MicrosoftDeploymentToolkitModule Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Check if bundle exist $bundle = Get-ChildItem "$($this.PSDriveName):" -Recurse | Where-Object {$_.Name -eq "$($this.BundleName)" -and $_.NodeType -eq 'Application'} if (!$bundle) { return $false } # Get GUID:s from bundle $applicationGuids = $this.GetApplicationGuids() # Compare GUID:s to check if update is needed if ((Compare-Object $applicationGuids $bundle.Dependency) -ne $null) {return $true} # Verify bundle parameter properties if ($bundle.ShortName -ne $this.BundleName) {return $true} if ($bundle.Version -ne $this.Version) {return $true} if ($bundle.Publisher -ne $this.Publisher) {return $true} if ($bundle.Language -ne $this.Language) {return $true} if ($bundle.Hide -ne $this.Hide.ToString()) {return $true} if ($bundle.Enable -ne $this.Enable.ToString()) {return $true} return $false } [void] CreateApplicationBundle() { # Import MicrosoftDeploymentToolkitModule Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Set splatting parameters from input $importParams = @{ Path = "$($this.PSDriveName):\$($this.Folder)" Enable = $this.Enable.ToString() Hide = $this.Hide.ToString() Name = $this.BundleName ShortName = $this.BundleName DisplayName = $this.BundleName Version = $this.Version Publisher = $this.Publisher Language = $this.Language Bundle = $true } # Import MDT application Import-MDTApplication @importParams > $null # Define path to bundle in MDT $path = "$($this.PSDriveName):\$($this.Folder)\$($this.BundleName)" # Get GUID:s for bundle $applicationGuids = $this.GetApplicationGuids() # Set GUID:s to property for matching capabilities Set-ItemProperty -Path $path -Name Dependency -Value $applicationGuids } [void] UpdateApplicationBundle() { # Import MicrosoftDeploymentToolkitModule Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Define path to bundle in MDT $path = "$($this.PSDriveName):\$($this.Folder)\$($this.BundleName)" # Define attributes to be verified $properties = @('Enable', 'Hide', 'ShortName', 'DisplayName', 'Version', 'Publisher', 'Language') # Loop through attributes and update accordingly foreach ($property in $properties) { if ($property -eq 'ShortName' -or $property -eq 'DisplayName') { Set-ItemProperty -Path "$path" -Name "$property" -Value "$($this.BundleName)" } else { Set-ItemProperty -Path "$path" -Name "$property" -Value "$($this.$property.ToString())" } } # Get GUID:s for bundle $applicationGuids = $this.GetApplicationGuids() # Set GUID:s to property for matching capabilities Set-ItemProperty -Path $path -Name Dependency -Value $applicationGuids } [void] RemoveApplicationBundle() { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false $path = "$($this.PSDriveName):\$($this.Folder)\$($this.BundleName)" Remove-Item -Path $path } [string[]] GetApplicationGuids() { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false [string[]]$applicationGuids = @() foreach ($application in $this.BundledApplications) { $applicationGuid = Get-ChildItem "$($this.PSDriveName):" -Recurse | Where-Object {$_.Name -eq $application -and $_.NodeType -eq 'Application'} | Select-Object -ExpandProperty guid if ($applicationGuid) { $applicationguids += $applicationGuid } } return $applicationGuids } } [DscResource()] class cMDTBootstrapIni { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$Path [DscProperty()] [string]$Content [void] Set() { # Check if defined as present if ($this.Ensure -eq [Ensure]::Present) { # If set to present set content according to contract $this.SetContent() } else { # If set to absent revert to default content $this.SetDefaultContent() } } [bool] Test() { # Call function to test file content according to contract $present = $this.TestFileContent() if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTBootstrapIni] Get() { return $this } [bool] TestFileContent() { $present = $false # Import existing file content $existingConfiguration = Get-Content -Path $this.Path -Raw #-Encoding UTF8 # Match against content from contract if ($existingConfiguration -eq $this.Content.Replace("`n","`r`n")) { $present = $true } # Return state return $present } [void] SetContent() { # Set new file content Set-Content -Path $this.Path -Value $this.Content.Replace("`n","`r`n") -NoNewline -Force #-Encoding UTF8 } [void] SetDefaultContent() { # Set default content $defaultContent = @" [Settings] Priority=Default [Default] "@ Set-Content -Path $this.Path -Value $defaultContent -NoNewline -Force #-Encoding UTF8 } } [DscResource()] class cMDTCustomize { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Mandatory)] [string]$Version [DscProperty(Key)] [string]$Name [DscProperty(Key)] [string]$Path [DscProperty(Mandatory)] [string]$SourcePath [DscProperty(Mandatory)] [string]$TempLocation [bool]$Protected [DscProperty(NotConfigurable)] [string]$Directory [void] Set() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath # Set file name basen on name and version $filename = "$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator))_$($this.Version).zip" # Determine if file path is an SMB or weblink and should be downloaded [bool]$download = $True If (($separator -eq "/") -Or ($this.SourcePath.Substring(0,2) -eq "\\")) { $targetdownload = "$($this.TempLocation)\$($filename)" } Else { $targetdownload = "$($this.SourcePath)_$($this.Version).zip" ; $download = $False } # Set extraction folder name $extractfolder = "$($this.path)\$($this.name)" # Set reference file name to enable versioning $referencefile = "$($this.Path)\$($this.name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" # Determine if customization should be present or not if ($this.ensure -eq [Ensure]::Present) { # Check if customization already exist in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" if ($present) { # Upgrade existing customization # If customization must be downloaded before imported If ($download) { # Start download of customization Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } # Check if protected mode has been defined if (-not $this.Protected) { # Check if reference file exist $present = Invoke-TestPath -Path $referencefile # If it exist remove the reference file If ($present) { Invoke-RemovePath -Path $referencefile } } # Expand archive to folder in MDT Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder -Verbose # If downloaded, remove downloaded archive after expansion If ($download) { Invoke-RemovePath -Path $targetdownload } # If protected mode has been defined create a new reference file If ($this.Protected) { New-ReferenceFile -Path $referencefile } } else { # Import new customization # If customization must be downloaded before imported If ($download) { # Start download of customization Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } # Expand archive to folder in MDT Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder -Verbose # If downloaded, remove downloaded archive after expansion If ($download) { Invoke-RemovePath -Path $targetdownload } # Create a new reference file New-ReferenceFile -Path $referencefile } # Set versioning file content Set-Content -Path $referencefile -Value "$($this.Version)" } else { # Remove customization and traverse folder path where empty Invoke-RemovePath -Path "$($this.path)\$($this.name)" -Verbose } } [bool] Test() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath # Check if customization exist in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" # If customization exists and should be present if (($present) -and ($this.ensure -eq [Ensure]::Present)) { # Verify existence of reference file If (Test-Path -Path "$($this.Path)\$($this.name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" -ErrorAction Ignore) { # Verify customization version against the reference file $match = Compare-Version -Source "$($this.Path)\$($this.name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" -Target $this.Version # If versioning file content do not match if (-not ($match)) { Write-Verbose "$($this.Name) version has been updated on the pull server" $present = $false } } else { $present = $false } } # If customization exist, should be absent but defined as protected if (($present) -and ($this.Protected) -and ($this.ensure -eq [Ensure]::Absent)) { Write-Verbose "Folder protection override mode defined" Write-Verbose "$($this.Name) folder will not be removed" return $true } # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTCustomize] Get() { return $this } } [DscResource()] class cMDTCustomSettingsIni { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$Path [DscProperty()] [string]$Content [void] Set() { # Check if defined as present if ($this.Ensure -eq [Ensure]::Present) { # If set to present set content according to contract $this.SetContent() } else { # If set to absent revert to default content $this.SetDefaultContent() } } [bool] Test() { # Call function to test file content according to contract $present = $this.TestFileContent() if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTCustomSettingsIni] Get() { return $this } [bool] TestFileContent() { $present = $false # Import existing file content $existingConfiguration = Get-Content -Path $this.Path -Raw #-Encoding UTF8 # Match against content from contract if ($existingConfiguration -eq $this.Content.Replace("`n","`r`n")) { $present = $true } return $present } [void] SetContent() { # Set new file content Set-Content -Path $this.Path -Value $this.Content.Replace("`n","`r`n") -NoNewline -Force #-Encoding UTF8 } [void] SetDefaultContent() { # Set default content $defaultContent = @" [Settings] Priority=Default Properties=MyCustomProperty [Default] OSInstall=Y SkipCapture=YES SkipAdminPassword=NO SkipProductKey=YES "@ Set-Content -Path $this.Path -Value $defaultContent -NoNewline -Force #-Encoding UTF8 } } [DscResource()] class cMDTDirectory { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Name [DscProperty()] [string]$PSDriveName [DscProperty()] [string]$PSDrivePath [DscProperty()] [bool]$Debug [void] Set() { # Determine present/absent if ($this.ensure -eq [Ensure]::Present) { # If present create path $this.CreateDirectory() } else { # Verify if local path or PSDrive if (($this.PSDrivePath) -and ($this.PSDriveName)) { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.path)\$($this.Name)' -Recurse -Levels 4 -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTDirectory" -Type SET } # Remove and traverse folder path where empty Invoke-RemovePath -Path "$($this.path)\$($this.Name)" -Recurse -Levels 4 -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } Else { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.path)\$($this.Name)' -Recurse -Levels 4 -Verbose" -Severity D -Category "cMDTDirectory" -Type SET } # Remove and traverse folder path where empty Invoke-RemovePath -Path "$($this.path)\$($this.Name)" -Recurse -Levels 4 -Verbose } } } [bool] Test() { # Verify if local path or PSDrive if (($this.PSDrivePath) -and ($this.PSDriveName)) { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.Name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTDirectory" -Type TEST } # Verify if PSDrive path exist $present = Invoke-TestPath -Path "$($this.path)\$($this.Name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDirectory" -Type TEST } } Else { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.Name)' -Verbose" -Severity D -Category "cMDTDirectory" -Type TEST } # Verify if local path exist $present = Invoke-TestPath -Path "$($this.path)\$($this.Name)" -Verbose If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDirectory" -Type TEST } } if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTDirectory] Get() { return $this } [void] CreateDirectory() { # Verify if local path or PSDrive if (($this.PSDrivePath) -and ($this.PSDriveName)) { If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path '$($this.path)\$($this.Name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTDirectory" -Type FUNCTION } # Create PSDrive path $present = Invoke-CreatePath -Path "$($this.path)\$($this.Name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDirectory" -Type FUNCTION } } Else { If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path '$($this.path)\$($this.Name)' -Verbose" -Severity D -Category "cMDTDirectory" -Type FUNCTION } # Create local path Invoke-CreatePath -Path "$($this.path)\$($this.Name)" -Verbose } } } [DscResource()] class cMDTDriver { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Mandatory)] [string]$Version [DscProperty(Key)] [string]$Name [DscProperty(Key)] [string]$Path [DscProperty(Mandatory)] [string]$Enabled [DscProperty(Mandatory)] [string]$Comment [DscProperty(Mandatory)] [string]$SourcePath [DscProperty(Mandatory)] [string]$TempLocation [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty()] [bool]$Debug [void] Set() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath # Set file name based on name, version and type $filename = "$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator))_$($this.Version).zip" If ($this.Debug) { Invoke-Logger -Message "Download file: $filename" -Severity D -Category "cMDTDriver" -Type SET } # Set folder name as file name without version $foldername = (Get-FileNameFromPath -Path $this.SourcePath -Separator $separator).Split(".")[0] If ($this.Debug) { Invoke-Logger -Message "Folder name: $foldername" -Severity D -Category "cMDTDriver" -Type SET } # Determine if file path is an SMB or weblink and should be downloaded [bool]$download = $True If (($separator -eq "/") -Or ($this.SourcePath.Substring(0,2) -eq "\\")) { $targetdownload = "$($this.TempLocation)\$($filename)" } Else { $targetdownload = "$($this.SourcePath)_$($this.Version).zip" ; $download = $False } If ($this.Debug) { Invoke-Logger -Message "Target download: $targetdownload" -Severity D -Category "cMDTDriver" -Type SET } # Set temporary extraction folder name $extractfolder = "$($this.TempLocation)\$($foldername)" If ($this.Debug) { Invoke-Logger -Message "Extract folder: $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Set reference file name to enable versioning $referencefile = "$($this.PSDrivePath)\Out-of-Box Drivers\$($($this.Path.Split("\")[-2]).Replace(' ',''))$($($this.Path.Split("\")[-1]).Replace(' ',''))$($($this.Name).Replace(' ',''))$($this.SourcePath.Split($separator)[-1]).version" If ($this.Debug) { Invoke-Logger -Message "Reference file: $referencefile" -Severity D -Category "cMDTDriver" -Type SET } # Determine if driver should be present or not if ($this.ensure -eq [Ensure]::Present) { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTDriver" -Type SET } # Check if driver already exist in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDriver" -Type SET } if ($present) { # Upgrade existing driver If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTDriver" -Type SET } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath)_$($this.Version).zip' -Target $targetdownload -Verbose" -Severity D -Category "cMDTDriver" -Type SET } # Start download Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTDriver" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDriver" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } If ($this.Debug) { Invoke-Logger -Message "Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder" -Severity D -Category "cMDTApplication" -Type SET } # Expand archive Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Check if expanded folder exist $present = Invoke-TestPath -Path $extractfolder If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDriver" -Type SET } # If expanded folder does not exist If (-not($present)) { Write-Error "Cannot find path '$extractfolder' because it does not exist." ; Return } If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.path)\$($this.name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTApplication" -Type SET } # Remove current version Invoke-RemovePath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose # If downloaded If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $targetdownload" -Severity D -Category "cMDTDriver" -Type SET } # Remove downloaded archive after expansion Invoke-RemovePath -Path $targetdownload } # Call MDT import of new driver $this.ImportDriver($extractfolder) If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Remove expanded folder after import Invoke-RemovePath -Path $extractfolder } else { # Import new driver If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path $($this.path) -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTDriver" -Type SET } # Create path for new driver import Invoke-CreatePath -Path $this.path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTDriver" -Type SET } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath)_$($this.Version).zip' -Target $targetdownload -Verbose" -Severity D -Category "cMDTDriver" -Type SET } # Start download Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).zip" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTDriver" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDriver" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } If ($this.Debug) { Invoke-Logger -Message "Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Expand archive Invoke-ExpandArchive -Source $targetdownload -Target $extractfolder If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Check if expanded folder exist $present = Invoke-TestPath -Path $extractfolder If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTDriver" -Type SET } # If expanded folder does not exist If (-not($present)) { Write-Error "Cannot find path '$extractfolder' because it does not exist." ; Return } # If downloaded If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $targetdownload" -Severity D -Category "cMDTDriver" -Type SET } # Remove downloaded archive after expansion Invoke-RemovePath -Path $targetdownload } # Call MDT import of new driver $this.ImportDriver($extractfolder) If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $extractfolder" -Severity D -Category "cMDTDriver" -Type SET } # Remove expanded folder after import Invoke-RemovePath -Path $extractfolder If ($this.Debug) { Invoke-Logger -Message "New-ReferenceFile -Path $referencefile" -Severity D -Category "cMDTDriver" -Type SET } # Create new versioning file New-ReferenceFile -Path $referencefile } If ($this.Debug) { Invoke-Logger -Message "Set-Content -Path $referencefile -Value '$($this.Version)'" -Severity D -Category "cMDTDriver" -Type SET } # Set versioning file content Set-Content -Path $referencefile -Value "$($this.Version)" } else { # Remove existing driver If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.path)\$($this.name)' -Recurse -Levels 3 -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTDriver" -Type SET } # Remove application and traverse folder path where empty Invoke-RemovePath -Path "$($this.path)\$($this.name)" -Recurse -Levels 3 -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path $referencefile" -Severity D -Category "cMDTDriver" -Type SET } # Remove reference file Invoke-RemovePath -Path $referencefile } } [bool] Test() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.path)\$($this.name)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTDriver" -Type TEST } # Check if driver already exists in MDT $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath # If driver exists and should be present if (($present) -and ($this.ensure -eq [Ensure]::Present)) { If ($this.Debug) { Invoke-Logger -Message "Compare-Version -Source '$($this.PSDrivePath)\Out-of-Box Drivers\$($($this.Path.Split('\')[-2]).Replace(' ',''))$($($this.Path.Split('\')[-1]).Replace(' ',''))$($($this.Name).Replace(' ',''))$($this.SourcePath.Split($separator)[-1]).version' -Target $($this.Version)" -Severity D -Category "cMDTDriver" -Type TEST } # Verify version against the reference file $match = Compare-Version -Source "$($this.PSDrivePath)\Out-of-Box Drivers\$($($this.Path.Split("\")[-2]).Replace(' ',''))$($($this.Path.Split("\")[-1]).Replace(' ',''))$($($this.Name).Replace(' ',''))$($this.SourcePath.Split($separator)[-1]).version" -Target $this.Version If ($this.Debug) { Invoke-Logger -Message "Match: $match" -Severity D -Category "cMDTDriver" -Type TEST } # If versioning file content do not match if (-not ($match)) { Write-Verbose "$($this.Name) version has been updated on the pull server" $present = $false } } # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTDriver] Get() { return $this } [void] ImportDriver($Driver) { If ($this.Debug) { Invoke-Logger -Message "Import-MicrosoftDeploymentToolkitModule" -Severity D -Category "cMDTDriver" -Type FUNCTION } # Import the required module MicrosoftDeploymentToolkitModule Import-MicrosoftDeploymentToolkitModule If ($this.Debug) { Invoke-Logger -Message "New-PSDrive -Name $($this.PSDriveName) -PSProvider 'MDTProvider' -Root $($this.PSDrivePath) -Verbose:$($false)" -Severity D -Category "cMDTDriver" -Type FUNCTION } # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false If ($this.Debug) { Invoke-Logger -Message "New-Item -Path $($this.Path) -enable $($this.Enabled) -Name $($this.Name) -Comments $($this.Comment) -ItemType 'folder' �Verbose" -Severity D -Category "cMDTDriver" -Type FUNCTION } # Create path for the driver New-Item -Path $this.Path -enable $this.Enabled -Name $this.Name -Comments $this.Comment -ItemType "folder" �Verbose If ($this.Debug) { Invoke-Logger -Message "Import-MDTDriver -Path '$($this.path)\$($this.name)' -SourcePath $Driver -ImportDuplicates -Verbose" -Severity D -Category "cMDTDriver" -Type FUNCTION } # Initialize driver import to MDT Import-MDTDriver -Path "$($this.path)\$($this.name)" -SourcePath $Driver -ImportDuplicates -Verbose } } [DscResource()] class cMDTMonitorService { [DscProperty(Mandatory)] [Ensure] $Ensure [ValidateSet('Yes')] [DscProperty(Key)] [ValidateNotNullorEmpty()] [String] $IsSingleInstance = 'Yes' [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty(Mandatory)] [string]$MonitorHost [void] Set() { # Check if monitor service is enabled $present = $this.MDTMonitorServiceIsEnabled() # Should monitor service be enabled if ($this.Ensure -eq [ensure]::Present -and $present -eq $false) { # Enable monitor service $this.EnableMDTMonitorService() } elseif ($this.Ensure -eq [ensure]::Absent -and $present -eq $true) { # Disable monitor service $this.DisableMDTMonitorService() } } [bool] Test() { # Check if monitor service is enabled $present = $this.MDTMonitorServiceIsEnabled() # Return boolean from test method if ($this.Ensure -eq [ensure]::Present) { return $present } else { return -not $present } } [cMDTMonitorService] Get() { return $this } [bool] MDTMonitorServiceIsEnabled() { # Check if monitor service is started try { $service = Get-Service MDT_Monitor -ErrorAction Stop if ($service.Status -ne 'Running') { return $false } } catch { return $false } # Check if firewall ports for monitoring is opened if (!(Test-NetConnection -Port 9800 -ComputerName localhost -InformationLevel Quiet)) { return $false } if (!(Test-NetConnection -Port 9801 -ComputerName localhost -InformationLevel Quiet)) { return $false } try { # Get firewall rule for monitor service $rule = Get-NetFirewallRule -DisplayName 'MDT Monitor' -ErrorAction Stop # Get ports from firewall rule $ports = $rule | Get-NetFirewallPortFilter # Check if ports are defined in rule if (!($ports.LocalPort.Contains('9800') -and $ports.LocalPort.Contains('9801'))) { return $false } } catch { return $false } return $true } [void] EnableMDTMonitorService() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Enable monitor service Enable-MDTMonitorService -EventPort 9800 -DataPort 9801 # Define host and ports Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorHost -Value $this.MonitorHost Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorEventPort -Value "9800" Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorDataPort -Value "9801" } [void] DisableMDTMonitorService() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Enable monitor service Disable-MDTMonitorService # Remove host and ports Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorHost -Value "" Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorEventPort -Value "" Set-ItemProperty "$($this.PSDriveName):\" -Name MonitorDataPort -Value "" } } [DscResource()] class cMDTOperatingSystem { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty()] [string]$Version [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Name [DscProperty(Key)] [string]$SourcePath [DscProperty(Mandatory)] [string]$TempLocation [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty()] [bool]$Debug [void] Set() { # Determine versioning type; checksum or static version [bool]$Hash = $False If (-not ($this.version)) { $Hash = $True } # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath $filename = $null # Set file name based on versioning type If ($Hash) { $filename = "$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).wim" } Else { $filename = "$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator))_$($this.Version).wim" } If ($this.Debug) { Invoke-Logger -Message "Download file: $filename" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Set folder name as file name without version $foldername = (Get-FileNameFromPath -Path $this.SourcePath -Separator $separator).Split(".")[0] If ($this.Debug) { Invoke-Logger -Message "Folder name: $foldername" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Determine if file path is an SMB or weblink and should be downloaded [bool]$download = $True If (($separator -eq "/") -Or ($this.SourcePath.Substring(0,2) -eq "\\")) { $targetdownload = "$($this.TempLocation)\$($filename)" If ($this.Debug) { Invoke-Logger -Message "Target download: $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } $targetdownloadref = "$($this.TempLocation)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" If ($this.Debug) { Invoke-Logger -Message "Target download reference: $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } } Else { If ($this.Debug) { Invoke-Logger -Message "Hash: $Hash" -Severity D -Category "cMDTOperatingSystem" -Type SET } If ($Hash) { $targetdownload = "$($this.SourcePath).wim" If ($this.Debug) { Invoke-Logger -Message "Target download: $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } $targetdownloadref = "$($this.SourcePath).version" If ($this.Debug) { Invoke-Logger -Message "Target download reference: $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } } Else { $targetdownload = "$($this.SourcePath)_$($this.Version).wim" If ($this.Debug) { Invoke-Logger -Message "Target download: $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } $targetdownloadref = "$($this.SourcePath)_$($this.Version).version" If ($this.Debug) { Invoke-Logger -Message "Target download reference: $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } } $download = $False } # Set reference file name to enable versioning $referencefile = "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" If ($this.Debug) { Invoke-Logger -Message "Reference file: $referencefile" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Set temporary extraction folder name $extractfolder = "$($this.TempLocation)\$($foldername)" If ($this.Debug) { Invoke-Logger -Message "Extract folder: $extractfolder" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Determine if OS should be present or not if ($this.ensure -eq [Ensure]::Present) { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)'" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Check if OS already exist in MDT $present = Invoke-TestPath -Path "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" if ($present) { # Upgrade existing OS If ($Hash) { # If checksum automatic update defined If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath).wim' -Target $targetdownload -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Start download of WIM Invoke-WebDownload -Source "$($this.SourcePath).wim" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath).version' -Target $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Start download of checksum file Invoke-WebDownload -Source "$($this.SourcePath).version" -Target $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download of checksum was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownloadref' because it does not exist." ; Return } } Else { If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if WIM image can be found on source $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If image can not be found If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } } Else { # If versioning update was defined # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath)_$($this.Version).wim' -Target $targetdownload -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Start download of WIM Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).wim" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } } If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)' -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Remove existing OS file Invoke-RemovePath -Path "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)'" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if removal was successfull $present = Invoke-TestPath -Path "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If removal was unsuccessfull If ($present) { Write-Error "Could not remove path '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)'." ; Return } # Define new file names for import. Needed to keep names intact in MDT when not performing a new import. $oldname = $null $newname = $null If (-not ($Hash)) { $oldname = $targetdownload $newname = $targetdownload.Replace("_$($this.Version)","") } # If file must be downloaded before imported If ($download) { If ($this.Debug) { Invoke-Logger -Message "Copy-Item $targetdownload -Destination '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)' -Force -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Copy WIM file to MDT storage location Copy-Item $targetdownload -Destination "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" -Force -Verbose } Else { If (-not ($Hash)) { If ($this.Debug) { Invoke-Logger -Message "Rename-Item -Path $oldname -NewName $newname -ErrorAction SilentlyContinue -Verbose:$($False)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Rename file for import Rename-Item -Path $oldname -NewName $newname -ErrorAction SilentlyContinue -Verbose:$False } If ($Hash) { If ($this.Debug) { Invoke-Logger -Message "Copy-Item $targetdownload -Destination '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)' -Force -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Copy WIM file to MDT storage location Copy-Item $targetdownload -Destination "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" -Force -Verbose } Else { If ($this.Debug) { Invoke-Logger -Message "Copy-Item $newname -Destination '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)' -Force -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Copy renamed WIM file to MDT storage location Copy-Item $newname -Destination "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$($filename)" -Force -Verbose } If (-not ($Hash)) { If ($this.Debug) { Invoke-Logger -Message "Rename-Item -Path $newname -NewName $oldname -ErrorAction SilentlyContinue -Verbose:$($False)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Rename source file to back original name Rename-Item -Path $newname -NewName $oldname -ErrorAction SilentlyContinue -Verbose:$False } } If ($Hash) { # Get versioning from downloaded checksum $this.version = Get-Content -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Version: $($this.version)" -Severity D -Category "cMDTOperatingSystem" -Type SET } } If ($this.Debug) { Invoke-Logger -Message "Set-Content -Path $referencefile -Value '$($this.Version)' -Verbose:$($false)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Set versioning content to reference file Set-Content -Path $referencefile -Value "$($this.Version)" -Verbose:$false } else { # Import new OS If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path '$($this.Path)' -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Create path for new OS import Invoke-CreatePath -Path "$($this.Path)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose # Define new file names for import. Needed to keep names intact in MDT when not performing a new import. $oldname = $null $newname = $null If (-not ($Hash)) { $oldname = $targetdownload $newname = $targetdownload.Replace("_$($this.Version)","") } # If file must be downloaded before imported If ($download) { # If file must be downloaded before imported If ($this.Debug) { Invoke-Logger -Message "Hash: $Hash" -Severity D -Category "cMDTOperatingSystem" -Type SET } If ($Hash) { # If checksum update was defined If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath).wim' -Target $targetdownload -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Download WIm file Invoke-WebDownload -Source "$($this.SourcePath).wim" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath).version' -Target $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Download checksum file Invoke-WebDownload -Source "$($this.SourcePath).version" -Target $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownloadref' because it does not exist." ; Return } } Else { # If versioning update was defined If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath)_$($this.Version).wim' -Target $targetdownload -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Download WIM file Invoke-WebDownload -Source "$($this.SourcePath)_$($this.Version).wim" -Target $targetdownload -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownload" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownload If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownload' because it does not exist." ; Return } } # Call function to import OS $this.ImportOperatingSystem($targetdownload) } Else { # If file must not be downloaded before imported If (-not ($Hash)) { If ($this.Debug) { Invoke-Logger -Message "Rename-Item -Path $oldname -NewName $newname -ErrorAction SilentlyContinue -Verbose:$($False)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Rename file for import Rename-Item -Path $oldname -NewName $newname -ErrorAction SilentlyContinue -Verbose:$False } If ($Hash) { # Call function to import OS $this.ImportOperatingSystem($targetdownload) } Else { # Call function to import OS $this.ImportOperatingSystem($newname) } If (-not ($Hash)) { If ($this.Debug) { Invoke-Logger -Message "Rename-Item -Path $newname -NewName $oldname -ErrorAction SilentlyContinue -Verbose:$($False)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Rename file after import Rename-Item -Path $newname -NewName $oldname -ErrorAction SilentlyContinue -Verbose:$False } } If ($this.Debug) { Invoke-Logger -Message "New-ReferenceFile -Path $referencefile -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath)" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Create new reference file for versioning New-ReferenceFile -Path $referencefile -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath If ($Hash) { # Get checksum from downloaded file $this.version = Get-Content -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Version: $($this.version)" -Severity D -Category "cMDTOperatingSystem" -Type SET } } If ($this.Debug) { Invoke-Logger -Message "Set-Content -Path $referencefile -Value '$($this.Version)'" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Set versioning file content Set-Content -Path $referencefile -Value "$($this.Version)" } } else { # Remove existing OS If ($this.Debug) { Invoke-Logger -Message "Invoke-RemovePath -Path '$($this.Path)' -Recurse -Levels 4 -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Remove OS recursively from MDT Invoke-RemovePath -Path "$($this.Path)" -Recurse -Levels 4 -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.PSDrivePath)\Operating Systems\$($this.Name)'" -Severity D -Category "cMDTOperatingSystem" -Type SET } # Test if renmoval was successfull $present = Invoke-TestPath -Path "$($this.PSDrivePath)\Operating Systems\$($this.Name)" If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type SET } # If removal was not successfull If ($present) { Write-Error "Cannot find path '$($this.PSDrivePath)\Operating Systems\$($this.Name)' because it does not exist." } } } [bool] Test() { # Get string path separator; eg. "/" or "\" [string]$separator = Get-Separator -Path $this.SourcePath # Determine if checksum or manual versioning update was defined If (-not ($this.version)) { # Determine versioning file must be downloaded [bool]$download = $True If (($separator -eq "/") -Or ($this.SourcePath.Substring(0,2) -eq "\\")) { $targetdownloadref = "$($this.TempLocation)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" } Else { $targetdownloadref = "$($this.SourcePath).version" $download = $False } If ($this.Debug) { Invoke-Logger -Message "Target download reference: $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type TEST } If ($this.Debug) { Invoke-Logger -Message "Download: $download" -Severity D -Category "cMDTOperatingSystem" -Type TEST } If ($download) { If ($this.Debug) { Invoke-Logger -Message "Invoke-WebDownload -Source '$($this.SourcePath).version' -Target $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type TEST } # Download versioning file Invoke-WebDownload -Source "$($this.SourcePath).version" -Target $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path $targetdownloadref" -Severity D -Category "cMDTOperatingSystem" -Type TEST } # Test if download was successfull $present = Invoke-TestPath -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Return: $present" -Severity D -Category "cMDTOperatingSystem" -Type TEST } # If download was not successfull If (-not($present)) { Write-Error "Cannot find path '$targetdownloadref' because it does not exist." ; Exit } } # Get content from downloaded versioning file $this.version = Get-Content -Path $targetdownloadref If ($this.Debug) { Invoke-Logger -Message "Version: $($this.version)" -Severity D -Category "cMDTOperatingSystem" -Type TEST } } If ($this.Debug) { Invoke-Logger -Message "Invoke-TestPath -Path '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).wim'" -Severity D -Category "cMDTOperatingSystem" -Type TEST } # Test if OS file already exist in MDT $present = Invoke-TestPath -Path "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).wim" # If OS exists and should be present if (($present) -and ($this.ensure -eq [Ensure]::Present)) { If ($this.Debug) { Invoke-Logger -Message "Compare-Version -Source '$($this.PSDrivePath)\Operating Systems\$($this.Name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version' -Target $($this.Version)" -Severity D -Category "cMDTOperatingSystem" -Type TEST } # Verify content from server side versioning file against local reference file $match = Compare-Version -Source "$($this.PSDrivePath)\Operating Systems\$($this.Name)\$((Get-FileNameFromPath -Path $this.SourcePath -Separator $separator)).version" -Target $this.Version If ($this.Debug) { Invoke-Logger -Message "Match: $match" -Severity D -Category "cMDTOperatingSystem" -Type TEST } if (-not ($match)) { # If version does not match Write-Verbose "$($this.Name) version has been updated on the pull server" $present = $false } } # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTOperatingSystem] Get() { return $this } [void] ImportOperatingSystem($OperatingSystem) { If ($this.Debug) { Invoke-Logger -Message "Import-MicrosoftDeploymentToolkitModule" -Severity D -Category "cMDTOperatingSystem" -Type FUNCTION } # Import the MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule If ($this.Debug) { Invoke-Logger -Message "New-PSDrive -Name $($this.PSDriveName) -PSProvider 'MDTProvider' -Root $($this.PSDrivePath) -Verbose:$($false)" -Severity D -Category "cMDTOperatingSystem" -Type FUNCTION } # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false # Verify that the path for the application import exist If (-not(Invoke-TestPath -Path $this.Path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath)) { If ($this.Debug) { Invoke-Logger -Message "Invoke-CreatePath -Path $($this.Path) -PSDriveName $($this.PSDriveName) -PSDrivePath $($this.PSDrivePath) -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type FUNCTION } # Create folder path to prepare for OS import Invoke-CreatePath -Path $this.Path -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } Try { $ErrorActionPreference = "Stop" If ($this.Debug) { Invoke-Logger -Message "Import-MDTOperatingSystem -Path $($this.Path) -SourceFile $OperatingSystem -DestinationFolder $($this.Name) -Verbose" -Severity D -Category "cMDTOperatingSystem" -Type FUNCTION } # Start import of OS file Import-MDTOperatingSystem -Path $this.Path -SourceFile $OperatingSystem -DestinationFolder $this.Name -Verbose $ErrorActionPreference = "Continue" } Catch [Microsoft.Management.Infrastructure.CimException] { If ($_.FullyQualifiedErrorId -notlike "*ItemAlreadyExists*") { throw $_ } } Finally { } } } [DscResource()] class cMDTPersistentDrive { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Name [DscProperty(Mandatory)] [string]$Description [DscProperty(Mandatory)] [string]$NetworkPath [void] Set() { # Determine present/absent if ($this.ensure -eq [Ensure]::Present) { # If present create drive $this.CreateDirectory() } else { # If absent remove drive $this.RemoveDirectory() } } [bool] Test() { # Check if persistent drive exist $present = $this.TestDirectoryPath() # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTPersistentDrive] Get() { return $this } [bool] TestDirectoryPath() { $present = $false # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Check if persistent drive exist if (Test-Path -Path $this.Path -PathType Container -ErrorAction Ignore) { $mdtShares = (GET-MDTPersistentDrive -ErrorAction SilentlyContinue) If ($mdtShares) { ForEach ($share in $mdtShares) { If ($share.Name -eq $this.Name) { $present = $true } } } } return $present } [void] CreateDirectory() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.Name -PSProvider "MDTProvider" -Root $this.Path -Description $this.Description -NetworkPath $this.NetworkPath -Verbose:$false | ` # Create MDT persistent drive Add-MDTPersistentDrive -Verbose } [void] RemoveDirectory() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule Write-Verbose -Message "Removing MDTPersistentDrive $($this.Name)" # Create PSDrive New-PSDrive -Name $this.Name -PSProvider "MDTProvider" -Root $this.Path -Description $this.Description -NetworkPath $this.NetworkPath -Verbose:$false | ` # Remove MDT persistent drive Remove-MDTPersistentDrive -Verbose } } [DscResource()] class cMDTPreReqs { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Key)] [string]$DownloadPath [DscProperty(Mandatory)] [hashtable]$Prerequisites [void] Set() { Write-Verbose "Starting Set MDT PreReqs..." if ($this.ensure -eq [Ensure]::Present) { $present = $this.TestDownloadPath() if ($present){ Write-Verbose " Download folder present!" } else{ New-Item -Path $this.DownloadPath -ItemType Directory -Force } [string]$separator = "" If ($this.DownloadPath -like "*/*") { $separator = "/" } Else { $separator = "\" } #Set all files: ForEach ($file in $this.Prerequisites) { if($file.MDT){ if(Test-Path -Path "$($this.DownloadPath)\Microsoft Deployment Toolkit"){ Write-Verbose " MDT already present!" } Else{ Write-Verbose " Creating MDT folder..." New-Item -Path "$($this.DownloadPath)\Microsoft Deployment Toolkit" -ItemType Directory -Force $this.WebClientDownload($file.MDT, "$($this.DownloadPath)\Microsoft Deployment Toolkit\MicrosoftDeploymentToolkit2013_x64.msi") } } if($file.ADK){ if(Test-Path -Path "$($this.DownloadPath)\Windows Assessment and Deployment Kit"){ Write-Verbose " ADK folder already present!" } Else{ Write-Verbose " Creating ADK folder..." New-Item -Path "$($this.DownloadPath)\Windows Assessment and Deployment Kit" -ItemType Directory -Force $this.WebClientDownload($file.ADK,"$($this.DownloadPath)\Windows Assessment and Deployment Kit\adksetup.exe") #Run setup to prepp files... } } <# if($file.SQL){ if(Test-Path -Path "$($this.DownloadPath)\Microsoft SQL Server 2014 Express"){ Write-Verbose " SQL folder already present!" } Else{ Write-Verbose " Creating SQL folder..." New-Item -Path "$($this.DownloadPath)\Microsoft SQL Server 2014 Express" -ItemType Directory -Force $this.WebClientDownload($file.SQL,"$($this.DownloadPath)\Microsoft SQL Server 2014 Express\SQLEXPR_x64_ENU.exe") } } #> if(Test-Path -Path "$($this.DownloadPath)\Community"){ Write-Verbose " Community folder already present!" } Else{ Write-Verbose " Creating Community folder..." New-Item -Path "$($this.DownloadPath)\Community" -ItemType Directory -Force New-Item -Path "$($this.DownloadPath)\Community\Scripts" -ItemType Directory -Force New-Item -Path "$($this.DownloadPath)\Community\Control" -ItemType Directory -Force New-Item -Path "$($this.DownloadPath)\Community\PEextraFiles" -ItemType Directory -Force } if($file.C01){ #ToDo: Need test for all files... $this.WebClientDownload($file.C01,"$($this.DownloadPath)\Community\modelalias.zip") $this.ExtractFile("$($this.DownloadPath)\Community\modelalias.zip","$($this.DownloadPath)\Community") Move-Item "$($this.DownloadPath)\Community\ModelAlias\ModelAliasExit.vbs" "$($this.DownloadPath)\Community\Scripts" Remove-Item -Path "$($this.DownloadPath)\Community\ModelAlias" -Force Remove-Item -Path "$($this.DownloadPath)\Community\modelalias.zip" -Force } } } else { $this.RemoveDirectory("") } Write-Verbose "MDT PreReqs set completed!" } [bool] Test() { Write-Verbose "Testing MDT PreReqs..." $present = $this.TestDownloadPath() if ($this.ensure -eq [Ensure]::Present) { Write-Verbose " Testing for download path.." if($present){ Write-Verbose " Download path found!"} Else{ Write-Verbose " Download path not found!" return $present } ForEach ($File in $this.Prerequisites) { if($file.MDT){ Write-Verbose " Testing for MDT..." $present = (Test-Path -Path "$($this.DownloadPath)\Microsoft Deployment Toolkit\MicrosoftDeploymentToolkit2013_x64.msi") Write-Verbose " $present" if($Present){}Else{return $false} } if($file.ADK){ Write-Verbose " Testing for ADK..." $present = (Test-Path -Path "$($this.DownloadPath)\Windows Assessment and Deployment Kit\adksetup.exe") Write-Verbose " $present" if($Present){}Else{return $false} } <# if($file.SQL){ Write-Verbose " Testing for SQL..." $present = (Test-Path -Path "$($this.DownloadPath)\Microsoft SQL Server 2014 Express\SQLEXPR_x64_ENU.exe") Write-Verbose " $present" if($Present){}Else{return $false} } #> if($file.C01){ Write-Verbose " Testing for Community Script: ModelAlias.vbs" $present = (Test-Path -Path "$($this.DownloadPath)\Community\Scripts\ModelAliasExit.vbs") Write-Verbose " $present" if($Present){}Else{return $false} } } } else{ if ($Present){ $present = $false } else{ $present = $true } } Write-Verbose "Test completed!" return $present } [cMDTPreReqs] Get() { return $this } [bool] TestDownloadPath() { $present = $false if (Test-Path -Path $this.DownloadPath -ErrorAction Ignore) { $present = $true } return $present } [bool] VerifyFiles() { [bool]$match = $false if (Get-ChildItem -Path $this.DownloadPath -Recurse) { #ForEach File, test... $match = $true } return $match } [void] WebClientDownload($Source,$Target) { $WebClient = New-Object System.Net.WebClient Write-Verbose " Downloading file $($Source)" Write-Verbose " Downloading to $($Target)" $WebClient.DownloadFile($Source, $Target) } [void] ExtractFile($Source,$Target) { Write-Verbose " Extracting file to $($Target)" Expand-Archive $Source -DestinationPath $Target -Force } [void] CleanTempDirectory($Object) { Remove-Item -Path $Object -Force -Recurse -Verbose:$False } [void] RemoveDirectory($referencefile = "") { Remove-Item -Path $this.DownloadPath -Force -Verbose } [void] RemoveReferenceFile($File) { Remove-Item -Path $File -Force -Verbose:$False } } [DscResource()] class cMDTTaskSequence { [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Name [DscProperty()] [string]$OperatingSystemPath [DscProperty()] [string]$WIMFileName [DscProperty(Mandatory)] [string]$ID [DscProperty(Mandatory)] [string]$PSDriveName [DscProperty(Mandatory)] [string]$PSDrivePath [void] Set() { # Determine present/absent if ($this.ensure -eq [Ensure]::Present) { # Call function to import task sequence $this.ImportTaskSequence() } else { # Remove path recursively Invoke-RemovePath -Path "$($this.path)\$($this.name)" -Recurse -Levels 3 -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } } [bool] Test() { # Test if path exist $present = Invoke-TestPath -Path "$($this.path)\$($this.name)" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath # Return boolean from test method if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [cMDTTaskSequence] Get() { return $this } [void] ImportTaskSequence() { # Import MicrosoftDeploymentToolkitModule module Import-MicrosoftDeploymentToolkitModule # Create PSDrive New-PSDrive -Name $this.PSDriveName -PSProvider "MDTProvider" -Root $this.PSDrivePath -Verbose:$false $OperatingSystemFile = $null If ($this.OperatingSystemPath) { # Get OS file name $OperatingSystemFile = $this.OperatingSystemPath } # Get existing OS file name If ($this.WIMFileName) { $Directory = $this.Name.Replace(" x64","") $Directory = $Directory.Replace(" x32","") $OperatingSystemFiles = (Get-ChildItem -Path "$($this.PSDriveName):\Operating Systems\$($this.Path.Split("\")[-1])") ForEach ($OSFile in $OperatingSystemFiles) { If ($OSFile.Name -like "*$($this.WIMFileName)*") { $OperatingSystemFile = "$($this.PSDriveName):\Operating Systems\$($this.Path.Split("\")[-1])\$($OSFile.Name)" } } } If ($OperatingSystemFile) { # Create path for task sequence if(-not (Test-Path $this.Path)){ Invoke-CreatePath -Path "$($this.PSDriveName):\Task Sequences\$($this.Path.Split("\")[-1])" -PSDriveName $this.PSDriveName -PSDrivePath $this.PSDrivePath -Verbose } # Import task sequence Import-MDTTaskSequence -path $this.Path -Name $this.Name -Template "Client.xml" -Comments "" -ID $this.ID -Version "1.0" -OperatingSystemPath $OperatingSystemFile -FullName "Windows User" -OrgName "Addlevel" -HomePage "about:blank" -Verbose } } } [DscResource()] class cMDT_TS_Step_SetVariable { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$TaskSequenceParentGroupName [DscProperty(Key)] [string]$TaskSequenceVariableName [DscProperty(Key)] [string]$TaskSequenceVariableValue [DscProperty(Key)] [string]$TaskSequenceStepName [DscProperty()] [string]$TaskSequenceStepDescription [DscProperty()] [bool]$Disable [DscProperty()] [bool]$ContinueOnError [DscProperty()] [string]$SuccessCodeList [DscProperty(Key)] [string]$TaskSequenceId [DscProperty(Mandatory)] [string]$PSDrivePath [DscProperty(Mandatory)] [string]$InsertAfterStep [void] Set() { [xml]$xml = $this.ReadTaskSequenceXML() $present = $this.TaskSequenceStepExists() $stepNeedsUpdate = $this.TaskSequenceStepNeedsUpdate() if ($this.Ensure -eq [ensure]::Present -and $present -eq $false) { if ($stepNeedsUpdate) { $this.UpdateTaskSequenceStep($xml) } else { $this.CreateTaskSequenceStep($xml) } } elseif ($this.Ensure -eq [ensure]::Absent -and $present -eq $true) { $this.RemoveTaskSequenceStep($xml) } } [bool] Test() { $present = $this.TaskSequenceStepExists() if ($this.Ensure -eq [ensure]::Present) { return $present } else { return -not $present } } [cMDT_TS_Step_SetVariable] Get() { return $this } [bool] TaskSequenceStepExists() { [xml]$xml = $this.ReadTaskSequenceXML() #Select parent group by name $parentGroup = $xml.SelectSingleNode("sequence/group[@name='$($this.TaskSequenceParentGroupName)']") #Select parent node by name $insertAfterNode = $parentGroup.SelectSingleNode("step[@name='$($this.InsertAfterStep)']") #Next sibling should be the same name as the task sequence step name if it exists. if ($insertAfterNode.NextSibling.name -eq $($this.TaskSequenceStepName)) { if ($this.TaskSequenceStepNeedsUpdate()) { return $false } return $true } return $false } [bool] TaskSequenceStepNeedsUpdate() { [xml]$xml = $this.ReadTaskSequenceXML() $parentGroup = $xml.SelectSingleNode("sequence/group[@name='$($this.TaskSequenceParentGroupName)']") $insertAfterNode = $parentGroup.SelectSingleNode("step[@name='$($this.InsertAfterStep)']") if ($insertAfterNode.NextSibling.name -ne $($this.TaskSequenceStepName)) { return $false } $node = $insertAfterNode.NextSibling $varName = $node.defaultVarList.SelectSingleNode("variable[@name='VariableName']").InnerText $varValue = $node.defaultVarList.SelectSingleNode("variable[@name='VariableValue']").InnerText if ($varName -ne $this.TaskSequenceVariableName) {return $true} if ($varValue -ne $this.TaskSequenceVariableValue) {return $true} if ($node.description -ne $this.TaskSequenceStepDescription) {return $true} if ($node.disable -ne $this.Disable) {return $true} if ($node.continueOnError -ne $this.ContinueOnError) {return $true} if ($node.successCodeList -ne $this.SuccessCodeList) {return $true} return $false } [void] CreateTaskSequenceStep($xml) { $parentGroup = $xml.SelectSingleNode("sequence/group[@name='$($this.TaskSequenceParentGroupName)']") $insertAfterNode = $parentGroup.SelectSingleNode("step[@name='$($this.InsertAfterStep)']") $stepNode = $xml.CreateElement("step") $stepNode.SetAttribute("type","SMS_TaskSequence_SetVariableAction") $stepNode.SetAttribute("name","$($this.TaskSequenceStepName)") $stepNode.SetAttribute("description","$($this.TaskSequenceStepDescription)") $stepNode.SetAttribute("disable","$($this.Disable.ToString().ToLower())") $stepNode.SetAttribute("continueOnError","$($this.ContinueOnError.ToString().ToLower())") $stepNode.SetAttribute("successCodeList","$($this.SuccessCodeList)") $defaultVarListNode = $xml.CreateElement("defaultVarList") $variableNode1 = $xml.CreateElement("variable") $variableNode1.SetAttribute("name","VariableName") $variableNode1.SetAttribute("property","VariableName") $variableNode1.InnerText = "$($this.TaskSequenceVariableName)" $defaultVarListNode.AppendChild($variableNode1) > $null $variableNode2 = $xml.CreateElement("variable") $variableNode2.SetAttribute("name","VariableValue") $variableNode2.SetAttribute("property","VariableValue") $variableNode2.InnerText = "$($this.TaskSequenceVariableValue)" $defaultVarListNode.AppendChild($variableNode2) > $null $stepNode.AppendChild($defaultVarListNode) > $null $actionNode = $xml.CreateElement("action") $actionNode.InnerText = "cscript.exe `"%SCRIPTROOT%\ZTISetVariable.wsf`"" $stepNode.AppendChild($actionNode) > $null $parentGroup.InsertAfter($stepNode,$insertAfterNode) $this.SaveTaskSequenceXML($xml) } [void] UpdateTaskSequenceStep($xml) { $parentGroup = $xml.SelectSingleNode("sequence/group[@name='$($this.TaskSequenceParentGroupName)']") $insertAfterNode = $parentGroup.SelectSingleNode("step[@name='$($this.InsertAfterStep)']") $node = $insertAfterNode.NextSibling $node.SetAttribute("name","$($this.TaskSequenceStepName)") $node.SetAttribute("description","$($this.TaskSequenceStepDescription)") $node.SetAttribute("disable","$($this.Disable.ToString().ToLower())") $node.SetAttribute("continueOnError","$($this.ContinueOnError.ToString().ToLower())") $node.SetAttribute("successCodeList","$($this.SuccessCodeList)") $node.defaultVarList.SelectSingleNode("variable[@name='VariableName']").InnerText = $this.TaskSequenceVariableName $node.defaultVarList.SelectSingleNode("variable[@name='VariableValue']").InnerText = $this.TaskSequenceVariableValue $this.SaveTaskSequenceXML($xml) } [void] RemoveTaskSequenceStep($xml) { $parentGroup = $xml.SelectSingleNode("sequence/group[@name='$($this.TaskSequenceParentGroupName)']") #Select parent node by name $insertAfterNode = $parentGroup.SelectSingleNode("step[@name='$($this.InsertAfterStep)']") #Next sibling should be the same name as the task sequence step name if it exists. if ($insertAfterNode.NextSibling.name -eq $($this.TaskSequenceStepName)) { $node = $insertAfterNode.NextSibling $node.ParentNode.RemoveChild($node) > $null $this.SaveTaskSequenceXML($xml) } } [xml] ReadTaskSequenceXML() { return [xml](Get-Content -Path "$($this.PSDrivePath)\Control\$($this.TaskSequenceId)\ts.xml") } [void] SaveTaskSequenceXML($xml) { $xml.Save("$($this.PSDrivePath)\Control\$($this.TaskSequenceId)\ts.xml") } }[DscResource()] class cMDTUpdateBootImage { [DscProperty(Key)] [string]$Version [DscProperty(Key)] [string]$PSDeploymentShare [DscProperty(Mandatory)] [bool]$Force [DscProperty(Mandatory)] [bool]$Compress [DscProperty(Mandatory)] [string]$DeploymentSharePath [DscProperty()] [string]$ExtraDirectory [DscProperty()] [string]$BackgroundFile [DscProperty()] [string]$LiteTouchWIMDescription [DscProperty()] [string]$FeaturePacks [void] Set() { $this.UpdateBootImage() } [bool] Test() { Return ($this.VerifyVersion()) } [cMDTUpdateBootImage] Get() { return $this } [bool] VerifyVersion() { [bool]$match = $false if ((Get-Content -Path "$($this.DeploymentSharePath)\Boot\CurrentBootImage.version" -ErrorAction Ignore) -eq $this.Version) { $match = $true } return $match } [void] UpdateBootImage() { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $this.PSDeploymentShare -PSProvider "MDTProvider" -Root $this.DeploymentSharePath -Verbose:$false If ([string]::IsNullOrEmpty($($this.ExtraDirectory))) { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.ExtraDirectory -Value "" Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.ExtraDirectory -Value "" } ElseIf (Invoke-TestPath -Path "$($this.DeploymentSharePath)\$($this.ExtraDirectory)") { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.ExtraDirectory -Value "$($this.DeploymentSharePath)\$($this.ExtraDirectory)" Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.ExtraDirectory -Value "$($this.DeploymentSharePath)\$($this.ExtraDirectory)" } If ([string]::IsNullOrEmpty($($this.BackgroundFile))) { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.BackgroundFile -Value "" Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.BackgroundFile -Value "" } ElseIf(Invoke-TestPath -Path "$($this.DeploymentSharePath)\$($this.BackgroundFile)") { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.BackgroundFile -Value "$($this.DeploymentSharePath)\$($this.BackgroundFile)" Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.BackgroundFile -Value "$($this.DeploymentSharePath)\$($this.BackgroundFile)" } If($this.LiteTouchWIMDescription) { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.LiteTouchWIMDescription -Value "$($this.LiteTouchWIMDescription) x64 $($this.Version)" } Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.GenerateLiteTouchISO -Value $false If($this.LiteTouchWIMDescription) { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.LiteTouchWIMDescription -Value "$($this.LiteTouchWIMDescription) x86 $($this.Version)" } Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.GenerateLiteTouchISO -Value $false If ([string]::IsNullOrEmpty($($this.FeaturePacks))) { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.FeaturePacks -Value "" Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.FeaturePacks -Value "" } Else { Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x64.FeaturePacks -Value $($this.FeaturePacks) Set-ItemProperty "$($this.PSDeploymentShare):" -Name Boot.x86.FeaturePacks -Value $($this.FeaturePacks) } #The Update-MDTDeploymentShare command crashes WMI when run from inside DSC. This section is a work around. $aPSDeploymentShare = $this.PSDeploymentShare $aDeploymentSharePath = $this.DeploymentSharePath $aForce = $this.Force $aCompress = $this.Compress $jobArgs = @($aPSDeploymentShare,$aDeploymentSharePath,$aForce,$aCompress) $job = Start-Job -Name UpdateMDTDeploymentShare -Scriptblock { Import-Module "$env:ProgramFiles\Microsoft Deployment Toolkit\Bin\MicrosoftDeploymentToolkit.psd1" -ErrorAction Stop -Verbose:$false New-PSDrive -Name $args[0] -PSProvider "MDTProvider" -Root $args[1] -Verbose:$false Update-MDTDeploymentShare -Path "$($args[0]):" -Force:$args[2] -Compress:$args[3] } -ArgumentList $jobArgs $job | Wait-Job -Timeout 1800 $timedOutJobs = Get-Job -Name UpdateMDTDeploymentShare | Where-Object {$_.State -eq 'Running'} | Stop-Job -PassThru If ($timedOutJobs) { Write-Error "Update-MDTDeploymentShare job exceeded timeout limit of 900 seconds and was aborted" } Else { Set-Content -Path "$($this.DeploymentSharePath)\Boot\CurrentBootImage.version" -Value "$($this.Version)" } } } [DscResource()] class cWDSBootImage { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$Path [DscProperty(Key)] [string]$Version [DscProperty(Key)] [string]$ImageName [void] Set() { if ($this.Ensure -eq [Ensure]::Present) { $this.AddBootImage() } else { $this.RemoveBootImage() } } [bool] Test() { Return ($this.VerifyVersion()) } [cWDSBootImage] Get() { return $this } [bool] VerifyVersion() { [bool]$match = $false $foldername = $this.Path.Replace("\$($this.Path.Split("\")[-1])","") if ((Get-Content -Path "$($foldername)\WSDBootImage.version" -ErrorAction Ignore) -eq $this.Version) { $match = $true } return $match } [bool] DoesBootImageExist() { return ((Get-WdsBootImage -ImageName $this.ImageName) -ne $null) } [void] AddBootImage() { If ($this.DoesBootImageExist()) { $this.RemoveBootImage() } Import-WdsBootImage -Path $this.Path -NewImageName $this.ImageName �SkipVerify | Out-Null $foldername = $this.Path.Replace("\$($this.Path.Split("\")[-1])","") if (-not (Get-Content -Path "$($foldername)\WSDBootImage.version" -ErrorAction Ignore)) { New-ReferenceFile -Path "$($foldername)\WSDBootImage.version" } Set-Content -Path "$($foldername)\WSDBootImage.version" -Value "$($this.Version)" } [void] RemoveBootImage() { Get-WdsBootImage -ImageName $this.ImageName | Remove-WdsBootImage } } [DscResource()] class cWDSConfiguration { [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty(Key)] [string]$RemoteInstallPath [void] Set() { if ($this.Ensure -eq [Ensure]::Present) { $this.InitializeServer() } else { $this.UninitializeServer() } } [bool] Test() { $present = $this.DoesRemoteInstallFolderExist() if ($this.Ensure -eq [Ensure]::Present) { return $present } else { return -not $present } } [bool] IsPartOfDomain() { return (Get-CimInstance -ClassName Win32_ComputerSystem).PartOfDomain } [cWDSConfiguration] Get() { return $this } [bool] DoesRemoteInstallFolderExist() { return (Test-Path $this.RemoteInstallPath -ErrorAction Ignore) } [void] InitializeServer() { if ($this.IsPartOfDomain()) { & WDSUTIL /Initialize-Server /RemInst:"$($this.RemoteInstallPath)" /Authorize } else { & WDSUTIL /Initialize-Server /RemInst:"$($this.RemoteInstallPath)" /Standalone } & WDSUTIL /Set-Server /AnswerClients:All } [void] UninitializeServer() { & WDSUTIL /Uninitialize-Server } } Function Compare-Version { [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Source, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Target ) [bool]$match = $false if ((Get-Content -Path $Source) -eq $Target) { $match = $true } return $match } Function Get-FileNameFromPath { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Separator ) [string]$fileName = $Path.Split($Separator)[-1] return $fileName } Function Get-FileTypeFromPath { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Separator ) [string]$fileType = ($Path.Split($Separator)[-1]).Split(".")[-1] return $fileType } Function Get-FolderNameFromPath { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Separator ) [string]$folderName = $Path.Replace("\$($Path.Split($Separator)[-1])","") return $folderName } Function Get-Separator { [CmdletBinding()] [OutputType([String])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path ) [string]$separator = "" If ($Path -like "*/*") { $separator = "/" } Else { $separator = "\" } return $separator } Function Get-Separator { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path ) [string]$separator = "" If ($Path -like "*/*") { $separator = "/" } Else { $separator = "\" } return $separator } Function Import-MicrosoftDeploymentToolkitModule { If (-Not(Get-Module MicrosoftDeploymentToolkit)) { Import-Module "$env:ProgramFiles\Microsoft Deployment Toolkit\Bin\MicrosoftDeploymentToolkit.psd1" -ErrorAction Stop -Global -Verbose:$False } } Function Invoke-CreatePath { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter()] [string]$PSDriveName, [Parameter()] [string]$PSDrivePath ) [bool]$present = $false if (($PSDrivePath) -and ($PSDriveName)) { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $PSDriveName -PSProvider "MDTProvider" -Root $PSDrivePath -Verbose:$false $Script:Directory = $($($Path.Split("\"))[0]) For ($i=1; $i -le $($Path.Split("\").Count-1); $i++) { $Script:Directory += "\$($($Path.Split("\"))[$i])" If(-not(Invoke-TestPath -Path $Script:Directory -PSDriveName $PSDriveName -PSDrivePath $PSDrivePath -Verbose)) { Try { New-Item -ItemType Directory -Path $Script:Directory -Verbose If ($this.Debug) { Invoke-Logger -Message "Successfully created: $Directory" -Severity D -Category "DIRECTORY" -Type "CREATE" } $present = $true } Catch { If ($this.Debug) { Invoke-Logger -Severity E -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } } } } else { $Script:Directory = $($($Path.Split("\"))[0]) For ($i=1; $i -le $($Path.Split("\").Count-1); $i++) { $Script:Directory += "\$($($Path.Split("\"))[$i])" If(-not(Invoke-TestPath -Path $Script:Directory -Verbose)) { Try { New-Item -ItemType Directory -Path $Script:Directory -Verbose If ($this.Debug) { Invoke-Logger -Message "Successfully created: $Directory" -Severity D -Category "DIRECTORY" -Type "CREATE" } $present = $true } Catch { If ($this.Debug) { Invoke-Logger -Severity E -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } } } } return $present } Function Invoke-ExpandArchive { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Source, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Target ) [bool]$Verbosity If($PSBoundParameters.Verbose) { $Verbosity = $True } Else { $Verbosity = $False } Write-Verbose "Expanding archive $($Source) to $($Target)" Expand-Archive $Source -DestinationPath $Target -Force -Verbose:$Verbosity } Function Invoke-Logger { param( [String]$Severity, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [String]$Category, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [String]$Type, $Message, $Error ) Switch ($Severity) { "I" { $Severity = "INFO" } "D" { $Severity = "DEBUG" } "W" { $Severity = "WARNING" } "E" { $Severity = "ERROR"} default { $Severity = "INFO" } } $date = [datetime]::UtcNow For ($x=$Severity.Length; $x -le 6; $x++) { $Severity = $Severity+" " } For ($x=$Category.Length; $x -le 7; $x++) { $Category = $Category+" " } For ($x=$Type.Length; $x -le 7; $x++) { $Type = $Type+" " } If ($Error) { ForEach ($Line in $Message) { Write-Log -Message "[$(Get-Date $date -UFormat '%Y-%m-%dT%T%Z')] [$($Severity)] [$($Category)] [$($Type)] [$($Line)]" } If ($Error.Exception.Message) { Write-Log -Message "[$(Get-Date $date -UFormat '%Y-%m-%dT%T%Z')] [$($Severity)] [$($Category)] [$($Type)] [$($Error.Exception.Message)]" } If ($Error.Exception.Innerexception) { Write-Log -Message "[$(Get-Date $date -UFormat '%Y-%m-%dT%T%Z')] [$($Severity)] [$($Category)] [$($Type)] [$($Error.Exception.Innerexception)]" } If ($Error.InvocationInfo.PositionMessage) { ForEach ($Line in $Error.InvocationInfo.PositionMessage.Split("`n")) { Write-Log -Message "[$(Get-Date $date -UFormat '%Y-%m-%dT%T%Z')] [$($Severity)] [$($Category)] [$($Type)] [$($Line)]" } } } Else { If ($Message) { If (($Message.GetType()).Name -eq "Hashtable") { Get-RecursiveProperties -Value $Message } Else { ForEach ($Line in $Message) { Write-Log -Message "[$(Get-Date $date -UFormat '%Y-%m-%dT%T%Z')] [$($Severity)] [$($Category)] [$($Type)] [$($Line)]" } } } } } #<![LOG[Report state message 0x40000950 to MP]LOG]!><time="01:38:47.034-120" date="07-16-2016" component="SMS_Distribution_Point_Monitoring" context="" type="1" thread="12172" file="smsdpmon.cpp:889"> #<![LOG[Begin validation of Certificate [Thumbprint 5F1966C815ADC9B25E8D9979917E26B5396D9154] issued to 'winPE.dec.addlevel.net']LOG]!><time="19:25:40.755-120" date="05-27-2016" component="SMSPXE" context="" type="1" thread="7484" file="ccmcert.cpp:1715"> Function Invoke-RemovePath { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter()] [string]$PSDriveName, [Parameter()] [string]$PSDrivePath, [Parameter()] [int32]$Levels, [Parameter()] [switch]$Recurse ) [bool]$Verbosity If($PSBoundParameters.Verbose) { $Verbosity = $True } Else { $Verbosity = $False } if (($PSDrivePath) -and ($PSDriveName)) { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $PSDriveName -PSProvider "MDTProvider" -Root $PSDrivePath -Verbose:$False Try { Remove-Item -Path $Path -Force -Verbose:$Verbosity If ($this.Debug) { Invoke-Logger -Message "Successfully removed: $Path" -Severity D -Category "DIRECTORY" -Type "REMOVE" } } Catch { If ($this.Debug) { Invoke-Logger -Severity E -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } If ($Recurse) { $Script:Dir = $Path For ($i=$($Path.Split("\").Count-1); $i -ge $Levels; $i--) { $Script:Dir = $Script:Dir.Replace("\$($($Path.Split("\"))[$i])","") If(-not(Invoke-TestPath -Path "$Dir\*" -PSDriveName $PSDriveName -PSDrivePath $PSDrivePath -Verbose)) { Try { Remove-Item -Path $Dir -Force -Verbose:$Verbosity If ($this.Debug) { Invoke-Logger -Message "Successfully removed: $Dir" -Severity D -Category "DIRECTORY" -Type "REMOVE" } } Catch { If ($this.Debug) { Invoke-Logger -Severity E -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } } } } } else { Try { Remove-Item -Path $Path -Force -Verbose:$Verbosity If ($this.Debug) { Invoke-Logger -Message "Successfully removed: $Path" -Severity D -Category "DIRECTORY" -Type "REMOVE" } } Catch { If ($this.Debug) { Invoke-Logger -Severity E -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } If ($Recurse) { $Script:Dir = $Path For ($i=$($Path.Split("\").Count-1); $i -ge 4; $i--) { $Script:Dir = $Script:Dir.Replace("\$($($Path.Split("\"))[$i])","") If(-not(Invoke-TestPath -Path "$Dir\*" -Verbose)) { Try { Remove-Item -Path $Dir -Force -Verbose:$Verbosity If ($this.Debug) { Invoke-Logger -Message "Successfully removed: $Dir" -Severity D -Category "DIRECTORY" -Type "REMOVE" } } Catch { Invoke-Logger -Severity "E" -Category "DIRECTORY" -Type "CREATE" -Error $Error[0] } } } } } } Function Invoke-TestPath { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter()] [string]$PSDriveName, [Parameter()] [string]$PSDrivePath ) [bool]$present = $false if (($PSDrivePath) -and ($PSDriveName)) { Import-MicrosoftDeploymentToolkitModule if (New-PSDrive -Name $PSDriveName -PSProvider "MDTProvider" -Root $PSDrivePath -Verbose:$false | ` Test-Path -Path $Path -ErrorAction Ignore) { $present = $true } } else { if (Test-Path -Path $Path -ErrorAction Ignore) { $present = $true } } return $present } Function Invoke-WebDownload { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Source, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Target ) [bool]$Verbosity If($PSBoundParameters.Verbose) { $Verbosity = $True } Else { $Verbosity = $False } If ($Source -like "*/*") { If (Get-Service BITS | Where-Object {$_.status -eq "running"}) { If ($Verbosity) { Write-Verbose "Downloading file $($Source) via Background Intelligent Transfer Service" } Import-Module BitsTransfer -Verbose:$false Start-BitsTransfer -Source $Source -Destination $Target -Verbose:$Verbosity Remove-Module BitsTransfer -Verbose:$false } else { If ($Verbosity) { Write-Verbose "Downloading file $($Source) via System.Net.WebClient" } $WebClient = New-Object System.Net.WebClient $WebClient.DownloadFile($Source, $Target) } } Else { If (Get-Service BITS | Where-Object {$_.status -eq "running"}) { If ($Verbosity) { Write-Verbose "Downloading file $($Source) via Background Intelligent Transfer Service" } Import-Module BitsTransfer -Verbose:$false Start-BitsTransfer -Source $Source -Destination $Target -Verbose:$Verbosity } Else { Copy-Item $Source -Destination $Target -Force -Verbose:$Verbosity } } } Function New-ReferenceFile { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [string]$Path, [Parameter()] [string]$PSDriveName, [Parameter()] [string]$PSDrivePath ) if (($PSDrivePath) -and ($PSDriveName)) { Import-MicrosoftDeploymentToolkitModule New-PSDrive -Name $PSDriveName -PSProvider "MDTProvider" -Root $PSDrivePath -Verbose:$false | ` New-Item -Type File -Path $Path -Force -Verbose:$False } else { New-Item -Type File -Path $Path -Force -Verbose:$False } } Function Write-Log { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] $Message ) [String]$LogFile = "$($PSScriptRoot)\$(Get-Date -Format "yyyy-MM-dd")_cMDT.log" Out-File -FilePath $LogFile -InputObject $Message -Encoding utf8 -Append -NoClobber #Write-Verbose $Message } |