    #User input arguments
    param(
       [Parameter(Mandatory=$True)]
       [string]$Action,

       [string]$ConfigPath,
    	
       [switch]$BDF
    )	

    #Global file variables
    $Script:context
    $Script:service
    $Script:lockobj
    $script:options
    $Script:Adapters=$null
    $Script:bSave=$False
    $Script:bRestore=$false
    $Script:bRemove=$False
    $Script:bUpSave=$False
    $Script:bUpRestore=$False
    $Script:bANSInstalled = $True
    $Script:colImportAdapters = $null
    $Script:EnabledSystemAdapters = $null

    #Save off input paramters to be used in functions
    $Script:Action=$Action
    $Script:BDF=$BDF
    $Script:ConfigPath=$ConfigPath
    $Script:ScriptPath=$null

    #Set WMI lock
    Function BeginApply
    {
        #retrieve instance
         $Script:service = Get-WMiobject -class IAnet_netservice -namespace root\intelncs2
       
        #create [in] parameters
         $inparams = $Script:service.GetMethodParameters("BeginApply")
       
        #spawn management object
         $Script:options = new-object System.Management.InvokeMethodOptions
       
        #add context for this script
         $Script:options.Context.Add('SaveRestoreApply', $true)
         $Script:options.Context.Add('GET_EXTENSIONS', $true)
         $Script:options.Context.Add('GET_EXT_KEYS_ONLY', $false)
         $Script:options.Context.Add('IANet_PartialData', 512)
       
        #obtain lock
         $Script:lockobj = $Script:service.InvokeMethod("BeginApply", $inparams, $Script:options)

        #this is necessary to set the lock into a new object
         $Script:context = new-object System.Management.ManagementNamedValueCollection

        #adding a new single named value to the collection with the value of the lock objects client handle
         $Script:context.Add('ClientSetId', [int] $Script:lockobj.ClientSetHandle)
         $Script:context.Add('SaveRestoreApply', $true)
    }
    
    #Remove WMI lock
    Function ReleaseLock
    {
        $inparams = $Script:service.GetMethodParameters("Apply")
        $inparams.ClientSetHandle=[int]$Script:lockobj.ClientSetHandle
        $result = $Script:Service.InvokeMethod("Apply", $inparams, $null)
    }
    
    Function NewObject ($class)
    {
        $classdef = New-Object System.Management.ManagementClass $class
        #the new object options
        $classdef.Options.UseAmendedQualifiers = $true
        $classdef.Options.Context = $Script:context
        
        return $classdef
    }

    Function DeleteObject ($object)
    {
        #the delete options
        $deleteoptions = New-Object System.Management.DeleteOptions
        $deleteoptions.Context = $Script:context
        
        $object.Delete($deleteoptions)
    }

    Function SetSetting ($setting)
    {
        #the put options
        $putoptions = New-Object System.Management.PutOptions($Script:context)
        $putoptions.UseAmendedQualifiers = $true

        #perform put
        $result = $setting.Put($putoptions)
    }

    #Get specified class object from WMI
    Function GetObject($class)
    {
        
        $querystring = [string] "SELECT * FROM $class"
        $query = New-Object System.Management.ObjectQuery($querystring)

        # the enumeration options
        $enumerate_option = New-Object System.Management.EnumerationOptions
        $enumerate_option.UseAmendedQualifiers = $true
        $enumerate_option.Context = $Script:context

        # setup scope
        $DMiXPath = New-Object System.Management.ManagementPath
        $DMiXPath.NamespacePath = "root\intelncs2"
        $scope = New-Object System.Management.ManagementScope($DMiXPath)
        $scope.Connect()

        #the searcher for the object
        $searcher = New-Object System.Management.ManagementObjectSearcher($scope, $query, $enumerate_option)
        $collection = $searcher.Get()

        #If the Get() above fails, it won't be caught until the return happens. So catch it and display an appropriate message.
        try
        {
            return $collection
        }
        catch
        {
            Write-Error "No objects found for $class - exiting script"
            exit
        }
    }

    #Get associated objects given the object path and where condition
    Function GetAssociated($path, $where)
    {
        $querystring = [string] "ASSOCIATORS OF {$path} WHERE $where"

        $query = New-Object System.Management.ObjectQuery($querystring)
    
        # the enumeration options
        $enumerate_option = New-Object System.Management.EnumerationOptions
        $enumerate_option.UseAmendedQualifiers = $true
        $enumerate_option.Context = $Script:context

        # setup scope
        $DMiXPath = New-Object System.Management.ManagementPath
        $DMiXPath.NamespacePath = "root\intelncs2"
        $scope = New-Object System.Management.ManagementScope($DMiXPath)
        $scope.Connect()

        #the searcher for the object
        $searcher = New-Object System.Management.ManagementObjectSearcher($scope, $query, $enumerate_option)
        $collection = $searcher.Get()

        return $collection
    }

    #Invoke a method given it's name, class and parameters 
    Function InvokeMethod($Class,$Method,$ColParameterName,$ColParameterValue)
    {
        $Invoke_option = New-Object System.Management.InvokeMethodOptions
        $Invoke_option.Context = $Script:context

        $params = $null
        if($null -ne $ColParameterName)
        {
            $params = $Class.psbase.GetMethodParameters($Method)
            if($ColParameterName.count -gt 1)
            {
                for($i=0; $i -lt $ColParameterName.count; $i++)
                {
                    $params.psbase.SetPropertyValue($ColParameterName[$i],$ColParameterValue[$i])
                }
            }
            else
            {
                $params.psbase.SetPropertyValue($ColParameterName,$ColParameterValue)
            }
        }

        return $Class.psbase.InvokeMethod($Method,$params,$Invoke_option)
    }
    
    #Function used to write objects to config file.
    Function WriteObjectToConfigFile($NewObjects,$Properties)
    {
        if($NewObjects -ne $null)
        {
            $ExportObject = $NewObjects | select $Properties | ConvertTo-Csv -NoTypeInformation
            $ExportObject = $ExportObject[1..$ExportObject.Count]
            WriteTextToConfigFile $ExportObject
        }
    }

    #Function used to write text to config file.
    Function WriteTextToConfigFile($NewText)
    { 
        $NewText | Out-File $Script:ConfigPath -Encoding utf8 -Append 
    }

    #Function used to write objects to the IP config file.
    Function WriteObjectToIPFile($NewObjects,$Properties)
    {
        if($NewObjects -ne $null)
        {
            $ExportObject = $NewObjects | select $Properties | ConvertTo-Csv -NoTypeInformation
            $ExportObject = $ExportObject[1..$ExportObject.Count]
            WriteTextToIPFile $ExportObject
        }
    }
     
	#Function used to write text to IP config file.
    Function WriteTextToIPFile($NewText)
    { 
        $NewText | Out-File $Script:ScriptPath\Saved_StaticIP.txt -Encoding utf8 -Append 
    }

    #Function used to read objects from config file given a file section.
    Function ReadFromConfigFile($FileSection)
    {
        $FileObjects=@()
        $FileObjects = Get-Content $Script:ConfigPath

        switch($FileSection)
        {
            "Adapters" {
                            #Find the section for adapters and add 1 to not include AdaptersStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"AdaptersStart") + 1
                            #Find the end of the section and remove 1 to not include AdaptersEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"AdaptersEnd") - 1

                            $colProperty = "Name","OriginalDisplayName","PermanentAddress","PCIDeviceID","SlotID"
                            break
                       }
            "AdapterSettings" {
                            #Find the section for adapters and add 1 to not include AdapterSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"AdapterSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include AdapterSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"AdapterSettingsEnd") - 1

                            $colProperty = "Name","Caption","CurrentValue","CurrentValues","PermanentAddress","PCIDeviceID","SlotID"
                            break
                       }
            "OEMSetting" {
                            #Find the section for adapters and add 1 to not include OEMSettingStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"OEMSettingStart") + 1
                            #Find the end of the section and remove 1 to not include OEMSettingEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"OEMSettingEnd") - 1

                            $colProperty = "OEMCustomizeable"
                            break
                       }
            "PMSettings" {
                            #Find the section for adapters and add 1 to not include PMSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"PMSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include PMSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"PMSettingsEnd") - 1

                            $colProperty = "Name","Caption","CurrentValue","CurrentValues","PermanentAddress","PCIDeviceID","SlotID"
                            break
                       }
            "Teams" {
                            #Find the section for adapters and add 1 to not include TeamsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"TeamsStart") + 1
                            #Find the end of the section and remove 1 to not include TeamsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"TeamsEnd") - 1

                            $colProperty = "TeamName","TeamMembers","TeamMode","PrimaryAdapter","SecondaryAdapter"
                            break
                       }
            "TeamSettings" {
                            #Find the section for adapters and add 1 to not include TeamSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"TeamSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include TeamSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"TeamSettingsEnd") - 1

                            $colProperty = "TeamName","Caption","CurrentValue","CurrentValues"
                            break
                       }
            "Vlans" {
                            #Find the section for adapters and add 1 to not include VlansStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"VlansStart") + 1
                            #Find the end of the section and remove 1 to not include VlansEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"VlansEnd") - 1

                            $colProperty = "ParentName","VLANID","VLANNAME"
                            break
                       }
            "VlanSettings" {
                            #Find the section for adapters and add 1 to not include VlanSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"VlanSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include VlanSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"VlanSettingsEnd") - 1

                            $colProperty = "ParentName","Name","VLANID","Caption","CurrentValue"
                            break
                       }
            "NICPARTSettings" {
                            #Find the section for adapters and add 1 to not include NICPARTSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"NICPARTSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include NICPARTSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"NICPARTSettingsEnd") - 1

                            $colProperty = "Name","PartitionNumber","Identifier","MinBWPercent","MaxBWPercent"
                            break
                       }
             Default {
                        return
                     }
        }

        #If no items were found in the provided section return nothing
        if($CsvEnd -lt $CsvObjectStart)
        {
            return

        }
        #Else return only the provided section and convert the text into objects
        else
        {
            return $FileObjects[$CsvObjectStart..$CsvEnd] | ConvertFrom-Csv -Header $colProperty
        }
    }

    #Function used to read objects from config file.
    Function ReadFromIPFile($FileSection)
    {
        $FileObjects=@()
        $FileObjects = Get-Content $Script:ScriptPath\Saved_StaticIP.txt

        switch($FileSection)
        {
            "AdapterIPSettings" {
                            #Find the section for adapters and add 1 to not include AdapterIPSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"AdapterIPSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include AdapterIPSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"AdapterIPSettingsEnd") - 1

                            $colProperty = "Name","Caption","CurrentValue","CurrentValues","PermanentAddress","PCIDeviceID","SlotID"
                            break
                       }
            "TeamIPSettings" {
                            #Find the section for adapters and add 1 to not include TeamIPSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"TeamIPSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include TeamIPSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"TeamIPSettingsEnd") - 1

                            $colProperty = "TeamName","Caption","CurrentValue","CurrentValues"
                            break
                       }
            "VlanIPSettings" {
                            #Find the section for adapters and add 1 to not include VlanIPSettingsStart identifier
                            $CsvObjectStart = [array]::indexof($FileObjects,"VlanIPSettingsStart") + 1
                            #Find the end of the section and remove 1 to not include VlanIPSettingsEnd identifier
                            $CsvEnd = [array]::indexof($FileObjects,"VlanIPSettingsEnd") - 1

                            $colProperty = "ParentName","VLANID","Caption","CurrentValue","CurrentValues"
                            break
                       }
             Default {
                        return
                     }
        }
        
        #If no items were found in the provided section return nothing
        if($CsvEnd -lt $CsvObjectStart)
        {
            return

        }
        #Else return only the provided section and convert the text into objects
        else
        {
            return $FileObjects[$CsvObjectStart..$CsvEnd] | ConvertFrom-Csv -Header $colProperty
        }
    }

	#Add the parent adapter identifiers to the setting objects
    Function AddParentIDs($Setting)
    {
        #Add the PermanentAddress, PCIDeviceID and SlotID to the settings object
        $SettingAdapter = $Script:Adapters | where {$_.DeviceID -eq $Setting.ParentId}
        if($SettingAdapter)
        {
            $Setting | Add-Member -Name "PermanentAddress" -Value  $SettingAdapter.PermanentAddress -MemberType NoteProperty
            $Setting | Add-Member -Name "PCIDeviceID" -Value  $SettingAdapter.PCIDeviceID -MemberType NoteProperty
            $AdapterSlotID =  $SettingAdapter.SlotID.split(":")[0..2] #Return only the first three elements in array
            $AdapterBDF = [string]::Join(':',$AdapterSlotID)
            $Setting | Add-Member -Name "SlotID" -Value  $AdapterBDF -MemberType NoteProperty
        }
    }

	Function PrintUsage
    {
        Write-Host "Intel(R) SaveRestore.ps1 version 1.0 "
        Write-Host "Copyright (c) 2014 Intel Corporation. All rights reserved."
        Write-Host ""
        Write-Host "  Usage: SaveRestore.ps1 -Action -ConfigPath -BDF"
        Write-Host "  Example: SaveRestore.ps1 –Action Save –ConfigPath C:\SaveFiles"
        Write-Host "  -Action is required. Valid values are 'save' and 'restore.'"
        Write-Host "  -ConfigPath is optional. It specifies the path and filename of the main configuration save file. If not specified, it is the script path and default filename (saved_config.txt)."
        Write-Host "  NOTE: The Saved_StaticIP.txt filename does not change and is always saved and restored from the script path."
        Write-Host "  -BDF is optional. If specified during a restore, it will restore settings to adapters using their bus/device/function."
        Write-Host "  The default configuration file names are saved_config.txt and Saved_StaticIP.txt"
    }

    Function CheckForAdminRights
    {
        $winIdent = [Security.Principal.WindowsIdentity]::GetCurrent()
        $WinPrinc = [Security.Principal.WindowsPrincipal] $winIdent
        $AdminId  = [Security.Principal.WindowsBuiltInRole] "Administrator"
        if(-Not $WinPrinc.IsInRole($AdminId))
        {
            Write-Error "Save/Restore Script requires administrative Rights. Please log in as an Administrator and try again."
            exit
        }
    }

    Function CheckForDMiXInstall
    {
        $DMiXInstall = Get-ItemProperty -Path HKLM:\SOFTWARE\Intel\Network_Services\DMIX -Name InstalledDMIX -ErrorAction SilentlyContinue

        if((!$DMiXInstall) -or ($DMiXInstall.InstalledDMIX -ne 1))
        {
            Write-Error "The save/restore script requires Intel® PROSet to be installed. Please install Intel PROSet and try again."
            exit
        }
    }

    Function CheckForANSInstall
    {
        $ANSInstall = Get-ItemProperty -Path HKLM:\SOFTWARE\Intel\Network_Services\DMIX -Name InstalledDMIX_ANS -ErrorAction SilentlyContinue

        if((!$ANSInstall) -or ($ANSInstall.InstalledDMIX_ANS -ne 1))
        {
            $Script:bANSInstalled = $False
        }
    }

    Function CheckIfConfigFileExists
    {
        If(!(Test-Path $Script:ConfigPath))
        {
            Write-Error "config file could not be found at $Script:ConfigPath. Please provide a path to the configuration file."
            exit            
        }
    }

    #Sets a global variable for the configuration file paths to be saved/restored from.
	Function SetupSaveRestoreLocation
    {
        $Script:ScriptPath = Get-Location

        #If the user did not specify a path, use the scripts path
        if(!$Script:ConfigPath)
        {
            $Script:ConfigPath = Get-Location 
            $Script:ConfigPath = $Script:ConfigPath + "\Saved_Config.txt"
        }
        else
        {
            #Find position of the last backslash before the filename
            $FileNamePos = $Script:ConfigPath.ToString().LastIndexOf("\")

            #Seperate the filename from the path to verify path exists
            $FilePath = $Script:ConfigPath.ToString().Substring(0,$FileNamePos)

            #Check that config path exists
            if(!(Test-Path $FilePath))
            {
                Write-Error "Configuration path $FilePath does not exist, please provide a valid path"
                exit
            }
        }

        Write-Host "Performing a save/Restore of configuration file at $Script:ConfigPath"  
    }

    #Get the present and enabled adapters on the system.
    Function GetAdaptersOnSystem
    {
            #Only store adapters that have a status of 3 (which means enabled)
            $Script:EnabledSystemAdapters = GetObject "IANet_PhysicalEthernetAdapter" | where {($_.StatusInfo -eq 3)}
            #Only store adapters that support DMiX or Extended DMiX capability or if it is intel vendor capable and this is an upgrade.
            $Script:Adapters = $Script:EnabledSystemAdapters | where {($_.Capabilities -eq 73) -or ($_.Capabilities -eq 74) -or (($_.Capabilities -eq 47) -and (($bUpSave -eq $True) -or ($bUpRestore -eq $True)))}
            #Save Teamable adapters to be referenced for teams
    }

    #Remove any present configuration files
    Function RemoveOldFiles
    {
        #check if the file exists before trying to remove it
        If(Test-Path $Script:ConfigPath)
        {
            Remove-Item $Script:ConfigPath
        }
        If(Test-Path $Script:ScriptPath\Saved_StaticIP.txt)
        {
            Remove-Item $Script:ScriptPath\Saved_StaticIP.txt
        }
    }

    #Save adapters on system to the configuration file
    Function SaveAdapters
    {
        WriteTextToConfigFile "AdaptersStart"

        $colProperty = "Name","OriginalDisplayName","PermanentAddress","PCIDeviceID","SlotID"
        WriteObjectToConfigFile $Script:EnabledSystemAdapters $colProperty

        WriteTextToConfigFile "AdaptersEnd"
        WriteTextToConfigFile ""
    }

    #Save OEM customization value
    Function SaveOEMCustomizeableSetting
    {
        WriteTextToConfigFile "OEMSettingStart"
        $OEMSetting = Get-ItemProperty -Path HKLM:\SOFTWARE\Intel\Network_Services\NCS2 -Name OEMCustomizeable -ErrorAction SilentlyContinue
        
        #If a value is present save it to the config file
        if($OEMSetting -ne $null)
        {        
            WriteObjectToConfigFile $OEMSetting OEMCustomizeable
        }

        WriteTextToConfigFile "OEMSettingEnd"
        WriteTextToConfigFile ""
    }

    #Save any legacy power management settings
    Function SavePowerManagementSettings
    {
        $colProperty = "Name","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"},"PermanentAddress","PCIDeviceID","SlotID"

        WriteTextToConfigFile "PMSettingsStart"

        foreach($Adapter in $Script:Adapters)
        {
            try
            {
                #Get the Power Management settings for adapter
                $PowerSettingValues = InvokeMethod $Adapter GetPowerUsageOptions $null $null
                $PowerSettingProperties = @{Name=$Adapter.Name;CurrentValue=$PowerSettingValues.AutoPowerSaveModeEnabled;
                                            CurrentValues={};PermanentAddress=$Adapter.PermanentAddress;PCIDeviceID=$Adapter.PCIDeviceID;
                                            SlotID=$Adapter.SlotID}

                #Check each Power Management setting to see if it NULL before trying to save it to the config file
                #if there is a value, create a custom object and save it to the config file
                if($PowerSettingValues.AutoPowerSaveModeEnabled -ne $null)
                {
                    $Setting = New-Object PSObject -Property $PowerSettingProperties
                    $Setting | Add-Member -Name "Caption" -Value  "AutoPowerSaveModeEnabled" -MemberType NoteProperty
                    WriteObjectToConfigFile $Setting $colProperty 
                }
                if($PowerSettingValues.ReduceSpeedOnPowerDown -ne $null)
                {
                    $Setting = New-Object PSObject -Property $PowerSettingProperties
                    $Setting | Add-Member -Name "Caption" -Value  "ReduceSpeedOnPowerDown" -MemberType NoteProperty
                    WriteObjectToConfigFile $Setting $colProperty
                }
                if($PowerSettingValues.SmartPowerDown -ne $null)
                {
                    $Setting = New-Object PSObject -Property $PowerSettingProperties
                    $Setting | Add-Member -Name "Caption" -Value  "SmartPowerDown" -MemberType NoteProperty
                    WriteObjectToConfigFile $Setting $colProperty
                }
                if($PowerSettingValues.SavePowerNowEnabled -ne $null)
                {
                    $Setting = New-Object PSObject -Property $PowerSettingProperties
                    $Setting | Add-Member -Name "Caption" -Value  "SavePowerNowEnabled" -MemberType NoteProperty
                    WriteObjectToConfigFile $Setting $colProperty
                }
                if($PowerSettingValues.EnhancedASPMPowerSaver -ne $null)
                {
                    $Setting = New-Object PSObject -Property $PowerSettingProperties
                    $Setting | Add-Member -Name "Caption" -Value  "EnhancedASPMPowerSaver" -MemberType NoteProperty
                    WriteObjectToConfigFile $Setting $colProperty
                }
            }
            catch
            {
            }
        }

        WriteTextToConfigFile "PMSettingsEnd"
        WriteTextToConfigFile ""
    }

    #Some settings need to be saved in a certain order, this function stops them from being saved now so they can be saved later by returning
    #whether it should be saved immidiately or later (using true or false).
    Function SaveAdapterSettingLater($Setting, $bIPSetting)
    {
        $bRet = $True
        
        #Don't save the settings now if it is an IP, DCB, performance profile, SRIOV, VMQueues, or NUMVF setting
        if(($bIPSetting -eq $False) -and ($Setting.GroupId -ne 12 ) -and ($Setting.GroupId -ne 8 ) -and ($Setting.Caption -ne "PerformanceProfile") -and 
          ($Setting.Caption -ne "*SRIOV") -and ($Setting.Caption -ne "VMQueues") -and ($Setting.Caption -ne "*NumVFs"))
        {
            $bRet = $False
        }

        return $bRet
    }

    #Check if the given setting is an IP setting and save it in the IP config file and return if it is an IP setting (true or false).
    #Depending on the device different properties of the object need to be saved.
	Function SaveIPSetting($Setting,$DeviceType,$bEnabledDHCP)
    {
        $bIPSetting = $False
        $bSaveIpSetting = $False
        
        #Check if the passed in setting is one of these IP settings.
        #Some IP settings need DHCP enabled to restore.
        switch($Setting.Caption)
        {
            "IPAddress" {
                            $bIPSetting=$True
                            if($bEnabledDHCP -eq 0)
                            {
                                $bSaveIpSetting = $True
                            }
                        }
            "SubnetMask" {
                            $bIPSetting=$True
                            if($bEnabledDHCP -eq 0)
                            {
                                $bSaveIpSetting = $True
                            }
                        }
            "DefaultGateway" {
                            $bIPSetting=$True
                            if($bEnabledDHCP -eq 0)
                            {
                                $bSaveIpSetting = $True
                            }
                        }
            "NameServer" {
                            $bIPSetting=$True
                            if($bEnabledDHCP -eq 0)
                            {
                                $bSaveIpSetting = $True
                            }
                        }
            "NameServerList" {
                                 $bIPSetting=$True
                                 $bSaveIpSetting = $True
                             }
            "NetbiosOptions" {
                                 $bIPSetting=$True
                                 $bSaveIpSetting = $True
                             }
            default {}
        }

        #Save IP settings with different properties depending on the device type
        if($bSaveIpSetting -eq $True -and $DeviceType -eq "Adapter")
        {
            $colProperty = "Name","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"},"PermanentAddress","PCIDeviceID","SlotID"
            WriteObjectToIPFile $Setting $colProperty
        }
        elseif($bSaveIpSetting -eq $True -and $DeviceType -eq "Team")
        {
            $colProperty = "TeamName","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"}
            WriteObjectToIPFile $Setting $colProperty
        }
        elseif($bSaveIpSetting -eq $True -and $DeviceType -eq "Vlan")
        {
            $colProperty = "ParentName","VLANID","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"}
            WriteObjectToIPFile $Setting $colProperty
        }

        return $bIPSetting
    }

    #Save the adapter settings
    Function SaveAdapterSettings
    {
        $colProperty = "Name","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"},"PermanentAddress","PCIDeviceID","SlotID"

        #Save power management settings
        SavePowerManagementSettings

        WriteTextToConfigFile "AdapterSettingsStart"
        WriteTextToIPFile "AdapterIPSettingsStart"
        
        foreach($Adapter in $Script:Adapters)
        {
            #Get the settings associated with the adapter
            $colSettings = GetAssociated $Adapter.path.path "ResultClass = IANet_AdapterSetting"

            #Check status of EnablDHCP for IP settings later
            $bEnableDHCPCol = $colSettings | where {($_.Caption -eq "EnableDHCP")} | select $colProperty

            foreach($Setting in $colSettings)
            {
                AddParentIDs $Setting

                #Get the DHCP enable value for the specific adapter
                $bEnableDHCP = $bEnableDHCPCol | where {($_.Name -eq $Setting.Name)}

                #check if setting is an IP setting save them in the IP config file instead of the Saved_Config file
                $bIPSetting = SaveIPSetting $Setting "Adapter" $bEnableDHCP.CurrentValue

                #Check to see if the setting should be saved later
                $bRet = SaveAdapterSettingLater $Setting $bIPSetting
                if($bRet -eq $False)
                {
                    WriteObjectToConfigFile $Setting $colProperty
                }
            }

            #Check if DCB is being updated and if so, don't save the settings so the default values are restored
            $RestoreDCB = $True
            $FCoEUpdate = Get-ItemProperty -Path HKLM:\SOFTWARE\Intel\Prounstl -Name DCB_Update_FCoE  -ErrorAction SilentlyContinue
            if($FCoEUpdate -ne $null)
            {
                if($FCoEUpdate.DCB_Update_FCoE -eq 1)
                {
                    #FCoE is changing don't save settings
                    $RestoreDCB = $False
                }
            }
            $iSCSIUpdate = Get-ItemProperty -Path HKLM:\SOFTWARE\Intel\Prounstl -Name DCB_Update_iSCSI  -ErrorAction SilentlyContinue
            if($iSCSIUpdate -ne $null)
            {
                if($iSCSIUpdate.DCB_Update_iSCSI -eq 1)
                {
                    #iSCSI is changing don't save settings
                    $RestoreDCB = $False
                }
            }

            #Save *SRIOV after *VMQ
            $SRIOVSetting = $colSettings | where {($_.Caption -eq "*SRIOV")}
            WriteObjectToConfigFile $SRIOVSetting $colProperty

            #Save DCB Settings if this is not an upgrade or if it is an upgrade, and we are modifying DCB
            if(($Script:bUpSave -eq $False) -or ($RestoreDCB -eq $True))
            {
                $colDCBSettings = $colSettings | where {($_.GroupId -eq 12) -or ($_.GroupId -eq 8)}
                WriteObjectToConfigFile $colDCBSettings $colProperty
            }

            #Save the performance profile
            $ProfileSetting = $colSettings | where {($_.Caption -eq "PerformanceProfile")}
            WriteObjectToConfigFile $ProfileSetting $colProperty

            #Save VMQueues and *NUMVFs last
            $VMQQueuesSetting = $colSettings | where {($_.Caption -eq "VMQueues")}
            WriteObjectToConfigFile $VMQQueuesSetting $colProperty
            $NumVFsSetting = $colSettings | where {($_.Caption -eq "*NumVFs")}
            WriteObjectToConfigFile $NumVFsSetting $colProperty            
        }

        WriteTextToConfigFile "AdapterSettingsEnd"
        WriteTextToConfigFile ""

        WriteTextToIPFile "AdapterIPSettingsEnd"
        WriteTextToIPFile ""
    }

    #Save team information
    Function SaveTeams
    {
        #Get current teams on system
        $colProperty = "TeamName","TeamMembers","TeamMode","PrimaryAdapter","SecondaryAdapter"
        $colItems = GetObject "IANet_TeamOfAdapters" | select $colProperty

        WriteTextToConfigFile "TeamsStart"

        #if there are teams on system save the team information to the config file.
        if($colItems)
        {
            #convert Memmber arrays into a "single" value to save
            foreach($item in $colItems)
            {
                $item.TeamMembers = $item.TeamMembers -join '|'
            }

            WriteObjectToConfigFile $colItems *
        }

        WriteTextToConfigFile "TeamsEnd"
        WriteTextToConfigFile ""
    }

    #Save team settings
    Function SaveTeamSettings
    {
        #Get the current team settings
        $colProperty = "TeamName","Caption","CurrentValue",@{expression={$_.CurrentValues -join ","};label="CurrentValues"}
        $colSettings = GetObject "IANet_TeamSetting" 

        WriteTextToConfigFile "TeamSettingsStart"
        WriteTextToIPFile "TeamIPSettingsStart"

        #Check status of EnablDHCP for IP settings later
        $bEnableDHCPCol = $colSettings | where {($_.Caption -eq "EnableDHCP")} | select $colProperty

        foreach($Setting in $colSettings)
        {
            #Get the DHCP enable value for the specific Team
            $bEnableDHCP = $bEnableDHCPCol | where {($_.TeamName -eq $Setting.Name)}

            #Save the IP Settings in the IP config file
            $bIPSetting = SaveIPSetting $Setting "Team" $bEnableDHCP.CurrentValue

            if($bIPSetting -eq $False)
            {
                WriteObjectToConfigFile $Setting $colProperty
            }
        }

        WriteTextToConfigFile "TeamSettingsEnd"
        WriteTextToConfigFile ""

        WriteTextToIPFile "TeamIPSettingsEnd"
        WriteTextToIPFile ""
    }

    #Save vlan information
    Function SaveVlans
    {
        #Get the vlans on the system
        $colProperty = "ParentName","VLANID","VLANNAME"
        $colVlans = GetObject "IANet_VLAN" | select $colProperty

        WriteTextToConfigFile "VlansStart"

        #Save untagged vlan last if there are vlans on the system
        if($colVlans)
        {
            $colTaggedVlans = $colVlans | where {($_.VLANID -ne 0)}             
            WriteObjectToConfigFile $colTaggedVlans *
            $colUnTaggedVlans = $colVlans | where {($_.VLANID -eq 0)}             
            WriteObjectToConfigFile $colUnTaggedVlans *
        }

        WriteTextToConfigFile "VlansEnd"
        WriteTextToConfigFile ""
    }

    #Save vlan settings
    Function SaveVlanSettings
    {
        #Get vlan settings on system
        $colProperty = "ParentName","Name","VLANID","Caption","CurrentValue"
        $colSettings = GetObject "IANet_VLANSetting" 

        WriteTextToConfigFile "VlanSettingsStart"
        WriteTextToIPFile "VlanIPSettingsStart"

        #Check status of EnablDHCP for IP settings later
        $bEnableDHCPCol = $colSettings | where {($_.Caption -eq "EnableDHCP")} | select $colProperty

        foreach($Setting in $colSettings)
        {
            #Get the DHCP enable value for the specific adapter
            $bEnableDHCP = $bEnableDHCPCol | where {($_.Name -eq $Setting.Name)}

            #Save the IP Settings in the IP config file
            $bIPSetting = SaveIPSetting $Setting "Vlan" $bEnableDHCP.CurrentValue

            if($bIPSetting -eq $False)
            {
                WriteObjectToConfigFile $Setting $colProperty
            }
        }

        WriteTextToConfigFile "VlanSettingsEnd"
        WriteTextToConfigFile ""

        WriteTextToIPFile "VlanIPSettingsEnd"
        WriteTextToIPFile ""
    }

    #Save NICPART settings
    Function SaveNICPARTSettings
    {
        $colProperty = "Name","PartitionNumber","Identifier","MinBWPercent","MaxBWPercent"
        
        WriteTextToConfigFile "NICPARTSettingsStart"
        
        #start lock
        BeginApply
        
        try
        {
            #Get the partition information for all partitions on system and save them
            $PartitionArray = InvokeMethod $Script:service GetPartitionsForPort "szDeviceID" $null
                WriteObjectToConfigFile $PartitionArray.Partitions $colProperty
        }
        catch
        {
        }

        #release lock
        ReleaseLock

        WriteTextToConfigFile "NICPARTSettingsEnd"
        WriteTextToConfigFile ""
    }
    
    #Remove teams and vlans on system
    Function RemoveTeamsAndVlans
    {
        #Store teams and vlans on system in one array
        $colDevices = @()
        $colDevices += GetObject "IANet_TeamOfAdapters"
        $colDevices += GetObject "IANet_Vlan"

        BeginApply

        #Remove all teams and vlans in array
        foreach($Device in $colDevices)
        {
            try
            {
                DeleteObject $Device
            }
            catch
            {
            }
        }

        ReleaseLock
    }

    #Check that adapters in configuration file are present and enabled on the system.
    Function CheckAdaptersExist
    {
        $Script:colImportAdapters  = ReadFromConfigFile "Adapters"
        if($Script:colImportAdapters -ne $null)
        {
            foreach($Adapter in $Script:colImportAdapters)
            {
                #Find the matching file adapter using the appropriate property to compare name,address or ID
                if($Script:BDF -eq $False)
                {
                    $ImportedAdapter = $Script:EnabledSystemAdapters | where {($_.Name -eq $Adapter.Name)}
                    if(($null -eq $ImportedAdapter) -and ($bUpRestore -eq $True))
                    {
                        $ImportedAdapter = $Script:EnabledSystemAdapters | where {($_.PermanentAddress -eq $Adapter.PermanentAddress)}
                    }
                    elseif($null -eq $ImportedAdapter)
                    {
                        $ImportedAdapter = $Script:EnabledSystemAdapters | where {($_.PCIDeviceID -eq $Adapter.PCIDeviceID)}
                    }
                }
                else
                {
                    $ImportedAdapter = $Script:EnabledSystemAdapters | where {($_.SlotID -eq $Adapter.SlotID)}
                }

                if($null -eq $ImportedAdapter)
                {
                    Write-warning "Invalid device found. Please verify configuration file matches your system configuration."
                }
            }
        }
    }

    #Restore custome OEM value
    Function RestoreOEMCustomizeableSetting
    {         
        $ImportOEMSetting = ReadFromConfigFile "OEMSetting"
        if($ImportOEMSetting -ne $null)
        {
            Write-Host "Setting OEM Customizeable value"
            Set-ItemProperty -Path HKLM:\SOFTWARE\Intel\Network_Services\NCS2 -Name OEMCustomizeable -Value $ImportOEMSetting.OEMCustomizeable -Type DWord
        }
    }

    #Restore adapter settings
    Function RestoreAdapterSettings($colImportedSettings)
    {
        #Get adapter settings on system
        $colSetting = GetObject "IANet_AdapterSetting"
        #Add parent identifiers to settings on system
        foreach($Setting in $colSetting)
        {
            AddParentIDs $Setting   
        }

        #start lock
        BeginApply

        #Loop through the passed in settings from the config file
        foreach($ImportedSetting in $colImportedSettings)
        {
            try
            {
                #Find the matching system setting using the appropriate property to compare name,address or ID
                if($Script:BDF -eq $False)
                {
                    $Setting = $colSetting | where {($_.Name -eq $ImportedSetting.Name) -and ($_.Caption -eq $ImportedSetting.Caption)}
                    if(($null -eq $Setting) -and ($bUpRestore -eq $True))
                    {
                        $Setting = $colSetting | where {($_.PermanentAddress -eq $ImportedSetting.PermanentAddress) -and ($_.Caption -eq $ImportedSetting.Caption)}
                    }
                    elseif($null -eq $Setting)
                    {
                        $Setting = $colSetting | where {($_.PCIDeviceID -eq $ImportedSetting.PCIDeviceID) -and ($_.Caption -eq $ImportedSetting.Caption)}
                    }
                }
                else
                {
                    $Setting = $colSetting | where {($_.SlotID -eq $ImportedSetting.SlotID) -and ($_.Caption -eq $ImportedSetting.Caption)}
                }

                #If the setting in the file can't be found on the system, continue to the next setting
                if($Setting -eq $null)
                {
                    continue;
                }

                #See if 'CurrentValues' is a property over the system setting, if so set that value from the config file setting
                if(($Setting.Properties | select -ExpandProperty Name) -contains "CurrentValues")
                {
                    #If no value was present from the file setting, then set it to empty
                    if($ImportedSetting.CurrentValues -eq $null)
                    {
                        $Setting.CurrentValues = {}
                    }
                    else
                    {
                        $Setting.CurrentValues = $ImportedSetting.CurrentValues.Split(",")
                    }
                }
                else
                {
                    $Setting.CurrentValue = $ImportedSetting.CurrentValue
                }

                #set setting
                SetSetting $Setting      
            }
            catch
            {
                Write-Host "Unable to set $($Setting.Caption) on $($Setting.Name)"
            }
        } 

        #release lock
        ReleaseLock
    }

    #Set the primary and secondary adapters on the team
    Function RestorePrimaryAndSecondary($Team)
    {
        Write-Host Restoring Primary and secondary adapters on $Team.TeamName     

        #Find the adapter objects from the configuration file that match the team primary and secondary adapter names
        $PrimaryImportAdapter = $Script:colImportAdapters | where {$_.OriginalDisplayName -eq $Team.PrimaryAdapter}
        $SecondaryImportAdapter = $Script:colImportAdapters | where {$_.OriginalDisplayName -eq $Team.SecondaryAdapter}
 
        #Find the matching system adapter using the appropriate property to compare name,address or ID
        if($Script:BDF -eq $False)
        {
            $PrimaryAdapter = $Script:EnabledSystemAdapters | where {$_.Name -eq $PrimaryImportAdapter.OriginalDisplayName}
            if(($null -eq $PrimaryAdapter) -and ($bUpRestore -eq $True))
            {
                $PrimaryAdapter = $Script:EnabledSystemAdapters | where {($_.PermanentAddress -eq $PrimaryImportAdapter.PermanentAddress)}
            }
            elseif($null -eq $PrimaryAdapter)
            {
                $PrimaryAdapter = $Script:EnabledSystemAdapters | where {($_.PCIDeviceID -eq $PrimaryImportAdapter.PCIDeviceID)}
            }
        }
        else
        {
            $PrimaryAdapter = $Script:EnabledSystemAdapters | where {($_.SlotID -eq $PrimaryImportAdapter.SlotID)}
        }
        if($Script:BDF -eq $False)
        {
            $SecondaryAdapter = $Script:EnabledSystemAdapters | where {$_.Name -eq $SecondaryImportAdapter.OriginalDisplayName}
            if(($null -eq $PrimaryAdapter) -and ($bUpRestore -eq $True))
            {
                $SecondaryAdapter = $Script:EnabledSystemAdapters | where {($_.PermanentAddress -eq $SecondaryImportAdapter.PermanentAddress)}
            }
            elseif($null -eq $PrimaryAdapter)
            {
                $SecondaryAdapter = $Script:EnabledSystemAdapters | where {($_.PCIDeviceID -eq $SecondaryImportAdapter.PCIDeviceID)}
            }
        }
        else
        {
            $SecondaryAdapter = $Script:EnabledSystemAdapters | where {($_.SlotID -eq $SecondaryImportAdapter.SlotID)}
        }

        #Set the primary and secondary adapters on the team
        $Team = GetObject "IANet_TeamOfAdapters" | where {$_.TeamName -eq $Team.TeamName}
        $param = $Team.psbase.GetMethodParameters("ValidateAndSetAdapterPriority")
        $param.PrimaryAdapter = $PrimaryAdapter
        $param.SecondaryAdapter = $SecondaryAdapter
        $param.SetValuesOnNoError = 2
        $value = $Team.psbase.InvokeMethod("ValidateAndSetAdapterPriority", $param, $invokeoptions)
    }

    #Restore teams from configuration file
    Function RestoreTeams
    {
        #Get the team objects from the configuration file
        $colImportTeams = ReadFromConfigFile "Teams"

        if($colImportTeams -ne $null)
        {
            BeginApply

            foreach($Team in $colImportTeams)
            {
                Write-Host Restoring $Team.TeamName

                try
                {
                    #Create a new team object
                    $classdef = NewObject root\intelncs2:IANet_TeamOfAdapters
                
                    #fill in the CreateTeam's method parameters with the new object
                    $param = $classdef.psbase.GetMethodParameters("CreateTeam2Ex")

                    $TeamedAdapters = $Team.TeamMembers.split("|")
                    $param.Adapters = @()    

                    $bCreateTeam = $True
                    #Set the teammembers for creation
                    foreach($AdapterName in $TeamedAdapters)
                    {
                        $ImportedAdapter = $Script:colImportAdapters | where {$_.OriginalDisplayName -eq $AdapterName}
                        $Adapter = $null

                        if($null -ne $ImportedAdapter)
                        {
                            #Find the matching system adapter using the appropriate property to compare name,address or ID
                            if($Script:BDF -eq $False)
                            {
                                $Adapter = $Script:EnabledSystemAdapters | where {($_.Name -eq $ImportedAdapter.OriginalDisplayName)}
                                if(($null -eq $Adapter) -and ($bUpRestore -eq $True))
                                {
                                    $Adapter = $Script:EnabledSystemAdapters | where {($_.PermanentAddress -eq $ImportedAdapter.PermanentAddress)}
                                }
                                elseif($null -eq $Adapter)
                                {
                                    $Adapter = $Script:EnabledSystemAdapters | where {($_.PCIDeviceID -eq $ImportedAdapter.PCIDeviceID)}
                                }
                            }
                            else
                            {
                                $Adapter = $Script:EnabledSystemAdapters | where {($_.SlotID -eq $ImportedAdapter.SlotID)}
                            }
                        }

                        
                        #If a teammember can't be found output an error and breakout of team creation
                        if($null -eq $Adapter)
                        {
                            Write-warning "Invalid device found. Please verify configuration file matches your system configuration."
                            $bCreateTeam = $False
                            break
                        }
                        $param.Adapters += $Adapter
                    }

                    #If an error was found, don't try and create the team
                    if($bCreateTeam -eq $False)
                    {
                        Continue
                    }

                    $param.TeamMode = $Team.TeamMode
                    $param.TeamName = $Team.TeamName

                    #the invoke options
                    $invokeoptions = New-Object System.Management.InvokeMethodOptions
                    $invokeoptions.Context = $Script:context
 
                    #call the CreateTeam method to create the new team
                    $value = $classdef.psbase.InvokeMethod("CreateTeam2Ex", $param, $invokeoptions)

                    #Set primary and secondary adapters
                    RestorePrimaryAndSecondary $Team
                }
                catch
                {   
                } 
            }

            ReleaseLock
        }
    }

    #Restore team settings
	Function RestoreTeamSettings($colImportSettings)
    {
        #Get the current team settings
        $colSetting = GetObject "IANet_TeamSetting"

        #start lock
        BeginApply

        foreach($Setting in $colSetting)
        {
            try
            {
                #If the current setting using 'CurrentValues' then set that value.
                if(($Setting.Properties | select -ExpandProperty Name) -contains "CurrentValues")
                {
                    $ValueObject = $colImportSettings | where {($_.TeamName -eq $Setting.Name) -and ($_.Caption -eq $Setting.Caption)} | select CurrentValues
                    if($ValueObject.CurrentValues -eq $null)
                    {
                        $Setting.CurrentValues = {}
                    }
                    else
                    {
                        $Setting.CurrentValues = $ValueObject.CurrentValues.Split(",")
                    }
                }
                else
                {
                    $ValueObject = $colImportSettings | where {($_.TeamName -eq $Setting.Name) -and ($_.Caption -eq $Setting.Caption)} | select CurrentValue
                    $Setting.CurrentValue = $ValueObject.CurrentValue
                }

                #If a matching system setting was found set it to the restore value
                if($ValueObject -ne $null)
                {
                    #set setting
                    SetSetting $Setting   
                }   
            }
            catch
            {
                Write-Host "Unable to set $($Setting.Caption) on $($Setting.Name)"
            }
        }
             
        #release lock
        ReleaseLock
    }

    #Restore vlans
    Function RestoreVlans
    {
        #Get vlan objects from config file
        $colImportVlans = ReadFromConfigFile "Vlans"

        if($colImportVlans -ne $null)
        {

            foreach($Vlan in $colImportVlans)
            {
                BeginApply

                try
                {
                    #Check needs to be created on an adapter first
                    $ImportedAdapter = $Script:colImportAdapters | where {$_.Name -eq $Vlan.ParentName}
                    $Adapter = $null

                    if($null -ne $ImportedAdapter)
                    {
                        #Find the matching system adapter using the appropriate property to compare name,address or ID
                        if($Script:BDF -eq $False)
                        {
                            $Adapter = $Script:Adapters | where {($_.Name -eq $ImportedAdapter.Name)}
                            if(($null -eq $Adapter) -and ($bUpRestore -eq $True))
                            {
                                $Adapter = $Script:Adapters | where {($_.PermanentAddress -eq $ImportedAdapter.PermanentAddress)}
                            }
                            elseif($null -eq $Adapter)
                            {
                                $Adapter = $Script:Adapters | where {($_.PCIDeviceID -eq $ImportedAdapter.PCIDeviceID)}
                            }
                        }
                        else
                        {
                            $Adapter = $Script:Adapters | where {($_.SlotID -eq $ImportedAdapter.SlotID)}
                        }
                    }

                    if($Adapter -ne $null)
                    {
                        #Get the vlan creation class associated with adapter parent object
                        $VlanCreator = GetAssociated $Adapter.path.path "ResultClass = IANet_802dot1QVLANService" | where {1}
                    }
                    #Check if vlan needs to be created on a team
                    else
                    {
                        #Get the logical ethernet adapter object for the team parent
                        $Team = GetObject "IANet_LogicalEthernetAdapter" | where {( NScompare $_.Name $Vlan.ParentName )}

                        if($Team -ne $null)
                        {
                            #Get the vlan creation class associated with team parent object
                            $VlanCreator = GetAssociated $Team.path.path "ResultClass = IANet_802dot1QVLANService" | where {1}
                        }
                    }

                    #If the vlan creation class was found continue on to create the vlan
                    if($VlanCreator -ne $null)
                    {
                        Write-Host Restoring $Vlan.VlanName

                        #fill in the CreateVlan's method parameters
                        $param = $VlanCreator.psbase.GetMethodParameters("CreateVlan")

                        $param.Name = $Vlan.VLANNAME
                        $param.VLANNumber = $Vlan.VLANID

                        #the invoke options
                        $invokeoptions = New-Object System.Management.InvokeMethodOptions
                        $invokeoptions.Context = $Script:context
 
                        #call the CreateVlan method to create the new vlan
                        $value = $VlanCreator.psbase.InvokeMethod("CreateVlan", $param, $invokeoptions)
                    }
                }
                catch
                {   
                } 
                ReleaseLock
            }
        }
    }
    
    #Restore vlan settings
    Function RestoreVlanSettings($colImportSettings)
    {
        #Get the current Vlan settings
        $colSetting = GetObject "IANet_VLANSetting"

        #start lock
        BeginApply

        foreach($Setting in $colSetting)
        {
            try
            {
                #If the current setting using 'CurrentValues' then set that value.
                if(($Setting.Properties | select -ExpandProperty Name) -contains "CurrentValues")
                {
                    $ValueObject = $colImportSettings | where {( NSCompare $_.ParentName $Setting.ParentName ) -and ( $_.Caption -eq $Setting.Caption) -and ($_.VLANID -eq $Setting.VLANID)} | select CurrentValues
                    if($ValueObject.CurrentValues -eq $null)
                    {
                        $Setting.CurrentValues = {}
                    }
                    else
                    {
                        $Setting.CurrentValues = $ValueObject.CurrentValues.Split(",")
                    }
                }
                else
                {
                    $ValueObject = $colImportSettings | where {( NSCompare $_.ParentName $Setting.ParentName) -and ($_.Caption -eq $Setting.Caption) -and ($_.VLANID -eq $Setting.VLANID)} | select CurrentValue
                    $Setting.CurrentValue = $ValueObject.CurrentValue
                }

                #If a matching system setting was found set it to the restore value                                    
                if($ValueObject -ne $null)
                {
                    #set setting
                    SetSetting $Setting      
                }
            }
            catch
            {
                Write-Host "Unable to set $($Setting.Caption) on $($Setting.Name)"
            }
        } 
        
        #release lock
        ReleaseLock
    }

    #Restore the IP settings from the IP config file
	Function RestoreIPSettings
    {
        #Restore Adapter IP settings from the IP config file
        $colImportSettings = ReadFromIPFile "AdapterIPSettings"
        if($colImportSettings -ne $null)
        {
            Write-Host "Restoring adapter IP settings"
            RestoreAdapterSettings $colImportSettings
        }

        if($Script:bANSInstalled)
        {
            #Restore Team IP settings from the IP config file 
            $colImportSettings = ReadFromIPFile "TeamIPSettings"
            if($colImportSettings -ne $null)
            {
                Write-Host "Restoring team IP settings"
                RestoreTeamSettings $colImportSettings $colSetting
            }

            #Restore Vlan IP settings from the IP config file
            $colImportSettings = ReadFromIPFile "VlanIPSettings"
            if($colImportSettings -ne $null)
            {
                Write-Host "Restoring vlan IP settings"
                RestoreVlanSettings $colImportSettings
            }
        }
    }

    #Restore devices and settings from configuration files
    Function RestoreAdvancedSettingsAndDevices
    {
        #Restore Adapter avanced settings from config file
        $colImportSettings = ReadFromConfigFile "AdapterSettings"
        if($colImportSettings -ne $null)
        {
            Write-Host "Restoring adapter settings"
            RestoreAdapterSettings $colImportSettings
        }

        if(!$Script:bANSInstalled)
        {
            Write-warning "Intel(R) ANS is not present on the system. Any Team and VLAN information contained in the configuration file will not be restored."
        }
        else
        {
            #Restore Teams
            RestoreTeams

            #Restore Team advanced settings from config file 
            $colImportSettings = ReadFromConfigFile "TeamSettings"
            if($colImportSettings -ne $null)
            {
                Write-Host "Restoring team settings"
                RestoreTeamSettings $colImportSettings
            }

            #Restore Vlans
            RestoreVlans

            #Restore Vlan avanced settings from config file
            $colImportSettings = ReadFromConfigFile "VlanSettings"
            if($colImportSettings -ne $null)
            {
                Write-Host "Restoring vlan settings"
                RestoreVlanSettings $colImportSettings
            }
        }

        if(Test-Path $Script:ScriptPath\Saved_StaticIP.txt)
        {
    	    #Restore IP Settings from IP config file
            RestoreIPSettings
        }
    }

    #Restore NICPART settings
    Function RestoreNICPARTSettings
    {
        #Restore NICPART settings from config file
        $colImportPartitions = ReadFromConfigFile "NICPARTSettings"
        Write-Host "Restoring adapter partition settings"

        BeginApply

        try
        {
            if($colImportPartitions -ne $null)
            {
                #Get the partition information for all partitions on system and save them
                $PartitionObject = InvokeMethod $Script:service GetPartitionsForPort "szDeviceID" $null
                $PartitionArray = $PartitionObject.Partitions


                foreach($Partition in $PartitionArray)
                {
                    $ImportPartition = $colImportPartitions | where {($_.PartitionNumber -eq $Partition.PartitionNumber) -and ($_.Identifier -eq $Partition.Identifier)}

                    if($ImportPartition -ne $null)
                    {
                        if($Script:BDF -eq $True)
                        {
                            $Partition.Name = "IGNORE"
                            $Partition.DeviceGuid = "IGNORE"   
                        }
                        else
                        {
                            $Partition.Identifier = "IGNORE"
                            $Partition.DeviceGuid = "IGNORE"   
                        }

                        $Partition.MinBWPercent = $ImportPartition.MinBWPercent
                        $Partition.MaxBWPercent = $ImportPartition.MaxBWPercent
                    }
                }

                $Output = InvokeMethod $Script:service ValidateAndSetBAndwidthsForPort "Partitions","SetValuesOnNoError" $PartitionArray,"1"
            }
        }
        catch
        {
        }

        ReleaseLock
    }
	
	
	<# 	
	.SYNOPSIS 
		Make sure users know about BDF parameter when using NICPART enabled adapters 
	.DESCRIPTION 
		By default, the save restore script uses the adapter's friendly name to match the name of the adapter 
		in the configuration file to adapter in the system.  Because of the way Windows enumerates devices and 
		assigns friendly names, the name of the adapter saved in the configuration file may not be the exact 
		same adapter/port/partition on another system. The /bdf command line option should be used when 
		restoring settings of NICPART enabled devices on multiple systems.
    .NOTES
        This must be invoked after GetAdaptersOnSystem - as it relies on the contents of $Script:Adapters.
        The global variable is used to save time when restoring settings on user systems (to avoid polling
        the system again just to get the same data).
	#> 
    function CheckNICPART_BDFWarning
    {
		$NICPART = $Script:Adapters | where {($_.Capabilities -eq 76)}
		if ($NICPART -and $Script:BDF -eq $false)
        {
            Write-Host "A device configured for NIC Partitioning was detected.  It is recommended to use the -BDF option when restoring."
        }
	
	}

	<# 	
	.SYNOPSIS 
		"No Space Compare" Compares two strings without whitespace
	.DESCRIPTION 
		Intel(R) Network Connections Software recently introduced a change to ANS team prefixes. The old format
        was "TEAM : ". The new format is "TEAM: ". To preserve user configurations during an upgrade it is 
        necessary to compare some devices without space differences.
	#> 
    function NSCompare ($s1, $s2)
    {
        $s1temp = $s1 -replace '\s', ''
        $s2temp = $s2 -replace '\s', ''
        return ($s1temp -eq $s2temp)
	}


