For those of you following my blog, please note that I am now blogging on a new site I have created with a friend of mine @TerenceBeggs.
Visit http://deployeverything.com for more content.
For those of you following my blog, please note that I am now blogging on a new site I have created with a friend of mine @TerenceBeggs.
Visit http://deployeverything.com for more content.
The majority of SCCM administrators will have included a list of maintenance tasks for ensuring optimum performance of their environment. One area that often gets overlooked however is the maintenance of IIS logs. The logs are obviously useful for troubleshooting purposes, however do you really need to know what was happening say over 30 days ago. The truth is if there was an issue you probably would have spotted it very early on and dealt with it.
So how do you deal with log files within your IIS directory filling up your disks?. The answer can be to setup a configuration item and let SCCM take care of its own compliance.
To start with you will need to create a Device Collection to deploy the Configuration Item and subsequent Baseline to. This can be achieved by creating a device collection using the following query;
select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ResourceNames in (Select ServerName FROM SMS_DistributionPointInfo)
Creating Your SCCM IIS Prune Logs Configuration Item
Once you have the device collection created and populated you can go on to create the Configuration Item to be used. To speed up this process I have exported the CI CAB for you to download, below are some screen shots of the manual creation process;
Download – Prune IIS Logs
In this section we will pick which operating systems are applicable for SCCM distribution points
Here we will create a new setting entry that will contain both the discovery and remediation scripts required
Discovery Script
# Specify the maximum log age file to maintain $MaxDays = 7 function DiscoverIISLogs ($MaxDays) { try { # Import IIS WebAdmin Module Import-Module WebAdministration # Return list of IIS webistes $IISSites = Get-Website # Loop for each IIS site foreach ($Site in $IISSites) { # Return path for IIS logs $IISLogs = $Site.LogFile.Directory # Condition to replace DOS %SystemDrive% variable with Powershell variable If ($IISLogs -like "*%SystemDrive%*") { $IISLogs = $IISLogs -replace "%SystemDrive%", "$env:SystemDrive" } # Count IIS Log files to prune $LogCount = $LogCount + (Get-ChildItem -Path $IISLogs -Recurse -Filter "*.log" | Where-Object { $(Get-Date).Subtract($_.LastWriteTime).Days -gt $MaxDays}).count } Return $LogCount } catch { return -1 } } DiscoverIISLogs ($MaxDays)
Remediation Script
# Specify the maximum log age file to maintain $MaxDays = 30 function PurgeIISLogs ($MaxDays) { try { # Import IIS WebAdmin Module Import-Module WebAdministration # Return list of IIS webistes $IISSites = Get-Website # Loop for each IIS site foreach ($Site in $IISSites) { # Return path for IIS logs $IISLogs = $Site.LogFile.Directory # Condition to replace DOS %SystemDrive% variable with Powershell variable If ($IISLogs -like "*%SystemDrive%*") { $IISLogs = $IISLogs -replace "%SystemDrive%", "$env:SystemDrive" } # Purge IIS Log files Get-ChildItem -Path $IISLogs -Recurse -Filter "*.log" | Where-Object { $(Get-Date).Subtract($_.LastWriteTime).Days -gt $MaxDays } | Foreach-Object { Remove-Item $_.FullName -Force -Verbose } } } catch { } } PurgeIISLogs ($MaxDays)
Here we will specify when to run the remediation script you created in the previous step
Now in order to apply the Configuration Item we will need to create a Configuration Baseline for the SCCM Server Device Collection.
Here we will add the Configuration Baseline we created earlier;
Set your schedule and generate an alert if required..
Now sit back, relax and watch your good work take hold across your estate;
Below we have the before and after results of a distribution point running a low workload;
When you have a large environment with thousands of clients you can clearly see the storage recovery benefits!.
If you want to run the script manually or deploy as a scheduled task, you can use the below PowerShell script (Download from https://gallery.technet.microsoft.com/scriptcenter/IIS-Log-Maintenance-6f357306);
<# .NOTES =========================================================================== Created on: 07/11/2016 22:05 Created by: Terence Beggs & Maurice Daly - DeployEverything.com Organization: Filename: PruneIISLogs.ps1 =========================================================================== .DESCRIPTION Clear up script for IIS logs. Removes logs older than the value specified in the MaxDays variable. The script can be used as part of a Configuration Item in SCCM or as a scheduled task. #> # Specify the maximum log age file to maintain $MaxDays = 7 function DiscoverIISLogs ($MaxDays) { try { # Import IIS WebAdmin Module Import-Module WebAdministration # Return list of IIS webistes $IISSites = Get-Website # Loop for each IIS site foreach ($Site in $IISSites) { # Return path for IIS logs $IISLogs = $Site.LogFile.Directory # Condition to replace DOS %SystemDrive% variable with Powershell variable If ($IISLogs -like "*%SystemDrive%*") { $IISLogs = $IISLogs -replace "%SystemDrive%", "$env:SystemDrive" } # Count IIS Log files to prune $LogCount = $LogCount + (Get-ChildItem -Path $IISLogs -Recurse -Filter "*.log" | Where-Object { $(Get-Date).Subtract($_.LastWriteTime).Days -gt $MaxDays}).count } Return $LogCount } catch { return -1 } } DiscoverIISLogs ($MaxDays) function PurgeIISLogs ($MaxDays) { try { # Import IIS WebAdmin Module Import-Module WebAdministration # Return list of IIS webistes $IISSites = Get-Website # Loop for each IIS site foreach ($Site in $IISSites) { # Return path for IIS logs $IISLogs = $Site.LogFile.Directory # Condition to replace DOS %SystemDrive% variable with Powershell variable If ($IISLogs -like "*%SystemDrive%*") { $IISLogs = $IISLogs -replace "%SystemDrive%", "$env:SystemDrive" } # Purge IIS Log files Get-ChildItem -Path $IISLogs -Recurse -Filter "*.log" | Where-Object { $(Get-Date).Subtract($_.LastWriteTime).Days -gt $MaxDays } | Foreach-Object { Remove-Item $_.FullName -Force -Verbose } } } catch { } } PurgeIISLogs ($MaxDays)
A special thanks goes out to Johan Arwidmark for sharing this clean up script on his DeploymentResearch blog (http://deploymentresearch.com/Research/Post/563/A-little-bit-of-ConfigMgr-housekeeping).
Back in September back I posted a PowerShell script to allow the automatic querying of Dell client models from your SCCM environment, download the associated drivers and bios updates and import them into SCCM (https://modalyitblog.com/2016/10/10/sccm-dell-client-bios-driver-autodownload-ps-script/). The script had the initial task of automating the following steps for your Dell driver imports;
I had a lot of great feedback on the script and I am happy to hear it helped a lot of you automate your driver update process. Since the script was released I have had a lot of requests to provide the same functionality for MDT and also to provide more command line functionality such as downloading drivers only and specifying the number of concurrent jobs as not to stress out your SCCM server during the import phase.
So here is version 4.0 of the script!
It has been significantly modified from the original and as requested it now provides driver imports into MDT (either a standalone environment or an MDT instance on your SCCM server), driver revisions, more error checking and a host of other features.
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 16/10/2016 13:00 Created by: Maurice Daly Filename: DellDownloads.ps1 =========================================================================== .DESCRIPTION This script allows you to automate the process of keeping your Dell driver and BIOS update sources up to date. The script reads the Dell SCCM driver pack site for models you have specified and then downloads the corresponding latest driver packs and BIOS updates. Version 1.0 -Retreive Dell models and download BIOS and Driver Packs Version 2.0 -Added driver CAB file extract, create new driver pack, category creation and import driver functions. Version 2.1 -Added multi-threading Version 2.2 -Added Max Concurrent jobs setting for limiting CPU utilisation Version 2.3 -Replaced Invoke-WebRequest download with BITS enabled downloads for improved performance Version 2.4 -Updated code and separated functions. Added required variables via commandline Version 3.0 -Creates BIOS Packages for each model and writes update powershell file for deployment with SCCM. Version 4.0 -Added support for MDT driver imports -Added operating system selection into the command line -Option to skip BIOS downloads -Validation for OS driver pack download for each model Version 4.1 -Added support for BIOS only downloads for SCCM .EXAMPLE In the below example the script will run the download and import process for both SCCM and MDT. Both sets of BIOS and Driver packages will be downloaded, in this instance for Windows 10 x64 DellDownloads.ps1 -ImportInto Both -DownloadType All -SiteServer YourSiteServer -RepositoryPath \\SERVER\Drivers -PackagePath \\SERVER\DriverPacks -WindowsVersion 10 -Architecture x64 In this example the script will run the download and import process for MDT only. Only the Driver packages will be downloaded, in this instance for Windows 10 x64. Note that you will be prompted for a path to a CSV containing the models you wish to download drivers for. DellDownloads.ps1 -ImportInto MDT -DownloadType Drivers -RepositoryPath \\SERVER\Drivers -WindowsVersion 10 -Architecture x64 -MDTCSVSource ".\MDTModels.csv" Use : This script is provided as it and I accept no responsibility for any issues arising from its use. Twitter : @modaly_it Blog : https://modalyitblog.com/ Credits MDT Import Script Source - https://scriptimus.wordpress.com/2012/06/18/mdt-powershell-importing-drivers/ SCCM Model Query Script - http://www.scconfigmgr.com/2015/04/14/get-device-models-in-configmgr-2012-with-powershell/ #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, HelpMessage = "Import drivers into which product? SCCM, MDT or Both?", Position = 1)] [ValidateSet("SCCM", "MDT", "Both")] [String]$ImportInto, [parameter(Mandatory = $true, HelpMessage = "Download just BIOS updates, driver packages or both?", Position = 2)] [ValidateSet("All", "Drivers", "BIOS")] [String]$DownloadType, [parameter(Mandatory = $false, HelpMessage = "Site server where the SMS Provider is installed", Position = 3)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Connection -ComputerName $_ -Count 1 -Quiet })] [string]$SiteServer, [parameter(Mandatory = $true, HelpMessage = "UNC path for downloading and extracting drivers", Position = 4)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$RepositoryPath, [parameter(Mandatory = $false, HelpMessage = "UNC path of your driver package repository", Position = 5)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$PackagePath, [parameter(Mandatory = $false, HelpMessage = "Source path to the CSV containing your list of models for MDT", Position = 6)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$MDTCSVSource, [parameter(Mandatory = $true, HelpMessage = "Please select an operating system", Position = 7)] [ValidateSet("7", "8", "8.1", "10")] [String]$WindowsVersion, [parameter(Mandatory = $true, HelpMessage = "Please select an operating system", Position = 8)] [ValidateSet("x86", "x64")] [String]$Architecture, [parameter(Mandatory = $false, HelpMessage = "Set the maximum number of current jobs", Position = 9)] [ValidateSet("1", "2", "3", "4", "5")] [String]$MaxConcurrentJobs ) Clear-Host # Import SCCM PowerShell Module $ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1" Import-Module $ModuleName # Defaults maximum concurrent jobs to 3 if the value is not set in the commandline if ($MaxConcurrentJobs -eq $null) { $MaxConcurrentJobs = 3 } # Query SCCM Site Code function QuerySiteCode ($SiteServer) { Write-Debug "Determining SiteCode for Site Server: '$($SiteServer)'" $SiteCodeObjects = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop foreach ($SiteCodeObject in $SiteCodeObjects) { if ($SiteCodeObject.ProviderForLocalSite -eq $true) { $SiteCode = $SiteCodeObject.SiteCode Write-Debug "SiteCode: $($SiteCode)" } } Return [string]$SiteCode } function QueryModels ($SiteCode) { # ArrayList to store the Dell models in $DellProducts = New-Object -TypeName System.Collections.ArrayList # Enumerate through all models $Models = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_G_System_COMPUTER_SYSTEM | Select-Object -Property Model | Where-Object { ($_.Model -like "*Optiplex*") -or ($_.Model -like "*Latitude*") } # Add model to ArrayList if not present if ($Models -ne $null) { foreach ($Model in $Models) { if ($Model.Model -notin $DellProducts) { $DellProducts.Add($Model.Model) | Out-Null } } } Return $DellProducts } function SCCMDownloadAndPackage ($PackagePath, $RepositoryPath, $SiteCode, $DellProducts, $WindowsVersion, $Architecture, $DownloadType, $ImportInto, $MaxConcurrentJobs) { $RunDownloadJob = { Param ($Model, $SiteCode, $PackagePath, $RepositoryPath, $OperatingSystem, $Architecture, $DownloadType, $MaxConcurrentJobs) # =================== DEFINE VARIABLES ===================== # Define Dell Download Sources $DellDownloadList = "http://downloads.dell.com/published/Pages/index.html" $DellDownloadBase = "http://downloads.dell.com" $DellSCCMDriverList = "http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment" $DellSCCMBase = "http://en.community.dell.com" # Import SCCM PowerShell Module $ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1" Import-Module $ModuleName # Directory used for driver and BIOS downloads $DriverRepositoryRoot = ($RepositoryPath.Trimend("\") + "\Dell\") Write-Host "Driver package path set to $DriverRepositoryRoot" # Directory used by SCCM for driver package $DriverPackageRoot = ($PackagePath.Trimend("\") + "\Dell\") Write-Host "Driver package path set to $DriverPackageRoot" # ========================================================== # =================== INITIATE DOWNLOADS =================== # ========================================================== if ($DownloadType -ne "Drivers") { # ================= BIOS Upgrade Download ================== Write-Host "Getting download URL for Dell client model: $Model" $ModelLink = (Invoke-WebRequest -Uri $DellDownloadList).Links | Where-Object { $_.outerText -eq $Model } $ModelURL = (Split-Path $DellDownloadList -Parent) + "/" + ($ModelLink.href) # Correct slash direction issues $ModelURL = $ModelURL.Replace("\", "/") $BIOSDownload = (Invoke-WebRequest -Uri $ModelURL -UseBasicParsing).Links | Where-Object { ($_.outerHTML -like "*BIOS*") -and ($_.outerHTML -like "*WINDOWS*") } | select -First 1 $BIOSFile = $BIOSDownload.href | Split-Path -Leaf If ($BIOSDownload -ne $null) { # Check for destination directory, create if required and download the BIOS upgrade file if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\BIOS")) -eq $true) { if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile)) -eq $false) { Write-Host -ForegroundColor Green "Downloading $($BIOSFile) BIOS update file" # Invoke-WebRequest ($DellDownloadBase + $BIOSDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) -UseBasicParsing Start-BitsTransfer ($DellDownloadBase + $BIOSDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) } else { Write-Host -ForegroundColor Yellow "Skipping $BIOSFile... File already downloaded..." } } else { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\BIOS") Write-Host -ForegroundColor Green "Downloading $($BIOSFile) BIOS update file" # Invoke-WebRequest ($DellDownloadBase + $BIOSDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) -UseBasicParsing Start-BitsTransfer ($DellDownloadBase + $BIOSDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) } # ================= Create BIOS Update Package ================== $BIOSUpdatePackage = ("Dell" + " " + $Model + " " + "BIOS UPDATE") $BIOSUpdateRoot = ($DriverRepositoryRoot + $Model + "\BIOS\") Set-Location -Path ($SiteCode + ":") if ((Get-CMPackage -name $BIOSUpdatePackage) -eq $null) { Write-Host -ForegroundColor Green "Creating BIOS Package" New-CMPackage -Name "$BIOSUpdatePackage" -Path $BIOSUpdateRoot -Description "Dell $Model BIOS Updates" -Manufacturer "Dell" -Language English } Set-Location -Path $env:SystemDrive $BIOSUpdateScript = ($BIOSUpdateRoot + "BIOSUpdate.ps1") $CurrentBIOSFile = Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse | Sort-Object $_.LastWriteTime | select -First 1 if ((Test-Path -Path $BIOSUpdateScript) -eq $False) { # Create BIOSUpdate.ps1 Deployment Script New-Item -Path ($BIOSUpdateRoot + "BIOSUpdate.ps1") -ItemType File $BIOSSwitches = " -noreboot -nopause " Add-Content -Path $BIOSUpdateScript ('$CurrentBIOSFile=' + '"' + $($CurrentBIOSFile.name) + '"') Add-Content -Path $BIOSUpdateScript ('$BIOSSwitches=' + '"' + $($BIOSSwitches) + '"') Add-Content -Path $BIOSUpdateScript ('Start-Process $CurrentBIOSFile -ArgumentList $BIOSSwitches') } else { # Check if older BIOS update exists and update BIOSUpdate deployment script $BIOSFileCount = (Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse).count if ($BIOSFileCount -gt 1) { $OldBIOSFiles = Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse | Where-Object { $_.Name -ne $CurrentBIOSFile.name } foreach ($OldBIOS in $OldBIOSFiles) { (Get-Content -Path $BIOSUpdateScript) -replace $OldBIOS.name, $CurrentBIOSFile.name | Set-Content -Path $BIOSUpdateScript } } } # =============== Refresh Distribution Points ================= Set-Location -Path ($SiteCode + ":") Get-CMPackage -name $BIOSUpdatePackage | Update-CMDistributionPoint Set-Location -Path $env:SystemDrive } } if ($DownloadType -ne "BIOS") { # =============== SCCM Driver Cab Download ================= Write-Host "Getting SCCM driver pack link for model: $Model" $ModelLink = (Invoke-WebRequest -Uri $DellSCCMDriverList -UseBasicParsing).Links | Where-Object { ($_.outerHTML -like "*$Model*") -and ($_.outerHTML -like "*$OperatingSystem*") } | select -First 1 $ModelURL = $DellSCCMBase + ($ModelLink.href) If ($ModelURL -ne $null) { $ModelURL = $ModelURL.Replace("\", "/") $SCCMDriverDownload = (Invoke-WebRequest -Uri $ModelURL -UseBasicParsing).Links | Where-Object { $_.href -like "*.cab" } $SCCMDriverCab = $SCCMDriverDownload.href | Split-Path -Leaf $DriverSourceCab = ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) $DriverPackageDir = ($DriverSourceCab | Split-Path -Leaf) $DriverPackageDir = $DriverPackageDir.Substring(0, $DriverPackageDir.length - 4) $DriverCabDest = $DriverPackageRoot + $DriverPackageDir $DriverRevision = ($DriverPackageDir).Split("-")[2] $DriverCategoryName = (('"' + 'Dell ' + $Model + '"') + "," + ("$DriverRevision")) $DriverExtractDest = ($DriverRepositoryRoot + $Model + "\" + $DriverRevision) # Check for destination directory, create if required and download the driver cab if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab)) -eq $false) { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\Driver Cab") Write-Host -ForegroundColor Green "Downloading $($SCCMDriverCab) driver cab file" Start-BitsTransfer -Source ($SCCMDriverDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) } else { Write-Host -ForegroundColor Yellow "Skipping $SCCMDriverCab... Driver pack already downloaded..." $SkipDriverImport = $True } # =============== Create Driver Package + Import Drivers ================= if ((Test-Path -Path ($DriverCabDest)) -eq $false) { New-Item -Type dir -Path $DriverExtractDest New-Item -Type dir -Path $DriverCabDest Set-Location -Path ($SiteCode + ":") $CMDDriverPackage = ("Dell " + $Model + " - " + $OperatingSystem + " " + $Architecture) Write-Host -ForegroundColor Green "Creating driver package" Set-Location -Path $env:SystemDrive Expand "$DriverSourceCab" -F:* "$DriverExtractDest" $DriverINFFiles = Get-ChildItem -Path $DriverExtractDest -Recurse -Filter "*.inf" | Where-Object { $_.FullName -like "*$Architecture*" } Set-Location -Path ($SiteCode + ":") if (Get-CMCategory -CategoryType DriverCategories -name $DriverCategoryName) { Write-Host -ForegroundColor Yellow "Category already exists" $DriverCategory = Get-CMCategory -CategoryType DriverCategories -name $DriverCategoryName } else { Write-Host -ForegroundColor Green "Creating category" $DriverCategory = New-CMCategory -CategoryType DriverCategories -name $DriverCategoryName } Write-Host -ForegroundColor Green "Creating Driver Package for Dell $Model" New-CMDriverPackage -Name $CMDDriverPackage -path ($DriverPackageRoot + $DriverPackageDir + "\" + $Architecture) Set-CMDriverPackage -Name $CMDDriverPackage -Version $DriverRevision $DriverPackage = Get-CMDriverPackage -Name $CMDDriverPackage foreach ($DriverINF in $DriverINFFiles) { $DriverInfo = Import-CMDriver -UncFileLocation ($DriverINF.FullName) -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True -AdministrativeCategory $DriverCategory | Select-Object * Add-CMDriverToDriverPackage -DriverID $DriverInfo.CI_ID -DriverPackageName "$($CMDDriverPackage)" -WarningAction SilentlyContinue -ErrorAction SilentlyContinue } } else { Write-Host -ForegroundColor Yellow "Driver Package Already Exists.. Skipping" } Set-Location -Path $env:SystemDrive } else { Write-Host -ForegroundColor Red "Operating system driver package download path not found.. Skipping $Model" } } } # Operating System Version $OperatingSystem = ("Windows " + $WindowsVersion) $TotalModelCount = $DellProducts.Count $RemainingModels = $TotalModelCount foreach ($Model in $DellProducts) { Write-Progress -activity "Initiate Driver Download & Driver Package Jobs" -status "Progress:" -percentcomplete (($TotalModelCount - $RemainingModels)/$TotalModelCount * 100) $RemainingModels-- $Check = $false while ($Check -eq $false) { if ((Get-Job -State 'Running').Count -lt $MaxConcurrentJobs) { Start-Job -ScriptBlock $RunDownloadJob -ArgumentList $Model, $SiteCode, $PackagePath, $RepositoryPath, $OperatingSystem, $Architecture, $DownloadType -Name ($Model + " Download") $Check = $true } } } Get-Job | Wait-Job | Receive-Job Get-Job | Remove-Job if ($ImportInto -eq "Both") { # =============== MDT Driver Import ==================== Write-Host -ForegroundColor Green "Starting MDT Driver Import Process" # Import MDT Module Import-Module "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1" # Detect First MDT PSDrive If (!$PSDriveName) { $PSDriveName = (Get-MDTPersistentDrive)[0].name } # Detect First MDT Deployment Share If (!$DeploymentShare) { $DeploymentShare = (Get-MDTPersistentDrive)[0].path } $MDTDriverPath = $PSDriveName + ':\Out-of-Box Drivers' $MDTSelectionProfilePath = $PSDriveName + ':\Selection Profiles' # Connect to Deployment Share If ((Get-PSDrive -Name $PSDriveName -ErrorAction SilentlyContinue) -eq $false) { New-PSDrive -Name $PSDriveName -PSProvider MDTProvider -Root $DeploymentShare } $Make = "Dell" $OperatingSystemDir = ("Windows " + $WindowsVersion + " " + $Architecture) # Get full list of available driver cab folders from downloaded content and import into MDT if not already imported Get-ChildItem ($RepositoryPath + "\" + $Make) -Recurse | Where-Object { ($_.PSIsContainer -eq $true) -and ($_.FullName -like "*Driver Cab*") } | foreach { $Model = (($_.FullName | Split-Path -Parent) | Split-Path -Leaf) $DriverRevision = ((Get-ChildItem -Path $_.FullName -Filter *.Cab).Name).Split("-")[2] if ((Test-Path $MDTDriverPath\$OperatingSystemDir) -eq $false) { New-Item -path $MDTDriverPath -enable "True" -Name $OperatingSystemDir -ItemType "folder" -Verbose } if (!(Test-Path $MDTSelectionProfilePath"\Drivers - "$OperatingSystemDir)) { New-Item -path $MDTSelectionProfilePath -enable "True" -Name "Drivers - $OperatingSystemDir" -Definition "<SelectionProfile><Include path=`"Out-of-Box Drivers\$OS`" /></SelectionProfile>" -ReadOnly "False" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir -enable "True" -Name $Make -ItemType "folder" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make -enable "True" -Name $Model -ItemType "folder" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make\$Model -enable "True" -Name $DriverRevision -ItemType "folder" -Verbose Write-Host -ForegroundColor Green "Importing MDT driver pack for $Make $Model - Revision $DriverRevision" Import-MDTDriver -path $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision -Source $_.FullName } else { Write-Host -ForegroundColor Yellow "MDT driver pack already exists.. Skipping.." } } } } function MDTDownloadAndImport ($RepositoryPath, $DellProducts, $WindowsVersion, $Architecture, $MaxConcurrentJobs) { # Import MDT Module Import-Module "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1" # Detect First MDT PSDrive If (!$PSDriveName) { $PSDriveName = (Get-MDTPersistentDrive)[0].name } # Detect First MDT Deployment Share If (!$DeploymentShare) { $DeploymentShare = (Get-MDTPersistentDrive)[0].path } $MDTDriverPath = $PSDriveName + ':\Out-of-Box Drivers' $MDTSelectionProfilePath = $PSDriveName + ':\Selection Profiles' # Connect to Deployment Share If (!(Get-PSDrive -Name $PSDriveName -ErrorAction SilentlyContinue)) { New-PSDrive -Name $PSDriveName -PSProvider MDTProvider -Root $DeploymentShare } $DSDriverPath = $PSDriveName + ':\Out-of-Box Drivers' $DSSelectionProfilePath = $PSDriveName + ':\Selection Profiles' $RunMDTDownloadJob = { Param ($Model, $RepositoryPath, $WindowsVersion, $Architecture, $DownloadType, $PSDriveName, $DeploymentShare, $DSDriverPath, $DSSelectionProfilePath, $MaxConcurrentJobs) # =================== DEFINE VARIABLES ===================== # Define Dell Download Sources $DellDownloadList = "http://downloads.dell.com/published/Pages/index.html" $DellDownloadBase = "http://downloads.dell.com" $DellMDTDriverList = "http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment" $DellMDTBase = "http://en.community.dell.com" # Directory used for driver downloads $DriverRepositoryRoot = ($RepositoryPath.Trimend("\") + "\Dell\") Write-Host "Driver package path set to $DriverRepositoryRoot" # Operating System Version $OperatingSystem = ("Windows " + $WindowsVersion) # =============== MDT Driver Cab Download ================= Write-Host "Getting MDT driver pack link for model: $Model" $ModelLink = (Invoke-WebRequest -Uri $DellMDTDriverList -UseBasicParsing).Links | Where-Object { ($_.outerHTML -like "*$Model*") -and ($_.outerHTML -like "*$OperatingSystem*") } | select -First 1 $ModelURL = $DellMDTBase + ($ModelLink.href) If ($ModelURL -ne $null) { # Correct slash direction issues $ModelURL = $ModelURL.Replace("\", "/") $MDTDriverDownload = (Invoke-WebRequest -Uri $ModelURL -UseBasicParsing).Links | Where-Object { $_.href -like "*.cab" } $MDTDriverCab = $MDTDriverDownload.href | Split-Path -Leaf # Check for destination directory, create if required and download the driver cab if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $MDTDriverCab)) -eq $false) { if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\")) -eq $false) { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\Driver Cab") } else { # Remove previous driver cab revisions Get-ChildItem -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\") | Remove-Item } Write-Host -ForegroundColor Green "Downloading $($MDTDriverCab) driver cab file" Start-BitsTransfer -Source ($MDTDriverDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $MDTDriverCab) } else { Write-Host -ForegroundColor Yellow "Skipping $MDTDriverCab... Driver pack already downloaded..." } } } $TotalModelCount = $DellProducts.Count $RemainingModels = $TotalModelCount foreach ($Model in $DellProducts) { Write-Progress -activity "Initiate MDT Driver Download & Driver Package Jobs" -status "Progress:" -percentcomplete (($TotalModelCount - $RemainingModels)/$TotalModelCount * 100) $RemainingModels-- $Check = $false while ($Check -eq $false) { if ((Get-Job -State 'Running').Count -lt $MaxConcurrentJobs) { Start-Job -ScriptBlock $RunMDTDownloadJob -ArgumentList $Model, $RepositoryPath, $DellProducts, $WindowsVersion, $Architecture, $PSDriveName, $DeploymentShare -Name ($Model + " Driver Import") -Verbose $Check = $true } } } Get-Job | Wait-Job | Receive-Job Get-Job | Remove-Job # =============== MDT Driver Import ==================== $Make = "Dell" $OperatingSystemDir = ("Windows " + $WindowsVersion + " " + $Architecture) # Loop through folders and import Drivers Get-ChildItem ($RepositoryPath + "\" + $Make) -Recurse | Where-Object { ($_.PSIsContainer -eq $true) -and ($_.FullName -like "*Driver Cab*") } | foreach { $Model = (($_.FullName | Split-Path -Parent) | Split-Path -Leaf) $DriverRevision = ((Get-ChildItem -Path $_.FullName -Filter *.Cab).Name).Split("-")[2] if ((Test-Path $MDTDriverPath\$OperatingSystemDir) -eq $false) { New-Item -path $MDTDriverPath -enable "True" -Name $OperatingSystemDir -ItemType "folder" -Verbose } if ((Test-Path $MDTSelectionProfilePath"\Drivers - "$OperatingSystemDir) -eq $false) { New-Item -path $MDTSelectionProfilePath -enable "True" -Name "Drivers - $OperatingSystemDir" -Definition "<SelectionProfile><Include path=`"Out-of-Box Drivers\$OS`" /></SelectionProfile>" -ReadOnly "False" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir -enable "True" -Name $Make -ItemType "folder" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make -enable "True" -Name $Model -ItemType "folder" -Verbose } if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision) -eq $false) { New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make\$Model -enable "True" -Name $DriverRevision -ItemType "folder" -Verbose Write-Host -ForegroundColor Green "Importing MDT driver pack for $Make $Model - Revision $DriverRevision" Import-MDTDriver -path $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision -Source $_.FullName } else { Write-Host -ForegroundColor Yellow "MDT driver pack already exists.. Skipping.." } } } if (($ImportInto -eq "SCCM") -or ($ImportInto -eq "Both")) { if (($PackagePath -eq $null) -or ($SiteServer -eq $null)) { Write-Host -ForegroundColor "A required parameter was not included in the commandline. Please check the Package Path and Site Server variables" Break } # Get SCCM Site Code $SiteCode = QuerySiteCode ($SiteServer) Write-Debug $PackagePath Write-Debug $RepositoryPath if ($SiteCode -ne $null) { # Query Dell Products in SCCM using QueryModels function $DellProducts = QueryModels ($SiteCode) # Output the members of the ArrayList if ($DellProducts.Count -ge 1) { foreach ($ModelItem in $DellProducts) { $PSObject = [PSCustomObject]@{ "Dell Models Found" = $ModelItem } Write-Output $PSObject Write-Debug $PSObject } } # Start download, extract, import and package process Write-Host " " Write-Host "=================================================================================================" Write-Host "== " Write-Host "== Dell SCCM/MDT Driver Download & Import Script - By Maurice Daly " Write-Host "== " Write-Host "== Running download, extract and import processes with the following variables; " Write-Host "== 1.Import Drivers into: $($ImportInto) " Write-Host "== 2.Download BIOS or Drivers: $($DownloadType) " Write-Host "== 3.SCCM Site Server: $($SiteServer) " Write-Host "== 4.SCCM Site Code: $($SiteCode) " Write-Host "== 5.Driver Respository: $($RepositoryPath) " Write-Host "== 6.Package Destination: $($PackagePath) " Write-Host "== 7.Operating System: Windows $($WindowsVersion) - $($Architecture) " Write-Host "== " Write-Host "=================================================================================================" Write-Host " " Write-Host -ForegroundColor Green "Starting download, extract, import and driver package build process.." SCCMDownloadAndPackage ($PackagePath) ($RepositoryPath) ($SiteCode) ($DellProducts) ($WindowsVersion) ($Architecture) ($DownloadType) ($ImportInto) ($MaxConcurrentJobs) } else { Write-Host -ForegroundColor Red "SCCM Site Code could not be found" } } else { if ((Test-Path -Path $ModelCSVSource) -eq $true) { $DellProducts = New-Object -TypeName System.Collections.ArrayList $Models = Import-Csv -Path $ModelCSVSource # Add model to ArrayList if not present if ($Models -ne $null) { foreach ($Model in $Models.Model) { if ($Model -notin $DellProducts) { $DellProducts.Add($Model) | Out-Null } } } } else { Write-Host -ForegroundColor Red "Unable to find the file specified." Break } # Start download, extract, import and package process Write-Host " " Write-Host "=================================================================================================" Write-Host "== " Write-Host "== Dell SCCM/MDT Driver Download & Import Script - By Maurice Daly " Write-Host "== " Write-Host "== Running MDT only download, extract and import processes with the following variables; " Write-Host "== 1.Model Source File: $($ModelCSVSource) " Write-Host "== 1.Driver Respository: $($RepositoryPath) " Write-Host "== 2.Operating System: Windows $($WindowsVersion) - $($Architecture) " Write-Host "== " Write-Host "=================================================================================================" Write-Host " " Write-Host -ForegroundColor Green "Starting download, extract, import and driver package build process.." MDTDownloadAndImport ($RepositoryPath) ($DellProducts) ($WindowsVersion) ($Architecture) ($MaxConcurrentJobs) }
Lets step through the options available to you when running the script;
Run the script using the following opening syntax: .\DellDownloads.ps1 -ImportInto SCCM – for SCCM only or .\DellDownloads.ps1 -ImportInto Both – for both SCCM and MDT
When running the script for this type of deployment, the following switches are required;
–DownloadType :: Selects the type of download, the options available are All. Drivers or BIOS
–SiteServer :: The name of your SCCM site server than you are running the script on
–RepositoryPath :: The location for your bios and driver downloads and cabinet extracts
–PackagePath :: The location for your SCCM driver packages
–WindowsVersion :: Options include, 7, 8, 8.1 and 10
–Architecture :: Options include x86 or x64
–MaxConcurrentJobs :: Options for 1-5 concurrent jobs
Working example (SCCM only with BIOS and Driver downloads):
.\DellDownload -ImportInto SCCM -DownloadType ALL -SiteServer SCCM01 -RepositoryPath "\\server\drivers" -PackagePath "\\server\driverpacks" -WindowsVersion 10 -Architecture x64 -MaxConcurrentJobs 3
Working example (SCCM and MDT with Driver downloads and 3 concurrent jobs):
.\DellDownload -ImportInto Both -DownloadType Drivers -SiteServer SCCM01 -RepositoryPath "\\server\drivers" -PackagePath "\\server\driverpacks" -WindowsVersion 10 -Architecture x64 -MaxConcurrentJobs 3
MDT only – New Feature
The MDT only option differs from the SCCM functions in the fact the script does not query SCCM for a list of Dell enterprise client systems. In this instance a CSV is required with an initial column heading labelled “Model”, example;
Model
Optiplex 7040
Optiplex 7010
Latitude E5470
When running the script for this type of deployment, the following switches are required;
–DownloadType :: Selects the type of download, the options available are All or Drivers
–RepositoryPath :: The location for your bios and driver downloads and cabinet extracts
–WindowsVersion :: Options include, 7, 8, 8.1 and 10
–Architecture :: Options include x86 or x64
–MaxConcurrentJobs :: Options for 1-5 concurrent job (defaults to 3 if not entered)
-MDTCSVSource :: Location of Models CSV file
Working example of MDT only command;
.\DellDownload -ImportInto MDT -DownloadType Drivers -RepositoryPath "\\server\drivers" -WindowsVersion 10 -Architecture x64 -MaxConcurrentJobs 3 -MDTCSVSource ".\Models.csv"
Rebuilding the database indexes is a good thing, yes? Absolutely. Why not use the ConfigMgr rebuild index maintenance task? When the maintenance task works, and I have proof that some of the time it fails to run on ConfigMgr: It REINDEXES all indexes with more than 10% fragmentation It does not update statistics Let’s break […]
via Why you should not use the ConfigMgr rebuild index task — Steve Thompson [MVP]
If you still have to maintain Java installations in your environment you will probably come up against having machines with multiple versions installed, unless you are running a clean up script for the old releases.
It is however sometimes a requirement to keep a specific release of Java for application compatibility, so what do you do in those scenarios where you want to clean up your old installs but the required version.
The below PowerShell script will do just that. It looks at your installed versions of Java, removes all previous versions and provides you with the option of specifying a version to keep during the process.
Script Download Link – https://gallery.technet.microsoft.com/scriptcenter/Java-Version-Cleaner-4a73f6be
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 13/11/2016 22:13 Created by: Maurice.Daly Organization: Filename: JavaVersionCleaner.ps1 =========================================================================== .DESCRIPTION This script removes previous versions of Oracle Java. The script supports the option to specify specific versions to keep during the uninstall process. .EXAMPLE .\JavaVersionCleaner.ps1 -MinJavaVersion jre1.8.0_100 Using this will keep the current version of Java and also jre1.8.0_100 .\JavaVersionCleaner.ps1 This will remove all versions bar the current version of Java #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $false, HelpMessage = "Specify Java Version to maintain", Position = 1)] [ValidateNotNullOrEmpty()] [string]$MinJavaVersion ) function JavaX64Uninstall ($MinJavaVersion) { Write-Debug "Running X64 Uninstalls" # Read registry for Java 64 bit versions $JavaX64Installs = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall -Recurse | Get-ItemProperty | Where-Object { ($_.displayName -like "*Java*Update*") -and ($_.displayName -notlike "*Java*Auto*") } | Select Displayname, UninstallString, InstallDate, InstatallLocation $JavaX64Count = $JavaX64Installs.Count foreach ($JavaX64Install in ($JavaX64Installs | Sort-Object InstallDate)) { if (($JavaX64Count) -gt 1) { if ($JavaX64Install.InstallLocation -notlike "*$($MinJavaVersion)*") { $MSIString = $JavaX64Install.Uninstallstring | Split-Path -Leaf Write-Debug "Uninstalling $($JavaX64Install.Displayname)" Write-Debug "MSIString $($MSIString)" Start-Process MSIEXEC.EXE -ArgumentList (" /" + $MSIString + " /QN") } $JavaX64Count-- } } } function JavaX86Uninstall ($MinJavaVersion) { Write-Debug "Running X86 Uninstalls" # Read registry for Java 32 bit versions $JavaX86Installs = Get-ChildItem -Path HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall -Recurse | Get-ItemProperty | Where-Object { ($_.displayName -like "*Java*Update*") -and ($_.displayName -notlike "*Java*Auto*") } | Select Displayname, UninstallString, InstallDate, InstallLocation $JavaX86Count = $JavaX86Installs.Count foreach ($JavaX86Install in ($JavaX86Installs | Sort-Object InstallDate)) { if (($JavaX86Count) -gt 1) { if ($JavaX86Install.InstallLocation -notlike "*$($MinJavaVersion)*") { $MSIString = $JavaX86Install.UninstallString | Split-Path -Leaf Write-Debug "Uninstalling $($JavaX86Install.Displayname)" Write-Debug "MSIString $($MSIString)" Start-Process MSIEXEC.EXE -ArgumentList (" /" + $MSIString + " /QN") } $JavaX86Count-- } } } # Check for Windows 32 or 64 bit and process functions if ((Test-Path -Path "C:\Program Files (x86)") -eq $true) { JavaX64Uninstall ($MinJavaVersion) JavaX86Uninstall ($MinJavaVersion) }else{ JavaX86Uninstall ($MinJavaVersion) }
Over time in any environment the day will come around when the inevitable happens and staff leave. This happens due to lots of different reasons but there is often a question as to what to do with user accounts when this happens. This is particularly true in smaller companies with no set process for IT departments off-boarding staff.
In my own environment, I decided to set up a standard script which would work with Active Directory and Office 365 to achieve the following;
The user account is then maintained for a period of 30 days before being deleted and thus returning any assigned Office 365 licenses to the pool etc.
This might help to give you some ideas about setting up your own scripting process for dealing with this issue.
Script Download Link – https://gallery.technet.microsoft.com/scriptcenter/Staff-Off-Boarding-Script-430bdd0a
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 04/11/2016 21:00 Created by: Maurice Daly Filename: DisableUserOffice365.ps1 =========================================================================== .DESCRIPTION This script provides a standard off-boarding method for staff leaving the company. The script does the following; 1. Disables the specified user account 2. Updates the user description with the user who disabled the account and the time/date when the account was disabled 3. Moves the account to the disabled user account OU (needs to exist) 4. Sets an out of office reply stating that the employee has left the company 5. Disables activesync, pop3, imap etc 6. Places mail account into legal hold for 7 years (requires Office 365 E3) 7. Hides the mail account from the GAL 8. Emails the former employee's manager advising that the account has been disabled Version 1.0 Initial release Use : This script is provided as it and I accept no responsibility for any issues arising from its use. Twitter : @modaly_it Blog : https://modalyitblog.wordpress.com/ #> Write-Host " **************** PLEASE ENTER ACTIVE DIRECTORY ADMIN CREDENTIALS **************** " $Credential = Get-Credential -Credential "$env:USERDOMAIN\$env:USERNAME" $DC = $env:LOGONSERVER.Substring(2) #Initiate Remote PS Session to local DC $ADPowerShell = New-PSSession -ComputerName $DC -Authentication Negotiate -Credential $Credential # Import-Module ActiveDirectory write-host "Importing Active Directory PowerShell Commandlets" Invoke-Command -Session $ADPowerShell -scriptblock { import-module ActiveDirectory } Import-PSSession -Session $ADPowerShell -Module ActiveDirectory -AllowClobber -ErrorAction Stop # Retrieve AD Details $ADDetails = Get-ADDomain $Domain = $ADDetails.DNSRoot Clear-Host write-host "Importing Office 365 PowerShell Commandlets" Write-Host -ForegroundColor White -BackgroundColor DarkBlue " **************** PLEASE ENTER OFFICE 365 ADMIN CREDENTIALS **************** " $Office365Credential = Get-Credential $Office365PowerShell = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Office365Credential -Authentication Basic -AllowRedirection Import-PSSession $Office365PowerShell Clear-Host write-host " **************** Disable Active Directory User Account & Enable Out Of Office **************** " write-host " " # Get Variables $DisabledDate = Get-Date $LeaveDate = Get-Date -Format "dddd dd MMMM yyyy" $DisabledBy = Get-ADUser "$env:username" -properties Mail $DisabledByEmail = $DisabledBy.Mail # Prompt for AD Username $Employee = Read-Host "Employee Username" $EmployeeDetails = Get-ADUser $Employee -properties * If ($EmployeeDetails.Manager -ne $null) { $Manager = Get-ADUser $EmployeeDetails.Manager -Properties Mail } Clear-Host # Prompt for confirmation write-host " ******************************** CONFIRM USER DISABLE REQUEST ******************************** " write-host " " write-host -ForegroundColor Yellow "Please review the Employee details below to ensure you are disabling the correct user account." $EmployeeDetails | fl Name, Title, Company, @{ Expression = { $_.mail }; Label = "Email Address" }, @{Expression = { $_.Created }; Label = "Employment Started"} $choice = " " while ($choice -notmatch "[y|n]") { $choice = read-host "Do you want to continue? (Y/N)" } # Actions if ($choice -eq "y") { Clear-Host write-host " ******************************** DISABLING USER ACCOUNT ******************************** " write-host " " write-host "Step1. Modifying user description for audit purposes" -ForegroundColor Yellow Set-ADUser $Employee -Description "Disabled by $($DisabledBy.name) on $DisabledDate" write-host "Step2. Disabling $Employee Active Directory Account." -ForegroundColor Yellow Disable-ADAccount $Employee write-host "Step3. Moving $Employee to the Disabled User Accounts OU." -ForegroundColor Yellow write-host " " Move-ADObject -Identity $EmployeeDetails.DistinguishedName -targetpath "OU=Disabled User Accounts,DC=YOURDOMAIN,DC=SUFFIX" write-host "Waiting 5 seconds for AD & Exchange OU update to complete" sleep -Seconds 5 write-host " " write-host "Refreshing Employee Details for Exchange Modification." write-host " " Get-ADUser $Employee -Properties Description | Format-List Name, Enabled, Description write-host "Step 4. Setting Exchange Out Of Office Auto-Responder." -ForegroundColor Yellow Set-MailboxAutoReplyConfiguration -Identity $EmployeeDetails.Mail -AutoReplyState enabled -ExternalAudience all -InternalMessage "Please note that I no longer work for $($EmployeeDetails.company) as of $LeaveDate." -ExternalMessage "Please note that I no longer work for $($EmployeeDetails.company) as of $LeaveDate. Direct all correspondence to info@yourdomain.suffix." Write-Host "Step 5. Disabling POP,IMAP, OWA and ActiveSync access for $User" -ForegroundColor Yellow Set-CasMailbox -Identity $EmployeeDetails.mail -OWAEnabled $false -POPEnabled $false -ImapEnabled $false -ActiveSyncEnabled $false Write-Host "Step 6. Placing mailbox $($EmployeeDetails.name) into Ligitgation hold for 7 years" -ForegroundColor Yellow Set-Mailbox -Identity $EmployeeDetails.mail -LitigationHoldEnabled $true -LitigationHoldDuration 2555 Write-Host "Step 7. Hiding $($EmployeeDetails.name) from Global Address lists" -ForegroundColor Yellow Set-ADUser -identity $Employee -add @{ msExchHideFromAddressLists = "True" } Set-ADUser -instance $EmployeeDetails -whatif If ($Manager.Mail -like "*@*") { Write-Host "Step 8. Sending Confirmation E-mail To Employee's Manager." -ForegroundColor Yellow $msg = new-object Net.Mail.MailMessage $smtp = new-object Net.Mail.SmtpClient("youroffice365mailserveraddress") $msg.From = "Support@yourdomain.suffix" $msg.To.Add("$($Manager.Mail)") $msg.subject = "IT Notification - Employee Leaver Confirmation" $msg.body = "This email is confirm that $($EmployeeDetails.Name)'s account has been disabled. An out of office notification advising that $($EmployeeDetails.Name) has left the company has also been set. Note that the account will be deleted after 30 days." $smtp.Send($msg) } }else{ write-host " " write-host "Employee disable request cancelled" -ForegroundColor Yellow }
In October of 2016 I released a script that downloaded drivers and bios updates for Dell client systems and created associated driver packs in SCCM (https://modalyitblog.wordpress.com/2016/10/10/sccm-dell-client-bios-driver-autodownload-ps-script/).
A friend of mine works in the UK educational system as an admin and thought it would be nice to have a similar script for his environment, mainly consisting of the UK educational hardware builder Viglen.
So here is version 1.0 of the download script adjusted for Viglen client systems.
The below scripts requires you to specify your driver file share and your SCCM site server name as a variable, it then does the following;
The downloads are stored within sub-folders within the share you specified, e.g;
\\MySCCMServer\Drivers\Viglen 820s\Driver ZIP\
\\MySCCMServer\Drivers\Viglen 820s\Extracted Drivers\
PowerShell Script
To run the script use the following syntax;
.\ViglenSCCMDownload.ps1 -SiteServer YOURSITESERVER -RepositoryPath “\\YOURSERVER\DRIVERREPO\” -PackagePath “\\YOURSERVER\DRIVERPACKPATH”
The script has Windows 10 x64 specified, however you can change this under the #Define Operating Systems section. Note I have tested Windows 7 & 10 only during building this.
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 03/11/2016 13:00 Created by: Maurice Daly Filename: ViglenSCCMDownloads.ps1 ========================================================================== .DESCRIPTION This script allows you to automate the process of keeping your driver sources up to date. The script reads the Viglen support download site for models found within SCCM and then downloads the corresponding drivers Version 1.0 Initial release Notes You can skip the driver package creation process by changing the $DriverPackageCreation variable to $False. The system architecture can also be changed by modifying the $Architecture variable and using x64 or x86 You can limit the number of concurrent jobs by specifying your max value in the $MaxConcurrent jobs variable To run the script use the following syntax; .\ViglenSCCMDownload.ps1 -SiteServer YOURSITESERVER -RepositoryPath UNCTEMPDRIVERPATH -PackagePath UNCDRIVERPACKAGEPATH To re-enable error messaging for troubleshooting purpose comment out the Error and Warning Preference values below Use : This script is provided as it and I accept no responsibility for any issues arising from its use. Twitter : @modaly_it Blog : https://modalyitblog.wordpress.com/ #> # Define SCCM Site Server [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, HelpMessage = "Site server where the SMS Provider is installed", Position = 1)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Connection -ComputerName $_ -Count 1 -Quiet })] [string]$SiteServer, [parameter(Mandatory = $true, HelpMessage = "UNC path for downloading and extracting drivers")] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$RepositoryPath, [parameter(Mandatory = $true, HelpMessage = "UNC path of your driver package repository")] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$PackagePath ) $ErrorActionPreference = 'SilentlyContinue' $WarningPreference = 'SilentlyContinue' # Import SCCM PowerShell Module Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" # Define Maximum Number Of Simultaneously Running Jobs $MaxConcurrentJobs = 5 # Query SCCM Site Code function QuerySiteCode ($SiteServer) { Write-Verbose "Determining SiteCode for Site Server: '$($SiteServer)'" $SiteCodeObjects = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop foreach ($SiteCodeObject in $SiteCodeObjects) { if ($SiteCodeObject.ProviderForLocalSite -eq $true) { $SiteCode = $SiteCodeObject.SiteCode Write-Debug "SiteCode: $($SiteCode)" } } Return [string]$SiteCode } function QueryModels ($SiteCode) { # ArrayList to store the Viglen models in $ViglenProducts = New-Object -TypeName System.Collections.ArrayList # Enumerate through all models #$Models = "VIG430P","VIG665W","Vig670W","Vig800S","Vig820S","Vig830S" $Models = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_G_System_COMPUTER_SYSTEM | Select-Object -Property Model | Where-Object { $_.Model -like "*Vig*" } # Add model to ArrayList if not present if ($Models -ne $null) { foreach ($Model in $Models) { if ($Model.Model -notin $ViglenProducts) { $ViglenProducts.Add($Model.Model) | Out-Null } } } #$ViglenProducts = "VIG430P", "VIG665W", "Vig670W", "Vig800S", "Vig820S", "Vig830S" Return $ViglenProducts } function StartDownloadAndPackage ($PackagePath, $RepositoryPath) { $RunDownloadJob = { Param ($Model, $SiteCode, $PackagePath, $RepositoryPath) # =================== DEFINE VARIABLES ===================== # Directory used for driver downloads $DriverRepositoryRoot = ($RepositoryPath.Trimend("\") + "\Viglen\") Write-Host "Driver package path set to $DriverRepositoryRoot" # Directory used by SCCM for driver package $DriverPackageRoot = ($PackagePath.Trimend("\") + "\Viglen\") Write-Host "Driver package path set to $DriverPackageRoot" # Define Operating System $OperatingSystem = "Windows" $OperatingSystemVersion = "10" $Architecture = "64" # Define Viglen Download Sources $ViglenBaseURL = "http://download.viglen.co.uk" $ViglenDownloadList = "/files/Motherboards/" $ViglenBIOSFolder = "BIOS/" $ViglenDriverFolder = "Drivers/" # Import Driver Packs? $DriverPackCreation = $true # Import SCCM PowerShell Module Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" # =================== INITIATE DOWNLOADS =================== Write-Host "Getting download URL for Viglen client model: $Model" $ModelLink = (Invoke-WebRequest -Uri ($ViglenBaseURL + $ViglenDownloadList) -UseBasicParsing).Links | Where-Object { $_.href -like "*$Model*" } $ModelURL = ($ViglenBaseURL + $ModelLink.href) # Correct slash direction issues $ModelURL = $ModelURL.Replace("\", "/") # ============= SCCM Driver Cab Download ================== Write-Host "Getting SCCM driver pack link for model: $Model" $ViglenInfFolder = (((Invoke-WebRequest -Uri ($ModelURL + $ViglenDriverFolder) -UseBasicParsing).links | Where-Object { $_.href -like "*INF*" }).href | Split-Path -Leaf) + "/" $SCCMDriverDownload = ((Invoke-WebRequest -Uri ($ModelURL + $ViglenDriverFolder + $ViglenInfFolder) -UseBasicParsing).Links | Where-Object { $_.href -like "*$($OperatingSystem.trim("dows"))*$OperatingSystemVersion*.zip" } | Select-Object -Last 1).href if ($SCCMDriverDownload -eq $null) { # Check for driver folder for specified OS $DriverOSSubFolder = ((Invoke-WebRequest -Uri ($ModelURL + $ViglenDriverFolder + $ViglenInfFolder) -UseBasicParsing).Links | Where-Object { $_.outerHTML -like "*$OperatingSystem*$OperatingSystemVersion*" }).href | Split-Path -Leaf if ($DriverOSSubFolder -eq $null) { Write-Host -ForegroundColor White -BackgroundColor Red "Driver does not exist for $Model running $OperatingSystem $OperatingSystemVersion" Break } else { $SCCMDriverDownload = ((Invoke-WebRequest -Uri ($ModelURL + $ViglenDriverFolder + $ViglenInfFolder + $DriverOSSubFolder) -UseBasicParsing).Links | Where-Object { $_.href -like "*$($OperatingSystem.trim("dows"))*$OperatingSystemVersion*.zip" } | Select-Object -Last 1).href } } else { # $SCCMDriverDownload = $SCCMDriverDownload.href } $SCCMDriverZIP = ($SCCMDriverDownload | Split-Path -Leaf) # Check for destination directory, create if required and download the driver zip if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver ZIP\")) -eq $true) { if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver ZIP\" + $SCCMDriverZIP)) -eq $true) { Write-Host -ForegroundColor Yellow "Skipping $SCCMDriverZIP... File already downloaded..." $SkipDriver = $true } else { Start-BitsTransfer -Source ($ViglenBaseURL + $SCCMDriverDownload) -Destination ($DriverRepositoryRoot + $Model + "\Driver ZIP\" + $SCCMDriverZIP) -DisplayName "Downloading $Model driver ZIP file" $SkipDriver = $false } } else { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\Driver ZIP") Start-BitsTransfer -Source ($ViglenBaseURL + $SCCMDriverDownload) -Destination ($DriverRepositoryRoot + $Model + "\Driver ZIP\" + $SCCMDriverZIP) -DisplayName "Downloading $Model driver ZIP file" } # =================== CREATE DRIVER PACKAGE AND IMPORT DRIVERS =================== Write-Host -ForegroundColor Green "Starting extract and import process" $DriverSourceFile = ($DriverRepositoryRoot + $Model + "\Driver ZIP\" + $SCCMDriverZIP) $DriverExtractDest = ($DriverRepositoryRoot + $Model + "\Extracted Drivers") $DriverPackageDir = ($DriverSourceFile | Split-Path -Leaf) $DriverPackageDir = $DriverPackageDir.Substring(0, $DriverPackageDir.length - 4) $DriverFileDest = $DriverPackageRoot + "Viglen\" + $DriverPackageDir if ($DriverPackCreation -eq $true) { if ((Test-Path -Path $DriverExtractDest) -eq $false) { New-Item -Type dir -Path $DriverExtractDest } else { Get-ChildItem -Path $DriverExtractDest -Recurse | Remove-Item -Recurse -Force } New-Item -Type dir -Path $DriverFileDest Set-Location -Path ($SiteCode + ":") $CMDDriverPackage = "Viglen " + $Model + " " + $OperatingSystem + " " + $OperatingSystemVersion + " " + $Architecture + "bit" if (Get-CMDriverPackage -Name $CMDDriverPackage) { Write-Host -ForegroundColor Yellow "Skipping.. Driver package already exists.." } else { Write-Host -ForegroundColor Green "Creating driver package" Set-Location -Path $env:SystemDrive Add-Type -assembly "system.io.compression.filesystem" [io.compression.zipfile]::ExtractToDirectory($DriverSourceFile, $DriverExtractDest) $DriverINFFiles = Get-ChildItem -Path $DriverExtractDest -Recurse -Filter "*.inf" } Set-Location -Path ($SiteCode + ":") New-CMDriverPackage -Name $CMDDriverPackage -path ($DriverPackageRoot + $Model + "\" + $OperatingSystem + " " + $OperatingSystemVersion + "\" + $Architecture) if (Get-CMCategory -CategoryType DriverCategories -name ("Viglen " + $Model)) { Write-Host -ForegroundColor Yellow "Category already exists" $DriverCategory = Get-CMCategory -CategoryType DriverCategories -name ("Viglen " + $Model) } else { Write-Host -ForegroundColor Green "Creating category" $DriverCategory = New-CMCategory -CategoryType DriverCategories -name ("Viglen " + $Model) } $DriverPackage = Get-CMDriverPackage -Name $CMDDriverPackage foreach ($DriverINF in $DriverINFFiles) { $DriverInfo = Import-CMDriver -UncFileLocation ($DriverINF.FullName) -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True -AdministrativeCategory $DriverCategory | Select-Object * Add-CMDriverToDriverPackage -DriverID $DriverInfo.CI_ID -DriverPackageName $CMDDriverPackage } } Set-Location -Path $env:SystemDrive } $TotalModelCount = $ViglenProducts.Count $RemainingModels = $TotalModelCount foreach ($Model in $ViglenProducts) { write-progress -activity "Initiate Driver Download & Driver Package Jobs" -status "Progress:" -percentcomplete (($TotalModelCount - $RemainingModels)/$TotalModelCount * 100) $RemainingModels-- $Check = $false while ($Check -eq $false) { if ((Get-Job -State 'Running').Count -lt $MaxConcurrentJobs) { Start-Job -ScriptBlock $RunDownloadJob -ArgumentList $Model, $SiteCode, $PackagePath, $RepositoryPath -Name ($Model + " Download") $Check = $true } } } Get-Job | Wait-Job | Receive-Job Get-Job | Remove-Job } # Get SCCM Site Code $SiteCode = QuerySiteCode ($SiteServer) Write-Debug $PackagePath Write-Debug $RepositoryPath if ($SiteCode -ne $null) { # Query Viglen Products in SCCM using QueryModels function $ViglenProducts = QueryModels ($SiteCode) # Output the members of the ArrayList if ($ViglenProducts.Count -ge 1) { foreach ($ModelItem in $ViglenProducts) { $PSObject = [PSCustomObject]@{ "Viglen Models Found" = $ModelItem } Write-Output $PSObject } } # Start download, extract, import and package process Write-Host -ForegroundColor Green "Starting download, extract, import and driver package build process.." StartDownloadAndPackage ($PackagePath) ($RepositoryPath) ($SiteCode) }
I’ve recently seen people asking on forums about how to modify the source settings of SCCM packages when migrating software installation files from an old server to a new one. Obviously manually updating packages is an option, but this will take time.. so this is achieved very easily by running the PowerShell code below
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 31/10/2016 14:13 Created by: Maurice.Daly Organization: Filename: UpdatePkgSource.ps1 =========================================================================== .DESCRIPTION Updates the source location for SCCM packages and update your distribution points Provided as is with no support. Run at your own risk. #> $OldSource = "\\YOUROLDSERVER\PACKAGESOURCE" $NewSource = "\\YOURNEWSERVER\PACKAGESOURCE" foreach ($Package in (Get-CMPackage | Where-Object { $_.PkgSourcePath -like "*$OldSource*" })) { Write-Host "Modifying $($Package.name) with new location $NewSource" $UpdatedSource = $Package.PkgSourcePath -replace $OldSource, $NewSource # Update source location of package Set-CMPackage -id $Package.ID -Path $UpdatedSource # Force update of distribution points Get-CMPackage -id $Package.ID | Update-CMDistriubtionPoint }
If you are a Dell hardware house then this script might come in useful for you.
As you are probably aware Dell provide excellent support for SCCM deployments via their Dell Command integration software and up to date driver cab files via their Enterprise Client Deployment site at http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment.
When I was refreshing my driver and bios update file repository I got thinking wouldn’t it be nice if I could just run a script that would download these update files based on the models of Dell client systems listed in my SCCM device collections?.
I found a script on Dustin Hedges blog (https://deploymentramblings.wordpress.com/2014/04/17/downloading-dell-driver-cab-files-automagically-with-the-driver-pack-catalog/) but I wanted to automate this further.
So here is my resulting effort. The below scripts requires you to specify your driver file share and your SCCM site server name as a variable, it then does the following;
Progress bars have also been added for both the system model and driver import stage.
The downloads are stored within sub-folders within the share you specified, e.g;
\\MySCCMServer\Drivers\Dell Optiplex 7040\BIOS
\\MySCCMServer\Drivers\Dell Optiplex 7040\Driver Cabs\
Automatically created SCCM Driver Packages:
SCCM Driver Package Contents;
Multi-Threaded Script
To run the script use the following syntax;
.\DellDownloads.ps1 -SiteServer YOURSITESERVER -RepositoryPath “\\YOURSERVER\DRIVERREPO\” -PackagePath “\\YOURSERVER\DRIVERPACKPATH”
Task Sequence BIOS Update Script
In the latest release BIOS packaging is included, it also generates a PowerShell script for use at deployment time which is contained within the BIOS folder of the model and uses the latest BIOS exe with silent switches for a silent upgrade.
Note: If you are using a BIOS setup password (which you should be), you will need to specify this within the script (unless you want me to update the script to look for this run running it from the shell).
Modify the following line – $BIOSSwitches = ” -noreboot -nopause /p=%YOURBIOSPASSWORD ”
UPDATE LOG
08/11/2016
The script has been updated with the following functionality;
28/10/2016
As a response to feedback, I have added a $MaxConcurrent jobs variable into the multi-threaded script that lets you specify the max number of jobs in order to control CPU utilization.
26/10/2016
I have added in an additional script below which is multi-threaded. This should help reduce the overall time to download, extract and create the driver packages in large environments with a wide range of models.
16/10/2016
Additional functionality has been added to now automate the process of extracting the CAB, creating computer categories, import the drivers into SCCM and create a driver pack for each of the models / driver packs downloaded.
Script Download Link – https://gallery.technet.microsoft.com/scriptcenter/SCCM-Dell-Client-Bios-ee577b04?redir=0
<# .NOTES =========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.128 Created on: 16/10/2016 13:00 Created by: Maurice Daly Filename: DellDownloads.ps1 =========================================================================== .DESCRIPTION This script allows you to automate the process of keeping your Dell driver and BIOS update sources up to date. The script reads the Dell SCCM driver pack site for models you have specified and then downloads the corresponding latest driver packs and BIOS updates. Version 1.0 Retreive Dell models and download BIOS and Driver Packs Version 2.0 Added driver CAB file extract, create new driver pack, category creation and import driver functions. Version 2.1 Added multi-threading Version 2.2 Added Max Concurrent jobs setting for limiting CPU utilisation Version 2.3 Replaced Invoke-WebRequest download with BITS enabled downloads for improved performance Version 2.4 Updated code and separated functions. Added required variables via commandline Version 3.0 Creates BIOS Packages for each model and writes update powershell file for deployment with SCCM. Notes You can skip the driver package creation process by changing the $DriverPackageCreation variable to $False. The system architecture can also be changed by modifying the $Architecture variable and using x64 or x86 To re-enable error messaging for troubleshooting purpose comment out the Error and Warning Preference values below Use : This script is provided as it and I accept no responsibility for any issues arising from its use. Twitter : @modaly_it Blog : https://modalyitblog.com/ #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, HelpMessage = "Site server where the SMS Provider is installed", Position = 1)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Connection -ComputerName $_ -Count 1 -Quiet })] [string]$SiteServer, [parameter(Mandatory = $true, HelpMessage = "UNC path for downloading and extracting drivers")] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$RepositoryPath, [parameter(Mandatory = $true, HelpMessage = "UNC path of your driver package repository")] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [string]$PackagePath ) $ErrorActionPreference = 'SilentlyContinue' $WarningPreference = 'SilentlyContinue' # Define Maximum Number Of Simultaneously Running Jobs $MaxConcurrentJobs = 5 $ErrorActionPreference = 'SilentlyContinue' $WarningPreference = 'SilentlyContinue' # Import SCCM PowerShell Module $ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1" Import-Module $ModuleName # Query SCCM Site Code function QuerySiteCode ($SiteServer) { Write-Debug "Determining SiteCode for Site Server: '$($SiteServer)'" $SiteCodeObjects = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop foreach ($SiteCodeObject in $SiteCodeObjects) { if ($SiteCodeObject.ProviderForLocalSite -eq $true) { $SiteCode = $SiteCodeObject.SiteCode Write-Debug "SiteCode: $($SiteCode)" } } Return [string]$SiteCode } function QueryModels ($SiteCode) { # ArrayList to store the Dell models in $DellProducts = New-Object -TypeName System.Collections.ArrayList # Enumerate through all models $Models = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_G_System_COMPUTER_SYSTEM | Select-Object -Property Model | Where-Object { ($_.Model -like "*Optiplex*") -or ($_.Model -like "*Latitude*") } # Add model to ArrayList if not present if ($Models -ne $null) { foreach ($Model in $Models) { if ($Model.Model -notin $DellProducts) { $DellProducts.Add($Model.Model) | Out-Null } } } Return $DellProducts } function StartDownloadAndPackage ($PackagePath, $RepositoryPath, $SiteCode, $DellProducts) { $RunDownloadJob = { Param ($Model, $SiteCode, $PackagePath, $RepositoryPath) # =================== DEFINE VARIABLES ===================== # Import SCCM PowerShell Module $ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1" Import-Module $ModuleName # Directory used for driver downloads $DriverRepositoryRoot = ($RepositoryPath.Trimend("\") + "\Dell\") Write-Host "Driver package path set to $DriverRepositoryRoot" # Directory used by SCCM for driver package $DriverPackageRoot = $PackagePath Write-Host "Driver package path set to $DriverPackageRoot" # Define Operating System $OperatingSystem = "Windows 10" $Architecture = "x64" # Define Dell Download Sources $DellDownloadList = "http://downloads.dell.com/published/Pages/index.html" $DellDownloadBase = "http://downloads.dell.com" $DellSCCMDriverList = "http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment" $DellSCCMBase = "http://en.community.dell.com" # Import Driver Packs? $DriverPackCreation = $true # =================== INITIATE DOWNLOADS =================== # ============= BIOS Upgrade Download ================== Write-Host "Getting download URL for Dell client model: $Model" $ModelLink = (Invoke-WebRequest -Uri $DellDownloadList).Links | Where-Object { $_.outerText -eq $Model } $ModelURL = (Split-Path $DellDownloadList -Parent) + "/" + ($ModelLink.href) # Correct slash direction issues $ModelURL = $ModelURL.Replace("\", "/") $BIOSDownload = (Invoke-WebRequest -Uri $ModelURL -UseBasicParsing).Links | Where-Object { ($_.outerHTML -like "*BIOS*") -and ($_.outerHTML -like "*WINDOWS*") } | select -First 1 $BIOSFile = $BIOSDownload.href | Split-Path -Leaf # Check for destination directory, create if required and download the BIOS upgrade file if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\BIOS")) -eq $true) { if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile)) -eq $false) { Write-Host -ForegroundColor Green "Downloading $($BIOSFile) BIOS update file" # Invoke-WebRequest ($DellDownloadBase + $BIOSDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) -UseBasicParsing Start-BitsTransfer ($DellDownloadBase + $BIOSDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) } else { Write-Host -ForegroundColor Yellow "Skipping $BIOSFile... File already downloaded..." } } else { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\BIOS") Write-Host -ForegroundColor Green "Downloading $($BIOSFile) BIOS update file" # Invoke-WebRequest ($DellDownloadBase + $BIOSDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) -UseBasicParsing Start-BitsTransfer ($DellDownloadBase + $BIOSDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSFile) } # ============= SCCM Driver Cab Download ================== Write-Host "Getting SCCM driver pack link for model: $Model" $ModelLink = (Invoke-WebRequest -Uri $DellSCCMDriverList -UseBasicParsing).Links | Where-Object { ($_.outerHTML -like "*$Model*") -and ($_.outerHTML -like "*$OperatingSystem*") } | select -First 1 $ModelURL = $DellSCCMBase + ($ModelLink.href) # Correct slash direction issues $ModelURL = $ModelURL.Replace("\", "/") $SCCMDriverDownload = (Invoke-WebRequest -Uri $ModelURL -UseBasicParsing).Links | Where-Object { $_.href -like "*.cab" } $SCCMDriverCab = $SCCMDriverDownload.href | Split-Path -Leaf # Check for destination directory, create if required and download the driver cab if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\")) -eq $true) { if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab)) -eq $false) { Write-Host -ForegroundColor Green "Downloading $($SCCMDriverCab) driver cab file" # Invoke-WebRequest ($SCCMDriverDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) -UseBasicParsing Start-BitsTransfer -Source ($SCCMDriverDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) $SkipDriver = $false } else { Write-Host -ForegroundColor Yellow "Skipping $SCCMDriverCab... File already downloaded..." $SkipDriver = $true } } else { Write-Host -ForegroundColor Green "Creating $Model download folder" New-Item -Type dir -Path ($DriverRepositoryRoot + $Model + "\Driver Cab") Write-Host -ForegroundColor Green "Downloading $($SCCMDriverCab) driver cab file" #Invoke-WebRequest ($SCCMDriverDownload.href) -OutFile ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) Start-BitsTransfer -Source ($SCCMDriverDownload.href) -Destination ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) } # =================== CREATE BIOS UPDATE PACKAGE =========================== $BIOSUpdatePackage = ("Dell" + " " + $Model + " " + "BIOS UPDATE") $BIOSUpdateRoot = ($DriverRepositoryRoot + $Model + "\BIOS\") Set-Location -Path ($SiteCode + ":") if ((Get-CMPackage -name $BIOSUpdatePackage) -eq $null) { Write-Host -ForegroundColor Green "Creating BIOS Package" New-CMPackage -Name "$BIOSUpdatePackage" -Path $BIOSUpdateRoot -Description "Dell $Model BIOS Updates" -Manufacturer "Dell" -Language English } Set-Location -Path $env:SystemDrive $BIOSUpdateScript = ($BIOSUpdateRoot + "BIOSUpdate.ps1") $CurrentBIOSFile = Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse | Sort-Object $_.LastWriteTime | select -First 1 if ((Test-Path -Path $BIOSUpdateScript) -eq $False) { # Create BIOSUpdate.ps1 Deployment Script New-Item -Path ($BIOSUpdateRoot + "BIOSUpdate.ps1") -ItemType File $BIOSSwitches = " -noreboot -nopause " Add-Content -Path $BIOSUpdateScript ('$CurrentBIOSFile=' + '"' + $($CurrentBIOSFile.name) + '"') Add-Content -Path $BIOSUpdateScript ('$BIOSSwitches=' + '"' + $($BIOSSwitches) + '"') Add-Content -Path $BIOSUpdateScript ('Start-Process $CurrentBIOSFile -ArgumentList $BIOSSwitches') } else { # Check if older BIOS update exists and update BIOSUpdate deployment script $BIOSFileCount = (Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse).count if ($BIOSFileCount -gt 1) { $OldBIOSFiles = Get-ChildItem -Path $BIOSUpdateRoot -Filter *.exe -Recurse | Where-Object { $_.Name -ne $CurrentBIOSFile.name } foreach ($OldBIOS in $OldBIOSFiles) { (Get-Content -Path $BIOSUpdateScript) -replace $OldBIOS.name, $CurrentBIOSFile.name | Set-Content -Path $BIOSUpdateScript } } } # Refresh Distribution Points Get-CMPackage -name $BIOSUpdatePackage | Update-CMDistributionPoint } # =================== CREATE DRIVER PACKAGE AND IMPORT DRIVERS =================== $DriverSourceCab = ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $SCCMDriverCab) $DriverExtractDest = ($DriverRepositoryRoot + $Model + "\Extracted Drivers") $DriverPackageDir = ($DriverSourceCab | Split-Path -Leaf) $DriverPackageDir = $DriverPackageDir.Substring(0, $DriverPackageDir.length - 4) $DriverCabDest = $DriverPackageRoot + "\Dell\" + $DriverPackageDir if ($DriverPackCreation -eq $true) { if ((Test-Path -Path $DriverExtractDest) -eq $false) { New-Item -Type dir -Path $DriverExtractDest } else { Get-ChildItem -Path $DriverExtractDest -Recurse | Remove-Item -Recurse -Force } New-Item -Type dir -Path $DriverCabDest Set-Location -Path ($SiteCode + ":") $CMDDriverPackage = "Dell " + $Model + " " + "(" + $DriverPackageDir + ")" + " " + $Architecture if (Get-CMDriverPackage -Name $CMDDriverPackage) { Write-Host -ForegroundColor Yellow "Skipping.. Driver package already exists.." } else { Write-Host -ForegroundColor Green "Creating driver package" Set-Location -Path $env:SystemDrive Expand "$DriverSourceCab" -F:* "$DriverExtractDest" $DriverINFFiles = Get-ChildItem -Path $DriverExtractDest -Recurse -Filter "*.inf" | Where-Object { $_.FullName -like "*$Architecture*" } Set-Location -Path ($SiteCode + ":") # Get-Location | Out-File -FilePath C:\Location2.txt New-CMDriverPackage -Name $CMDDriverPackage -path ($DriverPackageRoot + "\Dell\" + $DriverPackageDir + "\" + $OperatingSystem + "\" + $Architecture) if (Get-CMCategory -CategoryType DriverCategories -name ("Dell " + $Model)) { Write-Host -ForegroundColor Yellow "Category already exists" $DriverCategory = Get-CMCategory -CategoryType DriverCategories -name ("Dell " + $Model) } else { Write-Host -ForegroundColor Green "Creating category" $DriverCategory = New-CMCategory -CategoryType DriverCategories -name ("Dell " + $Model) } $DriverPackage = Get-CMDriverPackage -Name $CMDDriverPackage foreach ($DriverINF in $DriverINFFiles) { $DriverInfo = Import-CMDriver -UncFileLocation ($DriverINF.FullName) -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True -AdministrativeCategory $DriverCategory | Select-Object * Add-CMDriverToDriverPackage -DriverID $DriverInfo.CI_ID -DriverPackageName $CMDDriverPackage } } Set-Location -Path $env:SystemDrive } $TotalModelCount = $DellProducts.Count $RemainingModels = $TotalModelCount foreach ($Model in $DellProducts) { write-progress -activity "Initiate Driver Download &amp;amp; Driver Package Jobs" -status "Progress:" -percentcomplete (($TotalModelCount - $RemainingModels)/$TotalModelCount * 100) $RemainingModels-- $Check = $false while ($Check -eq $false) { if ((Get-Job -State 'Running').Count -lt $MaxConcurrentJobs) { Start-Job -ScriptBlock $RunDownloadJob -ArgumentList $Model, $SiteCode, $PackagePath, $RepositoryPath -Name ($Model + " Download") $Check = $true } } } Get-Job | Wait-Job | Receive-Job Get-Job | Remove-Job } # Get SCCM Site Code $SiteCode = QuerySiteCode ($SiteServer) Write-Debug $PackagePath Write-Debug $RepositoryPath if ($SiteCode -ne $null) { # Query Dell Products in SCCM using QueryModels function $DellProducts = QueryModels ($SiteCode) # Output the members of the ArrayList if ($DellProducts.Count -ge 1) { foreach ($ModelItem in $DellProducts) { $PSObject = [PSCustomObject]@{ "Dell Models Found" = $ModelItem } Write-Output $PSObject Write-Debug $PSObject } } # Start download, extract, import and package process Write-Host -ForegroundColor Green "Starting download, extract, import and driver package build process.." StartDownloadAndPackage ($PackagePath) ($RepositoryPath) ($SiteCode) ($DellProducts) }
As you might be aware Microsoft is introducing a new feature in Office 365 called Focused mailbox. The new feature is effectively replacing the clutter inbox that we have become familiar with, but also adds new features such as the ability to highlight people in the body of an email with the use of the @ symbol in front of the person.
More details can be found @ https://support.office.com/en-ie/article/Focused-Inbox-for-Outlook-f445ad7f-02f4-4294-a82e-71d8964e3978
Microsoft are currently in the process of rolling this out, if however you get itchy feet and want to enable the feature yourself simply run the PowerShell command below.
Note that I would not recommend this feature for Shared mailboxes, but if you want to go ahead just remove the filter.
Enable Focused Mail for Your Office 365 Tenant
$UserCredential = Get-Credential -Message "Office 365 Administrator Account Login" $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $Session Set-OrganizationConfig -FocusedInboxOn $True
Enable Focused Mail for All Users
$UserCredential = Get-Credential -Message "Office 365 Administrator Account Login" $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $Session Get-Mailbox | Where-Object {$_.RecipientTypeDetails -ne "SharedMailbox"} | Set-FocusedInbox -FocusedInboxOn $True
Update : 5/10/2016
Microsoft have delayed the roll-out of this feature, you can still prepare your mailboxes for the focused feature but your Office 365 tenant will need to be focused enabled by Microsoft.
Jetze Mellema has a blog post on this – http://jetzemellema.blogspot.ie/2016/10/focused-inbox-for-outlook-is-delayed.html?spref=tw
Update : 15/11/2016
I logged onto OWA this evening and finally focused mailbox has been enabled on our tenant 🙂