Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
driverautomationtool.ps1 - Modified to pass UseBasicParsing parameter. See: http://www.scconfigmgr.com/2017/03/01/driver-automation-tool/
<#
.SYNOPSIS
Driver Automation GUI Tool for Dell,HP,Lenovo,Acer and Microsoft systems
.DESCRIPTION
This script allows you to automate the process of keeping your Dell, Lenovo
and HP drives packages up to date. The script reads the Dell, Lenovo and HP
SCCM driver pack site for models you have specified and then downloads
the corresponding latest driver packs and BIOS updates(Dell only).
.NOTES
FileName: DriverDownloadTool.ps1
Blog: http://www.scconfigmgr.com
Author: Maurice Daly
Twitter: @Modaly_IT
Created: 2017-01-01
Updated: 2017-06-09
Version history:
3.9 - (2017-06-09) Script XML use optimisations. Lenovo BIOS extract and packaging. Minor bug fixes.
#>
#region Source: Startup.pss
#----------------------------------------------
#region Import Assemblies
#----------------------------------------------
[void][Reflection.Assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][Reflection.Assembly]::Load('System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
#endregion Import Assemblies
#Define a Param block to use custom parameters in the project
#Param ($CustomParameter)
function Main {
Param ([String]$Commandline)
if ((Show-MainForm_psf) -eq 'OK')
{
}
$script:ExitCode = 0 #Set the exit code for the Packager
}
#endregion Source: Startup.pss
#region Source: MainForm.psf
function Show-MainForm_psf
{
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][reflection.assembly]::Load('System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
#endregion Import Assemblies
#----------------------------------------------
#region Define SAPIEN Types
#----------------------------------------------
try{
[ProgressBarOverlay] | Out-Null
}
catch
{
Add-Type -ReferencedAssemblies ('System.Windows.Forms', 'System.Drawing') -TypeDefinition @"
using System;
using System.Windows.Forms;
using System.Drawing;
namespace SAPIENTypes
{
public class ProgressBarOverlay : System.Windows.Forms.ProgressBar
{
public ProgressBarOverlay() : base() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); }
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x000F)// WM_PAINT
{
if (Style != System.Windows.Forms.ProgressBarStyle.Marquee || !string.IsNullOrEmpty(this.Text))
{
using (Graphics g = this.CreateGraphics())
{
using (StringFormat stringFormat = new StringFormat(StringFormatFlags.NoWrap))
{
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
if (!string.IsNullOrEmpty(this.Text))
g.DrawString(this.Text, this.Font, Brushes.Black, this.ClientRectangle, stringFormat);
else
{
int percent = (int)(((double)Value / (double)Maximum) * 100);
g.DrawString(percent.ToString() + "%", this.Font, Brushes.Black, this.ClientRectangle, stringFormat);
}
}
}
}
}
}
public string TextOverlay
{
get
{
return base.Text;
}
set
{
base.Text = value;
Invalidate();
}
}
}
}
"@ -IgnoreWarnings | Out-Null
}
try{
[FolderBrowserModernDialog] | Out-Null
}
catch
{
Add-Type -ReferencedAssemblies ('System.Windows.Forms') -TypeDefinition @"
using System;
using System.Windows.Forms;
using System.Reflection;
namespace SAPIENTypes
{
public class FolderBrowserModernDialog : System.Windows.Forms.CommonDialog
{
private System.Windows.Forms.OpenFileDialog fileDialog;
public FolderBrowserModernDialog()
{
fileDialog = new System.Windows.Forms.OpenFileDialog();
fileDialog.Filter = "Folders|\n";
fileDialog.AddExtension = false;
fileDialog.CheckFileExists = false;
fileDialog.DereferenceLinks = true;
fileDialog.Multiselect = false;
fileDialog.Title = "Select a folder";
}
public string Title
{
get { return fileDialog.Title; }
set { fileDialog.Title = value; }
}
public string InitialDirectory
{
get { return fileDialog.InitialDirectory; }
set { fileDialog.InitialDirectory = value; }
}
public string SelectedPath
{
get { return fileDialog.FileName; }
set { fileDialog.FileName = value; }
}
object InvokeMethod(Type type, object obj, string method, object[] parameters)
{
MethodInfo methInfo = type.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return methInfo.Invoke(obj, parameters);
}
bool ShowOriginalBrowserDialog(IntPtr hwndOwner)
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
folderBrowserDialog.Description = this.Title;
folderBrowserDialog.SelectedPath = !string.IsNullOrEmpty(this.SelectedPath) ? this.SelectedPath : this.InitialDirectory;
folderBrowserDialog.ShowNewFolderButton = false;
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
fileDialog.FileName = folderBrowserDialog.SelectedPath;
return true;
}
return false;
}
protected override bool RunDialog(IntPtr hwndOwner)
{
if (Environment.OSVersion.Version.Major >= 6)
{
try
{
bool flag = false;
System.Reflection.Assembly assembly = Assembly.Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Type typeIFileDialog = assembly.GetType("System.Windows.Forms.FileDialogNative").GetNestedType("IFileDialog", BindingFlags.NonPublic);
uint num = 0;
object dialog = InvokeMethod(fileDialog.GetType(), fileDialog, "CreateVistaDialog", null);
InvokeMethod(fileDialog.GetType(), fileDialog, "OnBeforeVistaDialog", new object[] { dialog });
uint options = (uint)InvokeMethod(typeof(System.Windows.Forms.FileDialog), fileDialog, "GetOptions", null) | (uint)0x20;
InvokeMethod(typeIFileDialog, dialog, "SetOptions", new object[] { options });
Type vistaDialogEventsType = assembly.GetType("System.Windows.Forms.FileDialog").GetNestedType("VistaDialogEvents", BindingFlags.NonPublic);
object pfde = Activator.CreateInstance(vistaDialogEventsType, fileDialog);
object[] parameters = new object[] { pfde, num };
InvokeMethod(typeIFileDialog, dialog, "Advise", parameters);
num = (uint)parameters[1];
try
{
int num2 = (int)InvokeMethod(typeIFileDialog, dialog, "Show", new object[] { hwndOwner });
flag = 0 == num2;
}
finally
{
InvokeMethod(typeIFileDialog, dialog, "Unadvise", new object[] { num });
GC.KeepAlive(pfde);
}
return flag;
}
catch
{
return ShowOriginalBrowserDialog(hwndOwner);
}
}
else
return ShowOriginalBrowserDialog(hwndOwner);
}
public override void Reset()
{
fileDialog.Reset();
}
}
}
"@ -IgnoreWarnings | Out-Null
}
#endregion Define SAPIEN Types
#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$MainForm = New-Object 'System.Windows.Forms.Form'
$ProductListBox = New-Object 'System.Windows.Forms.ListBox'
$SCConfigMgrLogo = New-Object 'System.Windows.Forms.PictureBox'
$DescriptionText = New-Object 'System.Windows.Forms.TextBox'
$RemoveItemsButton = New-Object 'System.Windows.Forms.Button'
$SelectionTabs = New-Object 'System.Windows.Forms.TabControl'
$OSTab = New-Object 'System.Windows.Forms.TabPage'
$PleaseNnoteText = New-Object 'System.Windows.Forms.TextBox'
$PleaseNoteLabel = New-Object 'System.Windows.Forms.Label'
$ArchitectureComboxBox = New-Object 'System.Windows.Forms.ComboBox'
$DownloadComboBox = New-Object 'System.Windows.Forms.ComboBox'
$PlatformComboBox = New-Object 'System.Windows.Forms.ComboBox'
$OSComboBox = New-Object 'System.Windows.Forms.ComboBox'
$ArchitectureCheckBox = New-Object 'System.Windows.Forms.Label'
$SelectDeployLabel = New-Object 'System.Windows.Forms.Label'
$OperatingSysLabel = New-Object 'System.Windows.Forms.Label'
$DownloadTypeLabel = New-Object 'System.Windows.Forms.Label'
$ManufacturerTab = New-Object 'System.Windows.Forms.TabPage'
$MicrosoftCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$FindModelsButton = New-Object 'System.Windows.Forms.Button'
$PleaseSelectManufactLabel = New-Object 'System.Windows.Forms.Label'
$LenovoCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$HPCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$DellCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$FullModelListBox = New-Object 'System.Windows.Forms.ListBox'
$AddToListButton = New-Object 'System.Windows.Forms.Button'
$AcerCheckbox = New-Object 'System.Windows.Forms.CheckBox'
$DriverStorageTab = New-Object 'System.Windows.Forms.TabPage'
$PackageBrowseButton = New-Object 'System.Windows.Forms.Button'
$PackagePathTextBox = New-Object 'System.Windows.Forms.TextBox'
$RepositoryBrowseButton = New-Object 'System.Windows.Forms.Button'
$RepositoryTextBox = New-Object 'System.Windows.Forms.TextBox'
$PleaseNoteStorageText = New-Object 'System.Windows.Forms.TextBox'
$PleaseNoteStorageLabel = New-Object 'System.Windows.Forms.Label'
$PackagePathLabel = New-Object 'System.Windows.Forms.Label'
$RepositoryLabel = New-Object 'System.Windows.Forms.Label'
$DistributionTab = New-Object 'System.Windows.Forms.TabPage'
$EnableBinaryDifCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$DGGroupBox = New-Object 'System.Windows.Forms.GroupBox'
$DPGListBox = New-Object 'System.Windows.Forms.ListBox'
$DPGroupBox = New-Object 'System.Windows.Forms.GroupBox'
$DPListBox = New-Object 'System.Windows.Forms.ListBox'
$DriverCleanTab = New-Object 'System.Windows.Forms.TabPage'
$RemoveSourceLabel = New-Object 'System.Windows.Forms.Label'
$RemoveDriverSourceCheckbox = New-Object 'System.Windows.Forms.CheckBox'
$RemoveSupersededLabel = New-Object 'System.Windows.Forms.Label'
$RemoveLegacyDriverCheckbox = New-Object 'System.Windows.Forms.CheckBox'
$labelSelectingThisOptionW = New-Object 'System.Windows.Forms.Label'
$CleanUnusedCheckBox = New-Object 'System.Windows.Forms.CheckBox'
$SCConfigMgrLink = New-Object 'System.Windows.Forms.LinkLabel'
$SCCMDellTabControl = New-Object 'System.Windows.Forms.TabControl'
$ConfigMgrTabPage1 = New-Object 'System.Windows.Forms.TabPage'
$SiteCodeText = New-Object 'System.Windows.Forms.TextBox'
$SiteServerInput = New-Object 'System.Windows.Forms.TextBox'
$ConnectSCCMButton = New-Object 'System.Windows.Forms.Button'
$SiteCodeLabel = New-Object 'System.Windows.Forms.Label'
$SiteServerLabel = New-Object 'System.Windows.Forms.Label'
$ConfigMgrTabPage2 = New-Object 'System.Windows.Forms.TabPage'
$UseProxyServerCheckbox = New-Object 'System.Windows.Forms.CheckBox'
$ProxyPswdInput = New-Object 'System.Windows.Forms.TextBox'
$PasswordLabel = New-Object 'System.Windows.Forms.Label'
$ProxyUserInput = New-Object 'System.Windows.Forms.TextBox'
$UsernameLabel = New-Object 'System.Windows.Forms.Label'
$ProxyServerInput = New-Object 'System.Windows.Forms.TextBox'
$ProxyServerLabel = New-Object 'System.Windows.Forms.Label'
$ClearSelectionButton = New-Object 'System.Windows.Forms.Button'
$ModelProgressOverlay = New-Object 'SAPIENTypes.ProgressBarOverlay'
$ProgressBar = New-Object 'System.Windows.Forms.ProgressBar'
$ProgressListBox = New-Object 'System.Windows.Forms.ListBox'
$AutomationLabel = New-Object 'System.Windows.Forms.Label'
$StartDownloadButton = New-Object 'System.Windows.Forms.Button'
$SelectedLabel = New-Object 'System.Windows.Forms.Label'
$LoggingLabel = New-Object 'System.Windows.Forms.Label'
$ModelProgressLabel = New-Object 'System.Windows.Forms.Label'
$labelThisScriptIsUsedAtYo = New-Object 'System.Windows.Forms.Label'
$RepositoryBrowseFolderDialogue = New-Object 'SAPIENTypes.FolderBrowserModernDialog'
$PackageBrowseFolderDialogue = New-Object 'SAPIENTypes.FolderBrowserModernDialog'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects
#----------------------------------------------
# User Generated Script
#----------------------------------------------
$MainForm_Load = {
# Initialise Form
$MainForm.Visible = $true
Write-CMLogEntry -Value "======== INITIALISING LOG FILE & CHECKING PREREQUISITES ========" -Severity 1
Write-CMLogEntry -Value "Info: Log File Location - $TempDirectory" -Severity 1
If (($ScriptRelease -ne $null) -and ($ScriptRelease -lt $NewRelease))
{
Write-CMLogEntry -Value "Update Alert: Newer Version Available - $NewRelease" -Severity 2 -SkipGuiLog $true
Write-CMLogEntry -Value "Update Alert: Opening New Version Form" -Severity 2 -SkipGuiLog $true
Show-UpdateForm_psf
}
# Attempt ConfigMgr Site Code & MP Detection
Write-CMLogEntry -Value "Info: Checking WMI for ConfigMgr SMS_Authority Values" -Severity 1 -SkipGuiLog $true
$SCCMWMI = Get-CIMInstance -ClassName SMS_Authority -NameSpace root\ccm
if ($SCCMWMI.CurrentManagementPoint -ne $null)
{
Write-CMLogEntry -Value "======== ConfigMgr Site Discovery ========" -Severity 1
$SiteServerInput.Text = $SCCMWMI.CurrentManagementPoint
Write-CMLogEntry -Value "Info: ConfigMgr WMI Query Results - Site Server (Local MP) Found: $($SiteServerInput.Text)" -Severity 1 -SkipGuiLog $true
$SiteCodeText.Text = ($SCCMWMI.Name).TrimStart("SMS:")
Write-CMLogEntry -Value "Info: ConfigMgr WMI Query Results - Site Code Found: $($SiteCodeText.Text)" -Severity 1 -SkipGuiLog $true
ConnectSCCM
}
# Check PS Version Compatibilty
if ($PSVersionTable.PSVersion.Major -lt "3")
{
Write-CMLogEntry -Value "======== COMPATIBILITY ISSUE DETECTED ========" -Severity 3
Write-CMLogEntry -Value "Error: PowerShell Version Incompatible - Please Update PS Installation" -Severity 3
}
# Check for 7Zip Installation for Acer Drivers
Write-CMLogEntry -Value "Info: Checking For 7-Zip Installation" -Severity 1 -SkipGuiLog $true
# Read registry installed applications
$64BitApps = Get-ChildItem -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall -Recurse | Get-ItemProperty
$32BitApps = Get-ChildItem -Path HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall -Recurse | Get-ItemProperty
foreach ($App in $64BitApps)
{
if ($App.DisplayName -match "7-Zip")
{
$7ZipInstalled = $true
}
}
foreach ($App in $32BitApps)
{
if ($App.DisplayName -match "7-Zip")
{
$7ZipInstalled = $true
}
}
if ($7ZipInstalled -eq $true)
{
$AcerCheckbox.Enabled = $true
}
else
{
$AcerCheckbox.Enabled = $false
Write-CMLogEntry -Value "======== ACER COMPATIBILITY ISSUE DETECTED ========" -Severity 3
Write-CMLogEntry -Value "Error: Prerequisite 7-Zip Not Found - Acer Support Disabled" -Severity 3
}
# // Default Selection - Edit this section for your standard paths etc
$OSComboBox.SelectedIndex = 2
$PlatformComboBox.SelectedIndex = 1
$ArchitectureComboxBox.SelectedIndex = 0
$DownloadComboBox.SelectedIndex = 0
#$PackagePathTextBox.Text = "\\SERVER\UNCPATH"
#$RepositoryTextBox.Text = "\\SERVER\UNCPATH"
}
$StartDownloadButton_Click = {
# Reset Progress Bar
$ProgressBar.Value = "0"
$ModelProgressOverlay.Value = "0"
$ProgressListBox.ForeColor = 'Black'
# Set Variables Retrieved From GUI
$ImportInto = [string]$PlatformComboBox.SelectedItem
Write-CMLogEntry -Value "Info: Importing Into Products: $ImportInto" -Severity 1 -SkipGuiLog $true
$DownloadType = [string]$DownloadComboBox.SelectedItem
Write-CMLogEntry -Value "Info: Download Type: $DownloadType" -Severity 1 -SkipGuiLog $true
$SiteCode = $SiteCodeText.Text
# Set Models
if ($($ProductListBox.SelectedItems).count -gt 0)
{
$ImportModels = $ProductListBox.SelectedItems
}
else
{
$ImportModels = $ProductListBox.Items
}
# Set Initial Validation State
$ValidationErrors = 0
# ============ Validation Selection Details and Prerequisites ==============
# Reset Job Process Log Dialog
if (($ProgressListBox.ForeColor) -eq "Red") { $ProgressListBox.Items.Clear() }
# Validate Selected Models
if (($ImportModels.Count) -lt "1")
{
Write-CMLogEntry -Value "Error: No Models Selected" -Severity 3
$ValidationErrors++
}
# Validate Repository Path For BIOS & Driver Downloads
if ((Test-Path -Path $RepositoryTextBox.Text) -eq $true)
{
$RepositoryPath = [string]$RepositoryTextBox.Text
Write-CMLogEntry -Value "Pre-Check: Respository Path Set To $RepositoryPath" -Severity 1
}
else
{
Write-CMLogEntry -Value "Error: UNC Repository Path Specified Could Not Be Found $($RepositoryTextBox.Text)" -Severity 3
$ValidationErrors++
}
# Validate Package Path For ConfigMgr Driver Imports
if (($ImportInto -like "ConfigMgr*") -or ($ImportInto -like "Both*"))
{
if ($DownloadType -ne "BIOS")
{
if ((Test-Path -path $PackagePathTextBox.Text) -eq $true)
{
$PackagePath = [string]$PackagePathTextBox.Text
}
else
{
Write-CMLogEntry -Value "Error: UNC Package Path Specified Could Not Be Found $($PackagePathTextBox.Text)" -Severity 3
$ValidationErrors++
}
}
}
# Validate OS Selection
if (($OSComboBox).Text -ne $null)
{
$WindowsVersion = (($OSComboBox).Text).Split(" ")[1]
}
else
{
Write-CMLogEntry -Value "Error: Operating System Not Specified" -Severity 3
$ValidationErrors++
}
# Validate OS Architecture Selection
if (($ArchitectureComboxBox).Text -ne $null)
{
$Architecture = "x" + ($ArchitectureComboxBox.Text).Trim(" bit")
}
else
{
Write-CMLogEntry -Value "Error: Operating System Architecture Not Specified" -Severity 3
$ValidationErrors++
}
# Set Proxy Variables
if ($UseProxyServerCheckbox.Checked -eq $true)
{
$ProxyUser = [string]$ProxyUserInput.Text
$ProxyPswd = ConvertTo-SecureString $([string]$ProxyPswdInput.Text) -AsPlainText -Force
$ProxyServer = [string]$ProxyServerInput.Text
$ProxyCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ProxyUser, $ProxyPswd
Write-CMLogEntry -Value "Info: Downloading through proxy $ProxyServer" -Severity 1
$ProxyValidated = $true
}
# Download ScriptBlock
$DriverDownloadJob = {
Param ([string]$DriverRepositoryRoot,
[string]$Model,
[string]$DriverCab,
[string]$DriverDownloadURL,
$ProxyServer,
$ProxyCred)
# Start Driver Download
if ($ProxyCred -ne $null)
{
Start-BitsTransfer -DisplayName "$Model-DriverDownload" -Source $DriverDownloadURL -Destination "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)" -RetryTimeout 90 -RetryInterval 180 -Asynchronous -ProxyList $ProxyServer -ProxyAuthentication NTLM -ProxyCredential $ProxyCred -ProxyUsage SystemDefault -Priority Foreground
}
else
{
Start-BitsTransfer -DisplayName "$Model-DriverDownload" -Source $DriverDownloadURL -Destination "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)" -RetryTimeout 90 -RetryInterval 180 -Asynchronous
}
}
# MDT Import SriptBlock
$MDTImportJob = {
Param ([string]$PSDriveName,
[string]$MDTDriverPath,
[string]$Make,
[string]$Model,
[string]$DriverRevision,
[string]$OperatingSystemDir,
[string]$DriverExtractDest,
[string]$DeploymentShare,
[string]$Architecture)
Import-Module "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1"
Write-CMLogEntry -Value "$($Product): Reading MDT PS Module from C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1" -Severity 1 -SkipGuiLog $true
New-PSDrive -Name $PSDriveName -PSProvider MDTProvider -Root $DeploymentShare
# =============== MDT Driver Import ====================
if ($Make -eq "Dell")
{
$DriverFolder = (Get-ChildItem -Path "$DriverExtractDest" -Recurse | Where-Object { ($_.PSisContainer -eq $true) -and ($_.Name -eq "$Architecture") } | Select -first 1).FullName
Write-CMLogEntry -Value "$($Product): Importing MDT Drivers from $DriverExtractDest" -Severity 1 -SkipGuiLog $true
Import-MDTDriver -path "$MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision" -SourcePath "$DriverFolder"
}
else
{
Write-CMLogEntry -Value "$($Product): Importing MDT Drivers from $DriverExtractDest" -Severity 1 -SkipGuiLog $true
Import-MDTDriver -path "$MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision" -SourcePath "$DriverExtractDest"
}
}
# Move HP Driver Function
$MoveHPDrivers = {
Param ($HPExtract,
$DriverExtractDest)
Get-ChildItem -Path "$HPExtract" | Move-Item -Destination "$DriverExtractDest" -Verbose
#Remove-Item -Path "$HPExtract"
}
# Copy Drivers To Package Location (Standard)
$PackageDrivers = {
Param ($Make,
$DriverExtractDest,
$Architecture,
$DriverPackageDest)
if ($Make -eq "Dell")
{
Copy-Item -Path $(Get-ChildItem -Path "$DriverExtractDest" -Recurse -Directory | Where-Object { $_.Name -eq "$Architecture" } | Select-Object -First 1).FullName -Destination "$DriverPackageDest" -Container -Recurse
Write-CMLogEntry -Value "$($Product): Copying Drivers from $DriverExtractDest to $DriverPackageDest" -Severity 1 -SkipGuiLog $True
}
else
{
Copy-Item -Path "$DriverExtractDest" -Destination "$DriverPackageDest" -Container -Recurse
Write-CMLogEntry -Value "$($Product): Copying Drivers from $DriverExtractDest to $DriverPackageDest" -Severity 1 -SkipGuiLog $True
}
}
# Validate MDT PowerShell Commandlets / Install
if ((($ImportInto) -like ("MDT" -or "Both*")) -and ($ValidationErrors -eq 0))
{
# Validate MDT PS Commandlets
if ((Test-Path -Path $MDTPSCommandlets) -eq $true)
{
# Import MDT Module
Write-CMLogEntry -Value "$($Product): Importing: MDT PowerShell Commandlets" -Severity 1
Import-Module $MDTPSCommandlets
}
else
{
Write-CMLogEntry -Value "Error: MDT PowerShell Commandlets file not found at $MDTPSCommandlets" -Severity 1
$ValidationErrors++
}
}
if ($ValidationErrors -eq 0)
{
Write-CMLogEntry -Value "======== Starting Download Processes ========" -Severity 1
if ($ProductListBox.SelectedItems -ge 1)
{
Write-CMLogEntry -Value "Info: Models selected: $($ProductListBox.SelectedItems)" -Severity 1
}
else
{
Write-CMLogEntry -Value "Info: Models selected: $($ProductListBox.Items)" -Severity 1
}
Write-CMLogEntry -Value "Info: Operating System specified: Windows $($WindowsVersion)" -Severity 1
Write-CMLogEntry -Value "Info: Operating System architecture specified: $($Architecture)" -Severity 1
Write-CMLogEntry -Value "Info: Site Code specified: $($SiteCode)" -Severity 1
Write-CMLogEntry -Value "Info: Respository Path specified: $($RepositoryPath)" -Severity 1
Write-CMLogEntry -Value "Info: Package Path specified: $($PackagePath)" -Severity 1
# Operating System Version
$OperatingSystem = ("Windows " + $($WindowsVersion))
if ($ProductListBox.SelectedItems.Count -ge 1)
{
$TotalModelCount = $ProductListBox.SelectedItems.Count
}
else
{
$TotalModelCount = $ProductListBox.Items.Count
}
$RemainingModels = $TotalModelCount
# Initialise Job Progress Bar
$ProgressBar.Maximum = $TotalModelCount
$ModelProgressOverlay.Maximum = $TotalModelCount
foreach ($Model in $ImportModels)
{
Write-CMLogEntry -Value "======== Processing $Model Downloads ========" -Severity 1
# Vendor Make
$Make = $($Model).split(" ")[0]
$Model = $($Model).TrimStart("$Make")
$Model = $Model.Trim()
# Lookup OS Build Number
if ($OSComboBox.Text -like "Windows 10 1*")
{
Write-CMLogEntry -Value "Info: Windows 10 Build Lookup Required" -Severity 1 -SkipGuiLog $true
# Extract Windows 10 Version Number
$OSVersion = ([string]($OSComboBox).Text).Split(' ')[2]
# Get Windows Build Number From Version Hash Table
$OSBuild = $WindowsBuildHashTable.Item([int]$OSVersion)
Write-CMLogEntry -Value "Info: Windows 10 Build $OSBuild Identified For Driver Match" -Severity 1 -SkipGuiLog $true
}
Write-CMLogEntry -Value "Info: Starting Download,Extract And Import Processes For $Make Model: $($Model)" -Severity 1 -SkipGuiLog $true
# =================== DEFINE VARIABLES =====================
# Directory used for driver and BIOS downloads
$DriverRepositoryRoot = ($RepositoryPath.Trimend("\") + "\$Make\")
# Directory used by ConfigMgr for driver packages
if (($ImportInto -like "*ConfigMgr*") -and ($DownloadType -ne "BIOS")) { $DriverPackageRoot = ($PackagePath.Trimend("\") + "\$Make\") }
# =================== VENDOR SPECIFIC UPDATES ====================
if ($Make -eq "Dell")
{
Write-CMLogEntry -Value "Info: Setting Dell Variables" -Severity 1 -SkipGuiLog $true
if ($global:DellModelCabFiles -eq $null)
{
[xml]$DellModelXML = Get-Content -Path $TempDirectory\$DellXMLFile
# Set XML Object
$DellModelXML.GetType().FullName
$global:DellModelCabFiles = $DellModelXML.driverpackmanifest.driverpackage
}
$ModelURL = $DellDownloadBase + "/" + ($global:DellModelCabFiles | Where-Object { ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$Model*") }).delta
$ModelURL = $ModelURL.Replace("\", "/")
$DriverDownload = $DellDownloadBase + "/" + ($global:DellModelCabFiles | Where-Object { ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$Model") }).path
$DriverCab = (($global:DellModelCabFiles | Where-Object { ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$Model") }).path).Split("/") | select -Last 1
$DriverRevision = (($DriverCab).Split("-")[2]).Trim(".cab")
}
if ($Make -eq "HP")
{
Write-CMLogEntry -Value "Info: Setting HP Variables" -Severity 1 -SkipGuiLog $true
if ($global:HPModelSoftPaqs -eq $null)
{
[xml]$global:HPModelXML = Get-Content -Path $TempDirectory\$HPXMLFile
# Set XML Object
$global:HPModelXML.GetType().FullName
$global:HPModelSoftPaqs = $global:HPModelXML.NewDataSet.HPClientDriverPackCatalog.ProductOSDriverPackList.ProductOSDriverPack
}
if ($OSComboBox.Text -like "Windows 10 1*")
{
$HPSoftPaqSummary = $global:HPModelSoftPaqs | Where-Object { ($_.SystemName -like "*$Model*") -and ($_.OSName -like "Windows*$(($OSComboBox.Text).Split(' ')[1])*$(($ArchitectureComboxBox.Text).Trim(' bit'))*$((($OSComboBox.Text).Split(' ')[2]).Trim())*") }
}
else
{
$HPSoftPaqSummary = $global:HPModelSoftPaqs | Where-Object { ($_.SystemName -like "*$Model*") -and ($_.OSName -like "Windows*$(($OSComboBox.Text).Split(' ')[1])*$(($ArchitectureComboxBox.Text).Trim(' bit'))*") }
}
$HPSoftPaq = $HPSoftPaqSummary.SoftPaqID
$HPSoftPaqDetails = $global:HPModelXML.newdataset.hpclientdriverpackcatalog.softpaqlist.softpaq | Where-Object { $_.ID -eq "$HPSoftPaq" }
$ModelURL = $HPSoftPaqDetails.URL
# Replace FTP for HTTP for Bits Transfer Job
$DriverDownload = "http:" + ($HPSoftPaqDetails.URL).TrimStart("ftp:")
$DriverCab = $ModelURL | Split-Path -Leaf
$DriverRevision = "$($HPSoftPaqDetails.Version)"
}
if ($Make -eq "Lenovo")
{
Write-CMLogEntry -Value "Info: Setting Lenovo Variables" -Severity 1 -SkipGuiLog $true
LenovoModelTypeFinder -Model $Model -OS $OS
Write-CMLogEntry -Value "Info: $Make $Model matching model type: $global:LenovoModelType" -Severity 1 -SkipGuiLog $false
if ($global:LenovoModelDrivers -ne $null)
{
[xml]$global:LenovoModelXML = (New-Object System.Net.WebClient).DownloadString("$LenovoXMLSource")
# Set XML Object
$global:LenovoModelXML.GetType().FullName
$global:LenovoModelDrivers = $global:LenovoModelXML.Products
$LenovoDriver = (($global:LenovoModelDrivers.Product | Where-Object { $_.model -eq $Model }).driverPack | Where-Object { $_.id -eq "SCCM" })."#text"
}
if ($WindowsVersion -ne "7")
{
Write-CMLogEntry -Value "Info: Looking Up Lenovo $Model URL For Windows Version win$(($WindowsVersion).Trim('.'))" -Severity 1 -SkipGuiLog $true
$ModelURL = (($global:LenovoModelDrivers.Product | Where-Object { ($_.model -eq "$Model") -and ($_.os -eq "win$(($WindowsVersion -replace '[.]', ''))") }).driverPack | Where-Object { $_.id -eq "SCCM" })."#text" | Select -First 1
}
else
{
Write-CMLogEntry -Value "Info: Looking Up Lenovo $Model URL For Windows Version win$(($WindowsVersion).Trim('.'))" -Severity 1 -SkipGuiLog $true
$ModelURL = (($global:LenovoModelDrivers.Product | Where-Object { ($_.model -eq "$Model") -and ($_.os -eq "win$WindowsVersion$(($ArchitectureComboxBox.Text).Split(' ')[0])") }).driverPack | Where-Object { $_.id -eq "SCCM" })."#text" | Select -First 1
}
if ($DownloadType -ne "BIOS")
{
if ($Architecture -eq "x86")
{
$DriverDownload = FindDriver -URI $ModelURL -os $WindowsVersion -64bit $false -ProxyServer $ProxyServer -ProxyCred $ProxyCred
}
else
{
$DriverDownload = FindDriver -URI $ModelURL -os $WindowsVersion -64bit $true -ProxyServer $ProxyServer -ProxyCred $ProxyCred
}
If ($DriverDownload -ne "badlink")
{
$DriverCab = $DriverDownload | Split-Path -Leaf
$DriverRevision = ($DriverCab.Split("_") | Select -Last 1).Trim(".exe")
}
else
{
Write-CMLogEntry -Value "Error: Unable to find driver for $Make $Model" -Severity 1 -SkipGuiLog $false
}
}
}
if ($Make -eq "Acer")
{
Write-CMLogEntry -Value "Info: Setting Acer Variables" -Severity 1 -SkipGuiLog $true
$AcerModelDrivers = (Invoke-WebRequest -Uri $AcerSCCMSource).Links
$AcerDriver = $AcerModelDrivers | Where-Object { $_.outerText -match $Model }
$ModelURL = (($AcerDriver | Where-Object { $_.OuterText -like "*$($WindowsVersion)*$(($ArchitectureComboxBox.Text).Split(' ')[0])*" }).href)
$DriverDownload = "http:" + $ModelURL
$DriverCab = $DriverDownload | Split-Path -Leaf
$DriverRevision = "NA"
}
if ($Make -eq "Microsoft")
{
Write-CMLogEntry -Value "Info: Setting Microsoft Variables" -Severity 1 -SkipGuiLog $true
[xml]$MicrosoftModelXML = (New-Object System.Net.WebClient).DownloadString("$MicrosoftXMLSource")
# Set XML Object
$MicrosoftModelXML.GetType().FullName
$MicrosoftModelDrivers = $MicrosoftModelXML.Drivers
$ModelURL = ((($MicrosoftModelDrivers.Model | Where-Object { ($_.name -match "$Model") }).OSSupport) | Where-Object { $_.Name -eq "win$(($WindowsVersion).Trim("."))" }).DownloadURL
$DriverDownload = Get-RedirectedUrl -URL "$ModelURL" -ErrorAction Continue -WarningAction Continue
$DriverCab = $DriverDownload | Split-Path -Leaf
$DriverRevision = ($DriverCab.Split("_") | Select -Last 2).Trim(".msi")[0]
}
if ($DownloadType -ne "BIOS")
{
# Driver variables & switches
$DriverSourceCab = ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab)
$DriverPackageDir = ($DriverCab).Substring(0, $DriverCab.length - 4)
$DriverCabDest = $DriverPackageRoot + $DriverPackageDir
}
# Cater for Dell driver packages (both x86 and x64 drivers contained within a single package)
if ($Make -eq "Dell")
{
$DriverExtractDest = ("$DriverRepositoryRoot" + $Model + "\" + "Windows$WindowsVersion-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Extract Location Set - $DriverExtractDest" -Severity 1 -SkipGuiLog $true
$DriverPackageDest = ("$DriverPackageRoot" + "$Model" + "-" + "Windows$WindowsVersion-$Architecture-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Package Location Set - $DriverPackageDest" -Severity 1 -SkipGuiLog $true
}
else
{
If ($OSBuild -eq $null)
{
$DriverExtractDest = ("$DriverRepositoryRoot" + $Model + "\" + "Windows$WindowsVersion-$Architecture-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Extract Location Set - $DriverExtractDest" -Severity 1 -SkipGuiLog $true
$DriverPackageDest = ("$DriverPackageRoot" + "$Model" + "\" + "Windows$WindowsVersion-$Architecture-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Package Location Set - $DriverPackageDest" -Severity 1 -SkipGuiLog $true
}
else
{
$DriverExtractDest = ("$DriverRepositoryRoot" + $Model + "\" + "Windows$WindowsVersion-$OSBuild-$Architecture-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Extract Location Set - $DriverExtractDest" -Severity 1 -SkipGuiLog $true
$DriverPackageDest = ("$DriverPackageRoot" + "$Model" + "\" + "Windows$WindowsVersion-$OSBuild-$Architecture-$DriverRevision")
Write-CMLogEntry -Value "Info: Driver Package Location Set - $DriverPackageDest" -Severity 1 -SkipGuiLog $true
}
# Replace HP Model Slash
$DriverExtractDest = $DriverExtractDest -replace '/', '-'
$DriverPackageDest = $DriverPackageDest -replace '/', '-'
}
# Allow for both Driver & Standard Program Packages destinations
if ($ImportInto -like "*Driver*")
{
$DriverPackageDest = $DriverPackageDest + "\DriverPkg\"
}
if ($ImportInto -like "*Standard*")
{
$DriverPackageDest = $DriverPackageDest + "\StandardPkg\"
}
# Driver variables & switches
$DriverCategoryName = $Make + "-" + $Model + "-" + $OperatingSystem + "-" + $DriverRevision
# =================== INITIATE DOWNLOADS ===================
if ($ImportInto -ne "MDT")
{
# Product Type Display
if ($ImportInto -eq "Download Only")
{
$Product = "Download Only"
}
else
{
$Product = "ConfigMgr"
}
if ($DownloadType -ne "Drivers")
{
Write-CMLogEntry -Value "======== $MODEL BIOS PROCESSING STARTED ========" -Severity 1
if ($Make -eq "Dell")
{
# ================= Dell BIOS Upgrade Download ==================
$DellBIOSDownload = DellBiosFinder -Model $Model
$BIOSDownload = $DellDownloadBase + "/" + $($DellBIOSDownload.Path)
$BIOSVer = $DellBIOSDownload.DellVersion
Write-CMLogEntry -Value "Info: Latest available BIOS version is $BIOSVer" -Severity 1
$BIOSFile = $DellBIOSDownload.Path | Split-Path -Leaf
$BIOSVerDir = $BIOSVer -replace '\.', '-'
$BIOSUpdateRoot = ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSVerDir + "\")
if (($BIOSDownload -like "*.exe") -and ($Make -eq "Dell"))
{
Write-CMLogEntry -Value "Info: BIOS Download URL Found: $BIOSDownload" -Severity 2
# Check for destination directory, create if required and download the BIOS upgrade file
if ((Test-Path -Path "$($DriverRepositoryRoot + $Model + '\BIOS\' + $BIOSVerDir + '\' + $BIOSFile)") -eq $false)
{
If ((Test-Path -Path $BIOSUpdateRoot) -eq $false)
{
Write-CMLogEntry -Value "Info: Creating $BIOSUpdateRoot folder" -Severity 1
New-Item -Path $BIOSUpdateRoot -ItemType Directory
}
Write-CMLogEntry -Value "Info: Downloading $($BIOSFile) BIOS update file" -Severity 1
if ($UseProxyServerCheckbox.Checked -eq $true)
{
Start-BitsTransfer $BIOSDownload -Destination "$($BIOSUpdateRoot + $BIOSFile)" -RetryTimeout 90 -RetryInterval 180 -ProxyList $ProxyServer -ProxyList $ProxyServer -ProxyAuthentication NTLM -ProxyCredential $ProxyCred -ProxyUsage SystemDefault
}
else
{
Start-BitsTransfer $BIOSDownload -Destination "$($BIOSUpdateRoot + $BIOSFile)" -RetryTimeout 90 -RetryInterval 180
}
}
else
{
Write-CMLogEntry -Value "Info: Skipping $BIOSFile... File already downloaded." -Severity 2
}
}
if ($Product -ne "Download Only")
{
# ================= Create BIOS Update Package ==================
Set-Location -Path ($SiteCode + ":")
$BIOSUpdatePackage = ("BIOS Update - " + "$Make" + " " + $Model)
$BIOSModelPackage = Get-CMPackage | Where-Object { $_.Name -match $BIOSUpdatePackage } | Sort-Object SourceDate -Descending | select -First 1
if (($BIOSModelPackage.Version -ne $BIOSVer) -or ($BIOSModelPackage -eq $null))
{
Write-CMLogEntry -Value "$($Product): Creating BIOS Package" -Severity 1
New-CMPackage -Name "$BIOSUpdatePackage" -Path "$BIOSUpdateRoot" -Description "$Make $Model BIOS Updates" -Manufacturer "$Make" -Language English -version $BIOSVer
if ($EnableBinaryDifCheckBox.Checked -eq $true)
{
Write-CMLogEntry -Value "$($Product): Enabling Binary Delta Replication" -Severity 1
Set-CMPackage -Name "$BIOSUpdatePackage" -EnableBinaryDeltaReplication $true
}
Set-Location -Path $TempDirectory
# ================= Dell Flash 64 Upgrade Download ==================
$FlashUtilDir = $DriverRepositoryRoot + "\Flash64Utility\"
$Flash64BitDownload = (Invoke-WebRequest -Uri $Dell64BIOSUtil).links | Where-Object { $_.OuterText -eq "Here" }
$Flash64BitZip = $($FlashUtilDir + $(($Flash64BitDownload).href | Split-Path -Leaf))
if ((Test-Path -Path $FlashUtilDir) -eq $false)
{
New-Item -ItemType Directory -Path $FlashUtilDir | Out-Null
Write-CMLogEntry -Value "Info: Creating Directory - $FlashUtilDir" -Severity 1 -SkipGuiLog $True
Write-CMLogEntry -Value "Info: Downloading Dell Flash64 EXE From $($Flash64BitDownload.href) Using BITS" -Severity 1 -SkipGuiLog $True
if ($UseProxyServerCheckbox.Checked -eq $true)
{
Start-BitsTransfer ($Flash64BitDownload.href) -Destination "$($Flash64BitZip)" -RetryTimeout 90 -RetryInterval 180 -ProxyList $ProxyServer -ProxyList $ProxyServer -ProxyAuthentication NTLM -ProxyCredential $ProxyCred -ProxyUsage SystemDefault
}
else
{
Start-BitsTransfer ($Flash64BitDownload.href) -Destination "$($Flash64BitZip)" -RetryTimeout 90 -RetryInterval 180
}
# Unzip Flash64 Exe
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::ExtractToDirectory("$($Flash64BitZip)", "$($FlashUtilDir)")
Write-CMLogEntry -Value "Info: Unzipping Dell Flash64 EXE" -Severity 1 -SkipGuiLog $True
}
$Flash64BitExe = Get-ChildItem -Path "$($FlashUtilDir)" -Filter *.exe -File
Get-ChildItem -Path "$($FlashUtilDir)" -Filter *.EXE -File | Copy-Item -Destination "$($BIOSUpdateRoot)"
Write-CMLogEntry -Value "Info: Copying Dell Flash64Bit EXE To $BIOSUpdateRoot" -Severity 1 -SkipGuiLog $True
# =============== Distrubute Content =================
Set-Location -Path ($SiteCode + ":")
$SCCMPackage = Get-CMPackage -Name $BIOSUpdatePackage | Where-Object { $_.Version -eq $BIOSVer }
DistributeContent -Product $Product -Package $SCCMPackage.PackageID -ImportInto $ImportInto
Write-CMLogEntry -Value "$($Product): BIOS Update Package $($SCCMPackage.PackageID) Created & Distributing" -Severity 1
Set-Location -Path $TempDirectory
}
else
{
Write-CMLogEntry -Value "$($Product): BIOS package already exists" -Severity 1
}
}
}
if ($Make -eq "Lenovo")
{
# ================= Lenovo BIOS Upgrade Download ==================
Write-CMLogEntry -Value "Info: Retrieving BIOS Download URL For $Make Client Model: $($Model)" -Severity 1
Set-Location -Path $TempDirectory
Write-CMLogEntry -Value "Info: Attempting to find download URL using LenovoBiosFinder function" -Severity 1 -SkipGuiLog $true
$BIOSDownload = LenovoBiosFinder -Model $Model -OS $WindowsVersion
if ($BIOSDownload -ne $null)
{
# Download Lenovo BIOS Details XML
if ($ProxyCheck.StatusDescription -eq "OK")
{
Start-BitsTransfer -Source $($BIOSDownload.Location) -Destination $TempDirectory -RetryInterval 60 -RetryTimeout 180 -ProxyList $ProxyServer -ProxyAuthentication NTLM -ProxyCredential $ProxyCred -ProxyUsage SystemDefault -Priority Foreground
}
else
{
Start-BitsTransfer -Source $($BIOSDownload.Location) -Destination $TempDirectory -RetryInterval 60 -RetryTimeout 180
}
$LenovoBIOSDetails = (Select-Xml -Path ($TempDirectory + "\" + ($BIOSDownload.Location | Split-Path -leaf)) -XPath "/").Node.Package
$BIOSUpdatePackage = ("BIOS Update - " + "$Make" + " " + $Model + " ($global:LenovoModelType)")
Set-Location -Path ($SiteCode + ":")
$BIOSModelPackage = Get-CMPackage | Where-Object { $_.Name -match $BIOSUpdatePackage } | Sort-Object SourceDate -Descending | select -First 1
Set-Location -Path $TempDirectory
if (($BIOSModelPackage.Version -ne $BIOSVer) -or ($LenovoBIOSDetails.Name -ne $null))
{
$BIOSFile = ($LenovoBIOSDetails.ExtractCommand).Split(" ")[0]
Write-CMLogEntry -Value "Info: Found exe file link: $BIOSFile" -Severity 1
$BIOSVer = $LenovoBIOSDetails.version
Write-CMLogEntry -Value "Info: BIOS version is $BIOSVer" -Severity 1
$BIOSUpdateRoot = ($DriverRepositoryRoot + $Model + "\BIOS\" + $BIOSVer + "\")
Write-CMLogEntry -Value "Info: BIOS update directory set to $BIOSUpdateRoot" -Severity 1
# Check for destination directory, create if required and download the BIOS upgrade file
if ((Test-Path -Path "$($BIOSUpdateRoot + '\' + $BIOSFile)") -eq $false)
{
New-Item -Path $BIOSUpdateRoot -ItemType Directory
$BIOSFileDownload = ($BIOSDownload.Location | Split-Path -Parent) + "/$BIOSFile"
# Correct slash direction issues
$BIOSFileDownload = $BIOSFileDownload.Replace("\", "/")
Write-CMLogEntry -Value "Info: Downloading BIOS update file from $BIOSFileDownload" -Severity 1
if ($UseProxyServerCheckbox.Checked -eq $true)
{
Start-BitsTransfer $BIOSFileDownload -Destination "$($BIOSUpdateRoot + $BIOSFile)" -RetryTimeout 90 -RetryInterval 180 -ProxyList $ProxyServer -ProxyList $ProxyServer -ProxyAuthentication NTLM -ProxyCredential $ProxyCred -ProxyUsage SystemDefault
}
else
{
Start-BitsTransfer $BIOSFileDownload -Destination "$($BIOSUpdateRoot + $BIOSFile)" -RetryTimeout 90 -RetryInterval 180
}
# =============== Extract BIOS Files =================
$BIOSExtractSwitches = ((($LenovoBIOSDetails.ExtractCommand).TrimStart("$BIOSFile")).Trim()).Replace("%PACKAGEPATH%", $BIOSUpdateRoot)
Write-CMLogEntry -Value "Info: BIOS Switches = $BIOSExtractSwitches" -Severity 1
Start-Process -FilePath $($BIOSUpdateRoot + $BIOSFile) -ArgumentList $BIOSExtractSwitches -Wait
if ((Get-ChildItem -Path $BIOSUpdateRoot).count -eq "1")
{
# Cater for BIOS extract issues with UNC paths
$BIOSExtractSwitches = ((($LenovoBIOSDetails.ExtractCommand).TrimStart("$BIOSFile")).Trim()).Replace("%PACKAGEPATH%", ($TempDirectory + "\$Model\$BIOS\$BIOSVer"))
Start-Process -FilePath $("$BIOSUpdateRoot" + $BIOSFile) -ArgumentList $BIOSExtractSwitches -Wait
Write-CMLogEntry -Value "Info: Copying extracted files to $BIOSUpdateRoot" -Severity 1
Get-ChildItem -Path ($TempDirectory + "\$Model\$BIOS\$BIOSVer") | Copy-Item -Destination $BIOSUpdateRoot
}
Write-CMLogEntry -Value "Info: Removing source BIOS exe file" -Severity 1 -SkipGuiLog $true
Get-ChildItem -Path "$BIOSUpdateRoot" -Filter "*.exe" | Where-Object { $_.Name -eq $BIOSFile } | Remove-Item
If ($ImportInto -notmatch "Download")
{
# =============== Create Package =================
Set-Location -Path ($SiteCode + ":")
Write-CMLogEntry -Value "$($Product): Creating BIOS Package" -Severity 1
New-CMPackage -Name "$BIOSUpdatePackage" -Path "$BIOSUpdateRoot" -Description "$Make $Model BIOS Updates" -Manufacturer "$Make" -Language English -version $LenovoBIOSDetails.Version
if ($EnableBinaryDifCheckBox.Checked -eq $true)
{
Write-CMLogEntry -Value "$($Product): Enabling Binary Delta Replication" -Severity 1
Set-CMPackage -Name "$BIOSUpdatePackage" -EnableBinaryDeltaReplication $true
}
# =============== Distrubute Content =================
Set-Location -Path ($SiteCode + ":")
$SCCMPackage = Get-CMPackage -Name $BIOSUpdatePackage | Where-Object { $_.Version -eq $BIOSVer }
DistributeContent -Product $Product -Package $SCCMPackage.PackageID -ImportInto "Standard"
Write-CMLogEntry -Value "$($Product): BIOS Update Package $($SCCMPackage.PackageID) Created & Distributing" -Severity 1
}
Set-Location -Path $TempDirectory
}
else
{
Write-CMLogEntry -Value "Info: BIOS package already exists" -Severity 2
}
}
}
else
{
Write-CMLogEntry -Value "Error: Unable to find BIOS link" -Severity 2
}
Set-Location -Path $TempDirectory
}
}
Write-CMLogEntry -Value "======== $Model BIOS PROCESSING FINISHED ========" -Severity 1
}
if (($DownloadType -ne "BIOS") -and ($ImportInto -ne "MDT"))
{
Write-CMLogEntry -Value "======== $PRODUCT $Model DRIVER PROCESSING STARTED ========" -Severity 1
# =============== ConfigMgr Driver Cab Download =================
Write-CMLogEntry -Value "$($Product): Retrieving ConfigMgr Driver Pack Site For $Make $Model" -Severity 1
Write-CMLogEntry -Value "$($Product): URL Found: $ModelURL" -Severity 1
if (($ModelURL -ne $Null) -and ($ModelURL -ne "badLink"))
{
# Cater for HP / Model Issue
$Model = $Model -replace '/', '-'
$Model = $Model.Trim()
Set-Location -Path $TempDirectory
# Check for destination directory, create if required and download the driver cab
if ((Test-Path -Path $("$DriverRepositoryRoot" + "$Model" + "\Driver Cab\" + "$DriverCab")) -eq $false)
{
Write-CMLogEntry -Value "$($Product): Creating $Model download folder" -Severity 1
if ((Test-Path -Path $("$DriverRepositoryRoot" + "$Model" + "\Driver Cab")) -eq $false)
{
Write-CMLogEntry -Value "$($Product): Creating $("$DriverRepositoryRoot" + "$Model" + "\Driver Cab") folder " -Severity 1
New-Item -ItemType Directory -Path $("$DriverRepositoryRoot" + "$Model" + "\Driver Cab")
}
Write-CMLogEntry -Value "$($Product): Downloading $DriverCab driver cab file" -Severity 1
Write-CMLogEntry -Value "$($Product): Downloading from URL: $DriverDownload" -Severity 1
Start-Job -Name "$Model-DriverDownload" -ScriptBlock $DriverDownloadJob -ArgumentList ($DriverRepositoryRoot, $Model, $DriverCab, $DriverDownload, $ProxyServer, $ProxyCred)
sleep -Seconds 5
$BitsJob = Get-BitsTransfer | Where-Object { $_.DisplayName -match "$Model-DriverDownload" }
while (($BitsJob).JobState -eq "Connecting")
{
Write-CMLogEntry -Value "$($Product): Establishing Connection to $DriverDownload" -Severity 1
sleep -seconds 30
}
while (($BitsJob).JobState -eq "Transferring")
{
$PercentComplete = [int](($BitsJob.BytesTransferred * 100)/$BitsJob.BytesTotal);
Write-CMLogEntry -Value "$($Product): Downloaded $([int]((($BitsJob).BytesTransferred)/ 1MB)) MB of $([int]((($BitsJob).BytesTotal)/ 1MB)) MB ($PercentComplete%). Next update in 30 seconds." -Severity 1
sleep -seconds 30
}
Get-BitsTransfer | Where-Object { $_.DisplayName -eq "$Model-DriverDownload" } | Complete-BitsTransfer
Write-CMLogEntry -Value "$($Product): Driver Revision: $DriverRevision" -Severity 1
}
else
{
Write-CMLogEntry -Value "$($Product): Skipping $DriverCab... Driver pack already downloaded." -Severity 1
}
# Cater for HP / Model Issue
$Model = $Model -replace '/', '-'
if (((Test-Path -Path "$($DriverRepositoryRoot + "$Model" + '\Driver Cab\' + $DriverCab)") -eq $true) -and ($DriverCab -ne $null))
{
Write-CMLogEntry -Value "$($Product): $DriverCab File Exists - Processing Driver Package" -Severity 1 -SkipGuiLog $true
# =============== Create Driver Package + Import Drivers =================
if ((Test-Path -Path "$DriverExtractDest") -eq $false)
{
New-Item -ItemType Directory -Path "$($DriverExtractDest)"
}
if ((Get-ChildItem -Path "$DriverExtractDest" -Recurse -Filter *.inf -File).Count -eq 0)
{
Write-CMLogEntry -Value "==================== $PRODUCT DRIVER EXTRACT ====================" -Severity 1
Write-CMLogEntry -Value "$($Product): Expanding Driver CAB Source File: $DriverCab" -Severity 1
Write-CMLogEntry -Value "$($Product): Driver CAB Destination Directory: $DriverExtractDest" -Severity 1
if ($Make -eq "Dell")
{
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
Expand "$DriverSourceCab" -F:* "$DriverExtractDest"
}
if ($Make -eq "HP")
{
# Driver Silent Extract Switches
$HPTemp = $TempDirectory + "\" + $Model + "\Win" + $WindowsVersion + $Architecture
$HPTemp = $HPTemp -replace '/', '-'
# HP Work Around For Long Dir
if ((($HPTemp).Split("-").Count) -gt "1")
{
$HPTemp = ($HPTemp).Split("-")[0]
}
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $HPTemp" -Severity 1
$HPSilentSwitches = "-PDF -F" + "$HPTemp" + " -S -E"
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $HPSilentSwitches" -Severity 1 -SkipGuiLog $true
Start-Process -FilePath "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)" -ArgumentList $HPSilentSwitches -Verb RunAs
$DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4)
# Wait for HP SoftPaq Process To Finish
While ((Get-Process).name -contains $DriverProcess)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process: $DriverProcess) To Complete.. Next Check In 30 Seconds" -Severity 1
sleep -Seconds 30
}
# Move HP Extracted Drivers To UNC Share
$HPExtract = Get-ChildItem -Path $HPTemp -Directory
# Loop through the HP extracted driver folders to find the extracted folders and reduce directory path
while ($HPExtract.Count -eq 1)
{
$HPExtract = Get-ChildItem -Path $HPExtract.FullName -Directory
}
# Set HP extracted folder
$HPExtract = $HPExtract.FullName | Split-Path -Parent | Select -First 1
Write-CMLogEntry -Value "$($Product): HP Driver Source Directory Set To $HPExtract" -Severity 1
if ((Test-Path -Path "$HPExtract") -eq $true)
{
Start-Job -Name "$Model-Driver-Move" -ScriptBlock $MoveHPDrivers -ArgumentList ($HPExtract, $DriverExtractDest)
while ((Get-Job -Name "$Model-Driver-Move").State -eq "Running")
{
Write-CMLogEntry -Value "$($Product): Moving $Make $Model $OperatingSystem $Architecture Driver.. Next Check In 30 Seconds" -Severity 1
sleep -seconds 30
}
}
else
{
Write-CMLogEntry -Value "ERROR: Issues occured during the $Make $Model extract process" -Severity 3
}
}
if ($Make -eq "Lenovo")
{
# Driver Silent Extract Switches
$LenovoSilentSwitches = "/VERYSILENT /DIR=" + '"' + $DriverExtractDest + '"' + ' /Extract="Yes"'
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $LenovoSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
Start-Process -FilePath "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)" -ArgumentList $LenovoSilentSwitches -Verb RunAs
$DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4)
# Wait for Lenovo Driver Process To Finish
While ((Get-Process).name -contains $DriverProcess)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process: $DriverProcess) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
if ($Make -eq "Acer")
{
# Driver Silent Extract Switches
$AcerSilentSwitches = "x " + '"' + $($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab) + '"' + " -O" + '"' + $DriverExtractDest + '"'
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $AcerSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
$DriverProcess = Start-Process 'C:\Program Files\7-Zip\7z.exe' -ArgumentList $AcerSilentSwitches -PassThru -NoNewWindow
# Wait for Acer Driver Process To Finish
While ((Get-Process).ID -eq $DriverProcess.ID)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process ID: $($DriverProcess.ID)) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
if ($Make -eq "Microsoft")
{
# Driver Silent Extract Switches
$MicrosoftSilentSwitches = "/a" + '"' + $($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab) + '"' + '/QN TARGETDIR="' + $DriverExtractDest + '"'
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
$DriverProcess = Start-Process msiexec.exe -ArgumentList $MicrosoftSilentSwitches -PassThru
# Wait for Microsoft Driver Process To Finish
While ((Get-Process).ID -eq $DriverProcess.ID)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process ID: $($DriverProcess.ID)) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
}
else
{
Write-CMLogEntry -Value "Skipping.. Drivers already extracted." -Severity 1
}
if ($ImportInto -ne "Download Only")
{
Write-CMLogEntry -Value "$($Product): Checking For Extracted Drivers" -Severity 1 -SkipGuiLog $true
if ($ImportInto -like "*Driver*")
{
if ((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).count -ne 0)
{
Write-CMLogEntry -Value "$($Product): Driver Count In Path $DriverExtractDest - $((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).count) " -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "==================== $PRODUCT DRIVER IMPORT ====================" -Severity 1
if ($OSBuild -eq $null)
{
$CMDriverPackage = ("$Make " + $Model + " - " + $OperatingSystem + " " + $Architecture)
}
else
{
$CMDriverPackage = ("$Make " + $Model + " - " + $OperatingSystem + " " + $OSBuild + " " + $Architecture)
}
Set-Location -Path ($SiteCode + ":")
if ((Get-CMDriverPackage -Name $CMDriverPackage | Where-Object { $_.Version -eq $DriverRevision }) -eq $null)
{
if ((Test-Path -Path "$DriverPackageDest") -eq $false)
{
New-Item -ItemType Directory -Path "$DriverPackageDest"
}
Set-Location -Path ($SiteCode + ":")
Write-CMLogEntry -Value "$($Product): Creating Driver Package $CMDriverPackage" -Severity 1
Write-CMLogEntry -Value "$($Product): Searching For Driver INF Files In $DriverExtractDest" -Severity 1
Set-Location -Path $TempDirectory
$DriverINFFiles = Get-ChildItem -Path "$DriverExtractDest" -Recurse -Filter "*.inf" -File | Where-Object { $_.FullName -like "*$Architecture*" }
if ($DriverINFFiles.Count -ne $null)
{
Set-Location -Path ($SiteCode + ":")
if (Get-CMCategory -CategoryType DriverCategories -name $DriverCategoryName)
{
Write-CMLogEntry -Value "$($Product): Category already exists" -Severity 1
$DriverCategory = Get-CMCategory -CategoryType DriverCategories -name $DriverCategoryName
}
else
{
Write-CMLogEntry -Value "$($Product): Creating Category $DriverCategoryName" -Severity 1
$DriverCategory = New-CMCategory -CategoryType DriverCategories -name $DriverCategoryName
}
Write-CMLogEntry -Value "$($Product): Creating Driver Package for $Make $Model (Version $DriverRevision)" -Severity 1
New-CMDriverPackage -Name $CMDriverPackage -path "$DriverPackageDest"
Write-CMLogEntry -Value "$($Product): New CMDriverPacakge Name: $CMDriverPackage | Path $DriverPackageDest" -Severity 1 -SkipGuiLog $true
Set-CMDriverPackage -Name $CMDriverPackage -Version $DriverRevision
# Check For Driver Package
$SCCMDriverPackage = Get-CMDriverPackage -Name $CMDriverPackage | Where-Object { $_.Version -eq $DriverRevision }
Write-CMLogEntry -Value "$($Product): Checking Driver Package Created Successfully" -Severity 1 -SkipGuiLog $true
if ($SCCMDriverPackage.PackageID -ne $null)
{
# Import Driver Loop
$DriverNo = 1
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 "$($CMDriverPackage)"
Write-CMLogEntry -Value "$($Product): Importing Driver INF $DriverNo Of $($DriverINFFiles.count): $($DriverINF.FullName | Split-Path -Leaf)" -Severity 1
$DriverNo++
}
Write-CMLogEntry -Value "$($Product): Driver Package $($SCCMDriverPackage.PackageID) Created Succesfully" -Severity 1
# =============== Distrubute Content =================
Write-CMLogEntry -Value "$($Product): Distributing $($SCCMDriverPackage.PackageID)" -Severity 1 -SkipGuiLog $true
DistributeContent -Product $Product -Package $SCCMDriverPackage.PackageID -ImportInto $ImportInto
}
else
{
Write-CMLogEntry -Value "Error: Errors Occurred While Creating Driver Package" -Severity 3
}
Set-Location -Path $TempDirectory
}
else
{
Write-CMLogEntry -Value "$($Product): Extract Folder Empty.. Skipping Driver Import / Package Creation" -Severity 2
}
}
else
{
Write-CMLogEntry -Value "$($Product): Driver Package Already Exists.. Skipping" -Severity 1
Set-Location -Path $TempDirectory
}
}
else
{
Write-CMLogEntry -Value "======== DRIVER EXTRACT ISSUE DETECTED ========" -Severity 3
Write-CMLogEntry -Value "$($Product): Issues occurred while reading extracted drivers" -Severity 3
Write-CMLogEntry -Value "$($Product): Driver count in path $DriverExtractDest - $((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).count) " -Severity 1 -SkipGuiLog $true
}
}
Write-CMLogEntry -Value "$($Product): Checking For Extracted Drivers" -Severity 1 -SkipGuiLog $true
if ($ImportInto -like "*Standard*")
{
Write-CMLogEntry -Value "$($Product): Driver Count In Path $DriverExtractDest - $((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).count) " -Severity 1 -SkipGuiLog $true
if ((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).Count - $null)
{
Write-CMLogEntry -Value "$($Product): Validated Drivers Exist In $DriverExtractDest - Processing Driver Packaging Steps " -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "==================== $PRODUCT DRIVER PACKAGE ====================" -Severity 1
if ($OSBuild -eq $null)
{
$CMPackage = ("Drivers - " + "$Make " + $Model + " - " + $OperatingSystem + " " + $Architecture)
}
else
{
$CMPackage = ("Drivers - " + "$Make " + $Model + " - " + $OperatingSystem + " " + $OSBuild + " " + $Architecture)
}
if ($Make -eq "Lenovo")
{
$CMPackage = $CMPackage + " ($global:LenovoModelType)"
}
Set-Location -Path ($SiteCode + ":")
if ((Get-CMPackage -Name $CMPackage | Where-Object { $_.Version -eq $DriverRevision }) -eq $null)
{
Set-Location -Path $TempDirectory
if ((Test-Path -Path "$DriverPackageDest") -eq $false)
{
New-Item -ItemType Directory -Path "$DriverPackageDest"
}
Set-Location -Path ($SiteCode + ":")
Write-CMLogEntry -Value "$($Product): Creating Package for $Make $Model (Version $DriverRevision)" -Severity 1
# Work around for HP WMI when using the ConfigMgr Web Service
if ($Make -eq "HP")
{
$Manufacturer = "Hewlett-Packard"
}
else
{
$Manufacturer = $Make
}
# Create Driver Package
New-CMPackage -Name "$CMPackage" -path "$DriverPackageDest" -Manufacturer $Manufacturer -Description "$Make $Model Windows $WindowsVersion $Architecture Drivers" -Version $DriverRevision
if ($EnableBinaryDifCheckBox.Checked -eq $true)
{
Write-CMLogEntry -Value "$($Product): Enabling Binary Delta Replication" -Severity 1
Set-CMPackage -Name "$CMPackage" -EnableBinaryDeltaReplication $true
}
$MifVersion = $OperatingSystem + " " + $Architecture
Set-CMPackage -Name "$CMPackage" -MifName $Model -MifVersion $MifVersion
# Move Extracted Drivers To Driver Package Directory
Write-CMLogEntry -Value "$($Product): Source Directory $DriverExtractDest" -Severity 1
Write-CMLogEntry -Value "$($Product): Destination Directory $DriverPackageDest" -Severity 1
Set-Location -Path $TempDirectory
# Copy Drivers To Package Location
Start-Job -Name "$Model-Driver-Package" -ScriptBlock $PackageDrivers -ArgumentList ($Make, $DriverExtractDest, $Architecture, $DriverPackageDest)
while ((Get-Job -Name "$Model-Driver-Package").State -eq "Running")
{
Write-CMLogEntry -Value "$($Product): Copying $Make $Model $OperatingSystem $Architecture Drivers.. Next Check In 30 Seconds" -Severity 1
sleep -seconds 30
}
if ((Get-Job -Name "$Model-Driver-Package").State -eq "Completed")
{
# Check For Driver Package
Set-Location -Path ($SiteCode + ":")
$SCCMPackage = Get-CMPackage -Name $CMPackage | Where-Object { $_.Version -eq $DriverRevision }
if ($SCCMPackage.PackageID -ne $null)
{
Write-CMLogEntry -Value "$($Product): Driver Package $($SCCMPackage.PackageID) Created Succesfully" -Severity 1
# =============== Distrubute Content =================
DistributeContent -Product $Product -Package $SCCMPackage.PackageID -ImportInto $ImportInto
}
else
{
Write-CMLogEntry -Value "Error: Errors Occurred While Creating Package" -Severity 3
}
}
else
{
Write-CMLogEntry -Value "Error: Errors Occurred While Copying Drivers" -Severity 3
}
Get-Job -Name "$Model-Driver-Package" | Remove-Job
Set-Location -Path $TempDirectory
}
else
{
Write-CMLogEntry -Value "$($Product): Driver Package Already Exists.. Skipping" -Severity 2
Set-Location -Path $TempDirectory
}
}
else
{
Write-CMLogEntry -Value "======== DRIVER EXTRACT ISSUE DETECTED ========" -Severity 3
Write-CMLogEntry -Value "$($Product): Issues occurred while reading extracted drivers" -Severity 3
Write-CMLogEntry -Value "$($Product): Driver Count In Path $DriverExtractDest - $((Get-ChildItem -Recurse -Path "$DriverExtractDest" -Filter *.inf -File).count) " -Severity 1 -SkipGuiLog $true
}
}
}
}
else
{
Write-CMLogEntry -Value "$($Product): $DriverCab File Download Failed" -Severity 3
}
}
else
{
Write-CMLogEntry -Value "$($Product): Operating system driver package download path not found.. Skipping $Model" -Severity 3
}
Write-CMLogEntry -Value "======== $PRODUCT $MODEL DRIVER PROCESSING FINISHED ========" -Severity 1
}
Set-Location -Path $TempDirectory
if (($ImportInto -like "*Both*") -or ($ImportInto -eq "MDT"))
{
Write-CMLogEntry -Value "======== $PRODUCT $MODEL DRIVER PROCESSING STARTED ========" -Severity 1
Set-Location -Path $TempDirectory
# Import MDT Module
Write-CMLogEntry -Value "======== $Product Prerequisites ========" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Importing MDT PowerShell Module" -Severity 1 -SkipGuiLog $true
$MDTPSLocation = "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1"
if ((Test-Path -Path $MDTPSLocation) -eq $true)
{
Import-Module "$MDTPSLocation"
$Product = "MDT"
# =================== MDT Driver Download =====================
Write-CMLogEntry -Value "======== $Product Driver Download ========" -Severity 1
Write-CMLogEntry -Value "$($Product): Starting $Product Driver Download Process" -Severity 1
# =================== DEFINE VARIABLES =====================
Write-CMLogEntry -Value "$($Product): Driver Package Base Location Set To $DriverRepositoryRoot" -Severity 1
# Operating System Version
$OperatingSystem = ("Windows " + $WindowsVersion)
# =============== MDT Driver Cab Download =================
# Cater for HP / Model Issue
$Model = $Model -replace '/', '-'
if (($ModelURL -ne $null) -and ($ModelURL -ne "badLink"))
{
# Check for destination directory, create if required and download the driver cab
if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab)) -eq $false)
{
Write-CMLogEntry -Value "$($Product): Creating $Model download folder" -Severity 1
if ((Test-Path -Path ($DriverRepositoryRoot + $Model + "\Driver Cab")) -eq $false)
{
New-Item -ItemType Directory -Path "$($DriverRepositoryRoot + $Model + '\Driver Cab')"
}
Write-CMLogEntry -Value "$($Product): Downloading $DriverCab driver cab file" -Severity 1
Write-CMLogEntry -Value "$($Product): Downloading from URL: $DriverDownload" -Severity 1
Start-Job -Name "$Model-DriverDownload" -ScriptBlock $DriverDownloadJob -ArgumentList ($DriverRepositoryRoot, $Model, $DriverCab, $DriverDownload, $ProxyServer, $ProxyCred)
sleep -Seconds 5
$BitsJob = Get-BitsTransfer | Where-Object { $_.DisplayName -eq "$Model-DriverDownload" }
while (($BitsJob).JobState -eq "Connecting")
{
Write-CMLogEntry -Value "$($Product): Establishing Connection to $DriverDownload." -Severity 1
sleep -seconds 30
}
while (($BitsJob).JobState -eq "Transferring")
{
$PercentComplete = [int](($BitsJob.BytesTransferred * 100)/$BitsJob.BytesTotal);
Write-CMLogEntry -Value "$($Product): Downloaded $([int]((($BitsJob).BytesTransferred)/ 1MB)) MB of $([int]((($BitsJob).BytesTotal)/ 1MB)) MB ($PercentComplete%). Next update in 30 seconds" -Severity 1
sleep -seconds 30
}
Get-BitsTransfer | Where-Object { $_.DisplayName -eq "$Model-DriverDownload" } | Complete-BitsTransfer
Write-CMLogEntry -Value "$($Product): Driver Revision: $DriverRevision" -Severity 1
}
else
{
Write-CMLogEntry -Value "$($Product): Skipping $DriverCab... Driver pack already downloaded" -Severity 2
}
# Check for destination directory, create if required and download the driver cab
if ((Test-Path -Path "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)") -eq $false)
{
if ((Test-Path -Path "($DriverRepositoryRoot + $Model + '\Driver Cab\')") -eq $false)
{
Write-CMLogEntry -Value "$($Product): Creating $Model Download Folder" -Severity 1
New-Item -ItemType Directory -Path "$($DriverRepositoryRoot + $Model + '\Driver Cab')"
}
else
{
# Remove previous driver cab revisions
Get-ChildItem -Path "$($DriverRepositoryRoot + $Model + '\Driver Cab\')" | Remove-Item
}
Write-CMLogEntry -Value "$($Product): Downloading $DriverCab Driver Cab File" -Severity 1
Start-Job -Name "$Model-DriverDownload" -ScriptBlock $DriverDownloadJob -ArgumentList ($DriverRepositoryRoot, $Model, $DriverCab, $DriverDownload, $ProxyServer, $ProxyCred)
sleep -Seconds 5
$BitsJob = Get-BitsTransfer | Where-Object { $_.DisplayName -eq "$Model-DriverDownload" }
while (($BitsJob).JobState -eq "Connecting")
{
Write-CMLogEntry -Value "$($Product): Establishing Connection to $DriverDownload" -Severity 1
sleep -seconds 30
}
while (($BitsJob).JobState -eq "Transferring")
{
$PercentComplete = [int](($BitsJob.BytesTransferred * 100)/$BitsJob.BytesTotal);
Write-CMLogEntry -Value "$($Product): Downloaded $([int]((($BitsJob).BytesTransferred)/ 1MB)) 1MB of $([int]((($BitsJob).BytesTotal)/ 1MB)) MB ($PercentComplete%). Next update in 30 seconds" -Severity 1
sleep -seconds 30
}
Get-BitsTransfer | Where-Object { $_.DisplayName -eq "$Model-DriverDownload" } | Complete-BitsTransfer
Write-CMLogEntry -Value "$($Product): Driver Revision: $DriverRevision" -Severity 1
}
else
{
Write-CMLogEntry -Value "$($Product): Skipping $DriverCab... Driver pack already extracted" -Severity 2
}
if (((Test-Path -Path "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)") -eq $true) -and ($DriverCab -ne $null))
{
# =============== MDT Driver EXTRACT ====================
if ((Test-Path -Path "$DriverExtractDest") -eq $false)
{
# Extract Drivers From Driver
New-Item -ItemType Directory -Path "$DriverExtractDest"
}
if ((Get-ChildItem -Path "$DriverExtractDest" -Recurse -Filter *.inf -File).Count -eq 0)
{
Write-CMLogEntry -Value "======== $PRODUCT DRIVER EXTRACT ========" -Severity 1
Write-CMLogEntry -Value "$($Product): Expanding Driver CAB Source File: $DriverCab" -Severity 1
Write-CMLogEntry -Value "$($Product): Driver CAB Destination Directory: $DriverExtractDest" -Severity 1
if ($Make -eq "Dell")
{
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
Expand "$DriverSourceCab" -F:* "$DriverExtractDest"
}
if ($Make -eq "HP")
{
# Driver Silent Extract Switches
$HPTemp = $TempDirectory + "\" + $Model + "\Win" + $WindowsVersion + $Architecture
$HPTemp = $HPTemp -replace '/', '-'
# HP Work Around For Long Dir
if ((($HPTemp).Split("-").Count) -gt "1")
{
$HPTemp = ($HPTemp).Split("-")[0]
}
Write-CMLogEntry -Value "$($Product): Extracting HP Drivers to $HPTemp" -Severity 1
$HPSilentSwitches = "-PDF -F" + $HPTemp + " -S -E"
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $HPSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
Start-Process -FilePath "$($DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab)" -ArgumentList $HPSilentSwitches -Verb RunAs
$DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4)
# Wait for HP SoftPaq Process To Finish
While ((Get-Process).name -contains $DriverProcess)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process: $DriverProcess) To Complete.. Next Check In 30 Seconds" -Severity 1
sleep -Seconds 30
}
# Move HP Extracted Drivers To UNC Share
$HPExtract = Get-ChildItem -Path $HPTemp
Start-Job -Name "$Model-Driver-Move" -ScriptBlock $MoveHPDrivers -ArgumentList ($HPExtract, $DriverExtractDest)
sleep -Seconds 2
while ((Get-Job -Name "$Model-Driver-Move").State -eq "Running")
{
Write-CMLogEntry -Value "$($Product): Moving $Make $Model $OperatingSystem $Architecture Driver.. Next Check In 30 Seconds" -Severity 1
sleep -seconds 30
}
}
if ($Make -eq "Lenovo")
{
# Driver Silent Extract Switches
$LenovoSilentSwitches = "/VERYSILENT /DIR=" + "$($DriverExtractDest)" + '/Extract="Yes"'
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $LenovoSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
Start-Process -FilePath $($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab) -ArgumentList $LenovoSilentSwitches -Verb RunAs
$DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4)
# Wait for Lenovo Driver Process To Finish
While ((Get-Process).name -contains $DriverProces)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process: $DriverProcess) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
if ($Make -eq "Acer")
{
# Driver Silent Extract Switches
$AcerSilentSwitches = "x " + '"' + $($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab) + '"' + " -O" + '"' + $DriverExtractDest + '"'
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $AcerSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
$DriverProcess = Start-Process 'C:\Program Files\7-Zip\7z.exe' -ArgumentList $AcerSilentSwitches -PassThru -NoNewWindow
# Wait for Acer Driver Process To Finish
While ((Get-Process).ID -eq $DriverProcess.ID)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process ID: $($DriverProcess.ID)) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
if ($Make -eq "Microsoft")
{
# Driver Silent Extract Switches
$MicrosoftSilentSwitches = "/a" + '"' + $($DriverRepositoryRoot + $Model + "\Driver Cab\" + $DriverCab) + '"' + '/QN TARGETDIR="' + $DriverExtractDest + '"'
Write-CMLogEntry -Value "$($Product): Using $Make Silent Switches: $MicrosoftSilentSwitches" -Severity 1 -SkipGuiLog $true
Write-CMLogEntry -Value "$($Product): Extracting $Make Drivers to $DriverExtractDest" -Severity 1
$DriverProcess = Start-Process msiexec.exe -ArgumentList $MicrosoftSilentSwitches -PassThru
# Wait for Microsoft Driver Process To Finish
While ((Get-Process).ID -eq $MicrosoftProcess.ID)
{
Write-CMLogEntry -Value "$($Product): Waiting For Extract Process (Process ID: $($DriverProcess.ID)) To Complete.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 30
}
}
}
# =============== MDT Driver Import ====================
Write-CMLogEntry -Value "======== $PRODUCT Driver Import ========" -Severity 1
Write-CMLogEntry -Value "$($Product): Starting MDT Driver Import Process" -Severity 1
# Detect First MDT PSDrive
Write-CMLogEntry -Value "$($Product): Detecting MDT PSDrive" -Severity 1
if (!$PSDriveName) { $PSDriveName = (Get-MDTPersistentDrive)[0].name }
# Detect First MDT Deployment Share
Write-CMLogEntry -Value "$($Product): Detecting MDT Deployment Share" -Severity 1
if (!$DeploymentShare) { $DeploymentShare = (Get-MDTPersistentDrive)[0].path }
$MDTDriverPath = $PSDriveName + ':\Out-of-Box Drivers'
$MDTSelectionProfilePath = $PSDriveName + ':\Selection Profiles'
# Connect to Deployment Share
Write-CMLogEntry -Value "$($Product): Connecting To MDT Share" -Severity 1
if (!(Get-PSDrive -Name $PSDriveName -ErrorAction SilentlyContinue))
{
New-PSDrive -Name $PSDriveName -PSProvider MDTProvider -Root "$DeploymentShare"
Write-CMLogEntry -Value "$($Product): $PSDriveName connected to $DeploymentShare" -Severity 1 -SkipGuiLog $true
}
$DSDriverPath = $PSDriveName + ':\Out-of-Box Drivers'
$DSSelectionProfilePath = $PSDriveName + ':\Selection Profiles'
# Connect to Deployment Share
if ((Get-PSDrive -Name $PSDriveName -ErrorAction SilentlyContinue) -eq $false)
{
New-PSDrive -Name $PSDriveName -PSProvider MDTProvider -Root "$DeploymentShare"
Write-CMLogEntry -Value "$($Product): $PSDriveName connected to $DeploymentShare" -Severity 1 -SkipGuiLog $true
}
# Cater for HP / Model Issue
$Model = $Model -replace '/', '-'
# =============== MDT Driver Import ====================
if ($OSBuild -eq $null)
{
$OperatingSystemDir = ($OperatingSystem + " " + $Architecture)
}
else
{
$OperatingSystemDir = ($OperatingSystem + " " + $OSBuild + " " + $Architecture)
}
$DriverSource = $DriverRepositoryRoot + $Model + '\Driver Cab\' + $DriverCab
if ((Test-Path $MDTDriverPath\$OperatingSystemDir) -eq $false)
{
New-Item -path $MDTDriverPath -enable "True" -Name $OperatingSystemDir -ItemType Directory
}
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"
}
if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make) -eq $false)
{
New-Item -path $MDTDriverPath\$OperatingSystemDir -enable "True" -Name $Make -ItemType Directory
}
if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model) -eq $false)
{
New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make -enable "True" -Name $Model -ItemType Directory
}
if ((Test-Path $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision) -eq $false)
{
New-Item -path $MDTDriverPath\$OperatingSystemDir\$Make\$Model -enable "True" -Name $DriverRevision -ItemType Directory
Write-CMLogEntry -Value "$($Product): Importing MDT driver pack for $Make $Model - Revision $DriverRevision" -Severity 1
Write-CMLogEntry -Value "$($Product): MDT Driver Path = $MDTDriverPath\$OperatingSystemDir\$Make\$Model\$DriverRevision" -Severity 1
Start-Job -Name "$Model-MDTImport" -ScriptBlock $MDTImportJob -ArgumentList ($PSDriveName, $MDTDriverPath, $Make, $Model, $DriverRevision, $OperatingSystemDir, $DriverExtractDest, $DeploymentShare, $Architecture)
while ((Get-Job -Name "$Model-MDTImport").State -eq "Running")
{
Write-CMLogEntry -Value "$($Product): Waiting For Import Process To Finish For $Make $Model $OperatingSystem $Architecture.. Next Check In 60 Seconds" -Severity 1
sleep -seconds 60
}
}
else
{
Write-CMLogEntry -Value "$($Product): Driver pack already exists.. Skipping" -Severity 2
}
}
else
{
Write-CMLogEntry -Value "$($Product): Error Downloading $DriverCab" -Severity 3
}
}
}
else
{
Write-CMLogEntry -Value "Error: MDT PowerShell Commandlets Not Found - Path Specified $MDTPSLocation" -Severity 3
}
Write-CMLogEntry -Value "======== $PRODUCT $MODEL PROCESSING FINISHED ========" -Severity 1
}
if ($RemoveLegacyDriverCheckbox.Checked -eq $true)
{
Set-Location -Path ($SiteCode + ":")
Write-CMLogEntry -Value "======== Superseded Driver Package Option Processing ========" -Severity 1
$ModelDriverPacks = Get-CMDriverPackage | Where-Object { $_.Name -like "*$Model*$WindowsVersion*$Architecture*" } | Sort-Object Version -Descending
if ($ModelDriverPacks.Count -gt "1")
{
$LegacyDriverPack = $ModelDriverPacks | select -Last 1
Write-CMLogEntry -Value "$($Product): Removing $($LegacyDriverPack.Name) / Package ID $($LegacyDriverPack.PackageID)" -Severity 1
Remove-CMDriverPackage -id $LegacyDriverPack.PackageID -Force
}
$ModelPackages = Get-CMPackage | Where-Object { $_.Name -like "*$Model*$WindowsVersion*$Architecture*" } | Sort-Object Version -Descending
if ($ModelPackages.Count -gt "1")
{
$LegacyPackage = $ModelPackages | select -Last 1
Write-CMLogEntry -Value "$($Product): Removing $($LegacyPackage.Name) / Package ID $($LegacyPackage.PackageID)" -Severity 1
Remove-CMPackage -id $LegacyPackage.PackageID -Force
}
Set-Location -Path $TempDirectory
}
$ProgressBar.Increment(1)
$ModelProgressOverlay.Increment(1)
$RemainingModels--
Write-CMLogEntry -Value "Info: Remaining Models To Process: $RemainingModels" -Severity 1 -SkipGuiLog $True
}
}
$ProgressBar.Increment(1)
$ModelProgressOverlay.Increment(1)
if ($CleanUnusedCheckBox.Checked -eq $true)
{
Set-Location -Path ($SiteCode + ":")
Write-CMLogEntry -Value "======== Clean Up Driver Option Processing ========" -Severity 1
# Sleep to allow for driver package registration
sleep -Seconds 10
# Get list of unused drivers
$DriverList = Get-CMDriverPackage | Get-CMDriver | Select -Property CI_ID
$UnusedDrivers = Get-CMDriver | Where-Object { $_.CI_ID -notin $DriverList.CI_ID }
Write-CMLogEntry -Value "$($Product): Found $($UnusedDrivers.Count) Unused Drivers" -Severity 1
Write-CMLogEntry -Value "$($Product): Starting Driver Package Clean Up Process" -Severity 1
foreach ($Driver in $UnusedDrivers)
{
Write-CMLogEntry -Value "$($Product): Removing $($Driver.LocalizedDisplayName) from Category $($Driver.LocalizedCategoryInstanceNames)" -Severity 1
Remove-CMDriver -ID $Driver.CI_ID -Force
}
Write-CMLogEntry -Value "$($Product): Driver Clean Up Process Completed" -Severity 1
Set-Location -Path $TempDirectory
}
if ($RemoveDriverSourceCheckbox.Checked -eq $true)
{
# Clean Up Driver Source Files
if ((($RepositoryTextBox.Text) -ne $null) -and ((Test-Path -Path ($RepositoryTextBox.text)) -eq $true))
{
Write-CMLogEntry -Value "$($Product): Removing Downloaded Driver Files From $($RepositoryTextBox.Text). Extracted Drivers Will Remain" -Severity 1 -SkipGuiLog $true
Get-ChildItem -Path $($RepositoryTextBox.Text) -Recurse -Directory | Where-Object { $_.FullName -match "Driver Cab" } | Get-ChildItem | Remove-Item -Force
}
}
Write-CMLogEntry -Value "======== Finished Processing ========" -Severity 1
}
$ConnectSCCMButton_Click = {
$SiteServer = [string]$SiteServerInput.Text
$ProgressListBox.ForeColor = "Black"
Write-CMLogEntry -Value "======== Validating ConfigMgr Server Details $(Get-Date) ========" -Severity 1
ConnectSCCM
}
$ClearSelectionButton_Click = {
#Reset Windows Form
$ProgressListBox.ForeColor = "Black"
$ProductListBox.Items.Clear()
$ProgressListBox.Items.Clear()
$SiteServerInput.Text = $null
$SiteServerInput.Enabled = $true
$SiteCodeText = $null
$PlatformComboBox.SelectedItem = $null
$PlatformComboBox.Enabled = $true
$DownloadComboBox.SelectedItem = $null
$DownloadComboBox.Enabled = $true
$OSComboBox.SelectedItem = $null
$OSComboBox.Enabled = $true
$ArchitectureComboxBox.SelectedItem = $null
$ArchitectureComboxBox.Enabled = $true
$RepositoryTextBox.Text = $null
$PackagePathTextBox.Text = $null
$PackagePathTextBox.Enabled = $true
$StartDownloadButton.Enabled = $false
$FullModelListBox.Items.Clear()
$DellCheckBox.Checked = $false
$HPCheckBox.Checked = $false
$LenovoCheckBox.Checked = $false
}
$AddToListButton_Click = {
foreach ($Item in $FullModelListBox.SelectedItems)
{
$ProductListBox.Items.Add($Item)
}
}
$FindModelsButton_Click = {
$FullModelListBox.Items.Clear()
UpdateModeList $SiteServerInput.Text $SiteCodeText.Text
}
$UseProxyServerCheckbox_CheckedChanged = {
if ($UseProxyServerCheckbox.Checked -eq $true)
{
$ProxyPswdInput.Enabled = $true
$ProxyUserInput.Enabled = $true
$ProxyServerInput.Enabled = $true
}
else
{
$ProxyPswdInput.Enabled = $false
$ProxyUserInput.Enabled = $false
$ProxyServerInput.Enabled = $false
}
}
$DownloadComboBox_SelectedIndexChanged = {
if ($DownloadComboBox.Text -eq "BIOS")
{
$PackagePathTextBox.Enabled = $false
#$OSComboBox.Enabled = $false
#$ArchitectureComboxBox.Enabled = $false
$LenovoCheckBox.Enabled = $true
$LenovoCheckBox.Checked = $false
$HPCheckBox.Enabled = $false
$HPCheckBox.Checked = $false
$AcerCheckBox.Enabled = $false
$AcerCheckBox.Checked = $false
$MicrosoftCheckBox.Enabled = $false
$MicrosoftCheckBox.Checked = $false
$DellCheckBox.Checked = $false
$CleanUnusedCheckBox.Enabled = $false
$RemoveLegacyDriverCheckbox.Enabled = $false
}
else
{
if ($PlatformComboBox.SelectedItem -eq "Download Only")
{
$OSComboBox.Enabled = $true
$ArchitectureComboxBox.Enabled = $true
$PackagePathTextBox.Enabled = $false
SCCMOptions -OptionsEnabled $false
}
else
{
$PackagePathTextBox.Enabled = $true
$OSComboBox.Enabled = $true
$ArchitectureComboxBox.Enabled = $true
$PackagePathTextBox.Enabled = $true
SCCMOptions -OptionsEnabled $true
}
$LenovoCheckBox.Enabled = $true
$HPCheckBox.Enabled = $true
$AcerCheckBox.Enabled = $true
$MicrosoftCheckBox.Enabled = $true
$DellCheckBox.Checked = $false
}
}
$PlatformComboBox_SelectedIndexChanged = {
if ($PlatformComboBox.SelectedItem -eq "MDT")
{
$DownloadComboBox.Text = "Drivers"
$DownloadComboBox.Enabled = $false
$PackagePathTextBox.Enabled = $false
$CleanUnusedCheckBox.Enabled = $false
$RemoveLegacyDriverCheckbox.Enabled = $false
SCCMOptions -OptionsEnabled $false
}
if ($PlatformComboBox.SelectedItem -match "Standard")
{
$DownloadComboBox.Enabled = $true
$PackagePathTextBox.Enabled = $true
$CleanUnusedCheckBox.Enabled = $true
$RemoveLegacyDriverCheckbox.Enabled = $true
SCCMOptions -OptionsEnabled $true
}
if ($PlatformComboBox.SelectedItem -match "Driver")
{
$DownloadComboBox.Enabled = $true
$PackagePathTextBox.Enabled = $true
$CleanUnusedCheckBox.Enabled = $true
$RemoveLegacyDriverCheckbox.Enabled = $true
SCCMOptions -OptionsEnabled $true
}
if ($PlatformComboBox.SelectedItem -eq "Download Only")
{
$DownloadComboBox.Enabled = $true
$PackagePathTextBox.Enabled = $true
$PackagePathTextBox.Enabled = $false
SCCMOptions -OptionsEnabled $false
}
$StartDownloadButton.Enabled = $true
}
$RemoveItemsButton_Click = {
While ($ProductListBox.SelectedItems.Count -gt 0)
{
$ProductListBox.Items.RemoveAt($ProductListBox.SelectedIndex)
}
}
$SCConfigMgrLink_LinkClicked = [System.Windows.Forms.LinkLabelLinkClickedEventHandler]{
Start-Process "http://www.scconfigmgr.com/2017/03/01/driver-automation-tool/"
}
$OSComboBox_SelectedIndexChanged = {
if ($OSComboBox.SelectedItem -eq "Windows 10")
{
$HPCheckBox.Enabled = $false
$HPCheckBox.Checked = $false
}
else
{
$HPCheckBox.Enabled = $true
}
if ($OSComboBox.SelectedItem -like "Windows 10 1*")
{
$DellCheckBox.Enabled = $false
$DellCheckBox.Checked = $false
$AcerCheckbox.Enabled = $false
$AcerCheckbox.Checked = $false
$LenovoCheckBox.Enabled = $false
$LenovoCheckBox.Checked = $false
$MicrosoftCheckBox.Enabled = $false
$MicrosoftCheckBox.Checked = $false
}
else
{
$DellCheckBox.Enabled = $true
$AcerCheckbox.Enabled = $true
$LenovoCheckBox.Enabled = $true
$MicrosoftCheckBox.Enabled = $true
}
}
$MainForm_FormClosing = [System.Windows.Forms.FormClosingEventHandler]{
Write-CMLogEntry -Value "======== Cleaning Up Temporary Files ========" -Severity 1
Write-CMLogEntry -Value "Info: Removing Temp Folders & Source XML/CAB Files" -Severity 1 -SkipGuiLog $true
# Clean Up Temp Driver Folders
Get-ChildItem -Path $TempDirectory -Recurse -Directory | Remove-Item -Recurse
# Clean Up Temp XML & CAB Sources
Get-ChildItem -Path $TempDirectory -Recurse -Filter *.xml -File | Remove-Item
Get-ChildItem -Path $TempDirectory -Recurse -Filter *.cab -File | Remove-Item
}
$buttonBrowseFolder_Click = {
if ($RepositoryBrowseFolderDialogue.ShowDialog() -eq 'OK')
{
$RepositoryTextBox.Text = $RepositoryBrowseFolderDialogue.SelectedPath
}
}
$RepositoryBrowseButton_Click2 = {
if ($RepositoryBrowseFolderDialogue.ShowDialog() -eq 'OK')
{
$RepositoryTextBox.Text = $RepositoryBrowseFolderDialogue.SelectedPath
}
}
$PackageBrowseButton_Click2 = {
if ($PackageBrowseFolderDialogue.ShowDialog() -eq 'OK')
{
$PackagePathTextBox.Text = $PackageBrowseFolderDialogue.SelectedPath
}
}
# --End User Generated Script--
#----------------------------------------------
#region Generated Events
#----------------------------------------------
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$MainForm.WindowState = $InitialFormWindowState
}
$Form_StoreValues_Closing=
{
#Store the control values
$script:MainForm_ProductListBox = $ProductListBox.SelectedItems
$script:MainForm_DescriptionText = $DescriptionText.Text
$script:MainForm_PleaseNnoteText = $PleaseNnoteText.Text
$script:MainForm_ArchitectureComboxBox = $ArchitectureComboxBox.Text
$script:MainForm_ArchitectureComboxBox_SelectedItem = $ArchitectureComboxBox.SelectedItem
$script:MainForm_DownloadComboBox = $DownloadComboBox.Text
$script:MainForm_DownloadComboBox_SelectedItem = $DownloadComboBox.SelectedItem
$script:MainForm_PlatformComboBox = $PlatformComboBox.Text
$script:MainForm_PlatformComboBox_SelectedItem = $PlatformComboBox.SelectedItem
$script:MainForm_OSComboBox = $OSComboBox.Text
$script:MainForm_OSComboBox_SelectedItem = $OSComboBox.SelectedItem
$script:MainForm_MicrosoftCheckBox = $MicrosoftCheckBox.Checked
$script:MainForm_LenovoCheckBox = $LenovoCheckBox.Checked
$script:MainForm_HPCheckBox = $HPCheckBox.Checked
$script:MainForm_DellCheckBox = $DellCheckBox.Checked
$script:MainForm_FullModelListBox = $FullModelListBox.SelectedItems
$script:MainForm_AcerCheckbox = $AcerCheckbox.Checked
$script:MainForm_PackagePathTextBox = $PackagePathTextBox.Text
$script:MainForm_RepositoryTextBox = $RepositoryTextBox.Text
$script:MainForm_PleaseNoteStorageText = $PleaseNoteStorageText.Text
$script:MainForm_EnableBinaryDifCheckBox = $EnableBinaryDifCheckBox.Checked
$script:MainForm_DPGListBox = $DPGListBox.SelectedItems
$script:MainForm_DPListBox = $DPListBox.SelectedItems
$script:MainForm_RemoveDriverSourceCheckbox = $RemoveDriverSourceCheckbox.Checked
$script:MainForm_RemoveLegacyDriverCheckbox = $RemoveLegacyDriverCheckbox.Checked
$script:MainForm_CleanUnusedCheckBox = $CleanUnusedCheckBox.Checked
$script:MainForm_SiteCodeText = $SiteCodeText.Text
$script:MainForm_SiteServerInput = $SiteServerInput.Text
$script:MainForm_UseProxyServerCheckbox = $UseProxyServerCheckbox.Checked
$script:MainForm_ProxyPswdInput = $ProxyPswdInput.Text
$script:MainForm_ProxyUserInput = $ProxyUserInput.Text
$script:MainForm_ProxyServerInput = $ProxyServerInput.Text
$script:MainForm_ProgressListBox = $ProgressListBox.SelectedItems
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$RemoveItemsButton.remove_Click($RemoveItemsButton_Click)
$DownloadComboBox.remove_SelectedIndexChanged($DownloadComboBox_SelectedIndexChanged)
$PlatformComboBox.remove_SelectedIndexChanged($PlatformComboBox_SelectedIndexChanged)
$OSComboBox.remove_SelectedIndexChanged($OSComboBox_SelectedIndexChanged)
$FindModelsButton.remove_Click($FindModelsButton_Click)
$AddToListButton.remove_Click($AddToListButton_Click)
$PackageBrowseButton.remove_Click($PackageBrowseButton_Click2)
$RepositoryBrowseButton.remove_Click($RepositoryBrowseButton_Click2)
$SCConfigMgrLink.remove_LinkClicked($SCConfigMgrLink_LinkClicked)
$ConnectSCCMButton.remove_Click($ConnectSCCMButton_Click)
$UseProxyServerCheckbox.remove_CheckedChanged($UseProxyServerCheckbox_CheckedChanged)
$ClearSelectionButton.remove_Click($ClearSelectionButton_Click)
$StartDownloadButton.remove_Click($StartDownloadButton_Click)
$MainForm.remove_FormClosing($MainForm_FormClosing)
$MainForm.remove_Load($MainForm_Load)
$MainForm.remove_Load($Form_StateCorrection_Load)
$MainForm.remove_Closing($Form_StoreValues_Closing)
$MainForm.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events
#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$MainForm.SuspendLayout()
$SelectionTabs.SuspendLayout()
$OSTab.SuspendLayout()
$ManufacturerTab.SuspendLayout()
$DriverStorageTab.SuspendLayout()
$DistributionTab.SuspendLayout()
$DGGroupBox.SuspendLayout()
$DPGroupBox.SuspendLayout()
$DriverCleanTab.SuspendLayout()
$SCCMDellTabControl.SuspendLayout()
$ConfigMgrTabPage1.SuspendLayout()
$ConfigMgrTabPage2.SuspendLayout()
#
# MainForm
#
$MainForm.Controls.Add($ProductListBox)
$MainForm.Controls.Add($SCConfigMgrLogo)
$MainForm.Controls.Add($DescriptionText)
$MainForm.Controls.Add($RemoveItemsButton)
$MainForm.Controls.Add($SelectionTabs)
$MainForm.Controls.Add($SCConfigMgrLink)
$MainForm.Controls.Add($SCCMDellTabControl)
$MainForm.Controls.Add($ClearSelectionButton)
$MainForm.Controls.Add($ModelProgressOverlay)
$MainForm.Controls.Add($ProgressBar)
$MainForm.Controls.Add($ProgressListBox)
$MainForm.Controls.Add($AutomationLabel)
$MainForm.Controls.Add($StartDownloadButton)
$MainForm.Controls.Add($SelectedLabel)
$MainForm.Controls.Add($LoggingLabel)
$MainForm.Controls.Add($ModelProgressLabel)
$MainForm.Controls.Add($labelThisScriptIsUsedAtYo)
$MainForm.AutoScaleDimensions = '9, 17'
$MainForm.AutoScaleMode = 'Font'
$MainForm.BackColor = 'White'
$MainForm.ClientSize = '985, 661'
$MainForm.Font = 'Microsoft Sans Serif, 8.25pt, style=Bold'
$MainForm.FormBorderStyle = 'FixedSingle'
#region Binary Data
$MainForm.Icon = [System.Convert]::FromBase64String('
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
cfh3a2nWf3NxgNPPzpXZ1dRd2tbVANfU0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTQ0IAV0dG
CkY1NKFMOjn/hnp4/52UkP+bko7/aFpX/19PTv+imJX/q6Of/62mof+wqqX/mI+L/11NS/9iUlH/
mY+M/7mzsP/Dvrz/xsLB/8bBwP+3sa/yraalftHNzHTQzMsVz8vKAAAAAAAAAAAAAAAAAAAAAAAA
AAAAbF5dADsoJwBNOzpeSDY193NlY/+Rh4P/koiE/3hsaf9VREP/j4WC/5+Wkv+hmJT/pZyY/4yB
fv9aSkn/e25s/6ykoP+0rqr/t7Gs/7q1r/68trL/vrm2/8K9vP/Cvbzjwr28cMS/vTrBvLsA////
AAAAAAAAAAAAAAAAAAAAAABVREMAVkZFGUo4N8xeTkz/hXp2/4Z7d/+DeHT/WEhG/3ZpZv+Uiob/
lIqH/5iPi/+Ifnr/X1BN/4J2dP+mnZn/qKCc662lobWPipOqf3uKqaahn5q5s63FubOv+by2s/+8
trOusaqoTcjDwQHIw8AAAAAAAAAAAAAAAAAAdmhnAEMwLgBRQD9pUD49/XRoZf96b2v/fXJu/2pc
Wf9dTUv/h3x4/4l+ev+Mgn7/h315/2RYVP99cW7/mpGO8Z2VkZuknJg12c+6BhERTS4YGFypIiRz
u0BAdWaxq6R4s62o8bWvqummn5tom5GPCKeenAAAAAAAAAAAAAAAAABgUU8AYVNRDVA/Pb5fT07/
cWZi/29kYP9wZWH/WUpI/3BjYP9+c2//f3Rw/4J3c/9tYV3/dGhl/5GHg9mTioZUnpaTBpmQjABE
RHkAVVr/AF1gyxI4O858LTDB5D5BuGarpJ2Jraah/6WdmYmBdnQLjoSBAAAAAAAwMHgANDR7AFxF
JABZSkg6U0NB8GhbV/9kWFP/ZlpV/2NXUv9bTEn/dGll/3JnY/92a2f/cmdj/25hXv+IfXrLi4F9
NHhtaACUiocAAAAAAAAAAAAAAAAAOTzWAEVHzgUjJ86cKCzc4WFesWKhmJLqp5+bmI2EgwKXjosA
AAAAACsrfwAlJnsIDA1wZUM4T5VaS0j/YVVO/1pNRf9dUUr/Wk1I/2JVUv9rYFv/aF1Y/2xhXf9t
YV3/gHVx0YuBfTCOhIAAjoeDAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhykAB8goT0fIszzKy7WqZCG
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvp6cAOygmAE4+PB5ALi2qOygn
/D0rKv9yZGL/tK2q/8O+vP/Dv77/qqOi/1xNTP83IyL/YFBP/6yjov/Py8r/0s/O/9PPzv/V0dD/
19PS/9nV1P/c2Nf/3trZ/+Dc2//i3t3/5eHg/+jk4//X0dDyvLS0Z21hXwGxqagAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGtd
XABGNDMATz49IUIwLrg8KSj/RDEw/4R4df+3sKz/ubSv/7y2sv+dlJH/Tz89/z0qKf98b27/vbe2
/8jEw//IxMP/ysbF/8zIx//Oysn/0c3M/9XR0P/X09L+2dXU79vX1t7f29rZ4d3c5eHd3Pnj397/
39va5dvW1jva1dQA4t7dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA////AEs6OQBRQUAaQzIwtD4rKv9HNTT/in98/7Grpv+wqqX/s62o/5eO
iv9MOzr/QzEv/4t/ff+9t7T/v7q3/8C7uf/Cvbz/xL++/8bCwf/KxsX/xsHA/6qjof+EeXf8YlRS
1U08OrlNPTufbmBee722tWrg3Nuo3trZ9t/b2q7e2tkN3trZAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVERDAFhIRw5GNDOgQC4t/0Y1NP+I
fHn/q6Kf/6mhnf+spaD/l46K/08/Pf9FMzL/jYJ//7exrP+2saz/ubOu/7q1sP+8t7P/v7q3/7+6
uP+gmJf/Z1lX/z8tK/84JSP/RjQy/1dHRf9fUE7/WUlH9kk4NcJJODZZ08/NXdrX1tva1tVq29fW
ANrW1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkVlUA
joOCAkk4N3pDMTD7RDMy/35xb/+jmpb/oZiU/6Sbl/+akY3/WUlH/0MyMf+Genj/sKml/66oo/+w
qqX/sqyn/7Suqf+4sq3/r6ik/3pta/9FNDP/QS8u/2dYV/+XjYv/ta6t/8K9vP/HwsH/xsHA/7ex
sP+UiojvbmFfbs3Ix03W0tG21dHQHtXR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAIyCgQA+LCsAUD8+RkY0M+tDMTD/b2Bf/5uSjv+Yj4v/mpGO/5qRjf9oWlj/
QzEw/3dqaP+poJz/p5+b/6mhnf+ro5//raah/7CppP+fl5L/Y1RS/0MxMP9fT07/mpCO/7q0sP+/
urf/v7q4/8C8uv/Cvrz/xMC//8fEwv/KxsX/ubOy8qKamV7QzMtq0MzKaM7KyQDRzcwAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFdHRQBcTEsWSjg3wUUzMv9dTUz/k4iF
/5GHg/+SiIT/lYuI/3pua/9HNTT/Y1RS/5+Vkv+flpL/oZiU/6Oalv+lnZn/qKCc/5aMiP9cTEr/
Szk4/3pta/+tpaH/ta+q/7Wvqv+2sKz/ubOu/7u1sf+9t7P/vrm2/8C7uf/Cvrz/xcC//8K+vNrC
vbtHxsLAh8zIxw7MyMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcmZlAAAA
AABQPj11SDY1/U49PP+FeHb/i4F9/4uAfP+Og3//h3x4/1VFQ/9RPz7/j4SB/5iPi/+Yj4v/mpGN
/52UkP+gl5P/kYeD/11NS/9SQUD/iHt5/6ykoP+spKD/raWh/66oo/+xq6b6tq+p8Lexq++3saz5
uLOu/7q1sf+9t7T/v7m3/8C8uv/BvbuSt7GvZ8C7uTS/urgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAVkVEAFpKSSNMOzrYSTc2/25gXv+HfHn/gndz/4V6dv+HfHj/a1xa/0o4
N/92aGb/lIqG/5CGgv+SiIX/lIqH/5eNiv+PhYH/YlRR/1ZGRP+Kfnz/pZ2Z/6Oalv+mnZn3qaGc
yq6moYiGgo9+VVNzk2hlfXGemZ1fubSuf7awq8q3saz7ubOu/7u1sf+9t7TlsauoZa+oplCdlZMA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/c3IAAAAAAFNCQHtLOTj/V0ZF/4F1cv96
b2v/fHFt/390cP96bmr/VENB/1pJSP+MgH3/iX56/4uAfP+Ngn7/j4WB/42Df/9qXlr/V0pG/4V5
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