#THIS STARTS THE BEGINNING ON THE SAVE/RESTORE FILE 
    #Check for admin rights
    CheckForAdminRights

    #Check that DMiX is installed
    CheckForDMiXInstall

    #Check if ANS is installed
    CheckForANSInstall

    #Setup the save/restore path
    SetupSaveRestoreLocation

    #Determine which action was specified by the user
    switch($Script:Action)
    {
        "Save" {$Script:bSave=$True
                Write-Host "Performing a save"
                break}
        "UpSave" {$Script:bUpSave=$True
                Write-Host "Performing an upgrade save"
                break}
        "Restore" {$Script:bRestore=$True
                Write-Host "Performing a restore"
                break}
        "UpRestore" {$Script:bUpRestore=$True
                Write-Host "Performing an upgrade restore"
                break}
        "Remove" {$Script:bRemove=$True
                Write-Host "Performing a team and vlan device remove"
                break}
        "?" {PrintUsage}
        "help"{PrintUsage}
        default {PrintUsage}
    }

    #If a save is the primary action
    if($Script:bSave -eq $true -or $Script:bUpSave -eq $True)
    {    
        GetAdaptersOnSystem

        RemoveOldFiles

        SaveAdapters

        SaveOEMCustomizeableSetting

        SaveAdapterSettings

        if($Script:bANSInstalled)
        {
            SaveTeams

            SaveTeamSettings

            SaveVlans

            SaveVlanSettings
        }

        SaveNICPARTSettings
    }
    #If a restore is the primary action
    elseif($Script:bRestore -eq $true -or $Script:bUpRestore -eq $True)
    {
        CheckIfConfigFileExists

        if($Script:bANSInstalled)
        {
            RemoveTeamsAndVlans
        }

        GetAdaptersOnSystem

		CheckNICPART_BDFWarning

        CheckAdaptersExist

        RestoreOEMCustomizeableSetting

        RestoreAdvancedSettingsAndDevices

        RestoreNICPARTSettings
    }
    #If remove is the primary action
    elseif($Script:bRemove -eq $true)
    {
        RemoveTeamsAndVlans
    }
