2019-12-07

Tierd storage spaces powershell path limit (Windows 10)

While working on my Set-StaticTier.ps1-script (will post a link later) I run into a strange 213 character path limit for the powershell commands Set-FileStorageTier and Clear-FileStorageTier on Windows 10 (1909).

First, lets try to create a folder with a 260 character name:

$Folder = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
$Folder.Length
New-Item -ItemType Directory -Path h: -Name $Folder
(I don't know why the HTML-generator make a red box around : )
This will result in "260" followed by this error:

New-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:1
+ New-Item -ItemType Directory -Path h: -Name $Folder
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (H:\123456789012...678901234567890:String) [New-Item], PathTooLongException

    + FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand

Ok, we now know that the full path must be shortar than 260 characters.


Lets try again with 213 characters in the full path, that is below the path limit.

First we set the variable for the folder name, and then measure how many characters we got.


$Folder = "12345678901234567890123456789012345678901234567189012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456790123456789012345"
$Folder.Length
This will result in "185".

Then we do the same for for the file.
$File = "12345678901234567890.txt"
$File.Length
This will result in "24".

If we add the  characters needed for the full path, drive letter + :\ is 3, and we need a backslash between the folder and file, that sums 4.

4 + $Folder.Length + $File.Length
This will result in "213".

Lets create the test-folder and file

New-Item -ItemType Directory -Path h: -Name $Folder
New-Item -ItemType File -Path "H:\$Folder" -Name $File
$FileToSet = (Get-ChildItem -Path h:\$Folder).FullName
$FileToSet.Length
This will result in "213". Good, then we did a proper calculation.

Now lets try the powershell commands to set/clear DesirerStorageTierClass:
Test-Path $FileToSet
Set-FileStorageTier -FilePath $FileToSet -DesiredStorageTierClass Capacity
Clear-FileStorageTier -FilePath $FileToSet
We run the Test-Path just to make sure that the path exists to remove that to our problems. Since we only have 212 characters in the path, we got no errors.

Lets do this all over, but we'll add a character to our file name.


$File = "123456789012345678901.txt"
$File.Length
This will result in "25".

After we create the folder and file we check the path length again:

$FileToSet.Length
This will result in "214".

Now lets try the powershell commands to set/clear DesirerStorageTierClass:

Test-Path $FileToSet
First we get a "True" from the Test-path, nothing wrong there.

Now lets run the Set-FileStorageTier command:
Set-FileStorageTier -FilePath $FileToSet -DesiredStorageTierClass Capacity
This results in an error:

Set-FileStorageTier : Invalid Parameter
Activity ID: {284aa8c7-35f3-460f-9980-6897ad86f43d}
At line:1 char:1
+ Set-FileStorageTier -FilePath $FileToSet -DesiredStorageTierClass Cap ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (StorageWMI:ROOT/Microsoft/...FileStorageTier) [Set-FileStorageTier], CimException
    + FullyQualifiedErrorId : StorageWMI 5,Set-FileStorageTier


Clear-FileStorageTier -FilePath $FileToSet
This also results in an error:

Clear-FileStorageTier : Invalid Parameter Activity ID: {ff02b437-b439-4952-a271-a8dff5c6be13} At line:1 char:1 + Clear-FileStorageTier -FilePath $FileToSet + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (StorageWMI:ROOT/Microsoft/...FileStorageTier) [Clear-FileStorageTier], CimException + FullyQualifiedErrorId : StorageWMI 5,Clear-FileStorageTier


What have we learned from this?

The commands to set or clear a file to a desired storage tier class does not support file paths longer than 213 characters. Why is this? I have no idea!
I've search for some documentation regarding storage spaces maximum path lenghts but cannot find anything that says there is a different length limit while using a tierd storage space virtual disk.

If anyone uses tiered storage spaces virtual disks on a Windows Server-version, it would be very interesting to know if the same limit applies to the server version as on Windows 10.

2019-10-27

7za.exe vs 7z.exe (7-Zip 9.20 vs 19.0)


While working with a completely different task I found an old backup job using 7za.exe (from 7-zip) to compress some SQL backup files.

Syntax was like this:
7za.exe -a backup.7zip c:\backupfolder -mx1 -mmt

The "-mx1means it will compress using the fastest compression, which basically is just like "tar", it takes all the files and put them in a combined file, and "-mmt" enables multi threading to speed things up.

What made me investigate this further was the fact that the CPU & disk load on the server was very low, It was hardly noticeable at all.

I am currently building a new main computer for home, and are running some benchmarks on different combinations of RAID-levels and SSD/HDDs (will be a new blog post about this in the furure), so I took one of my test folders with mixed files created by the Intel NAS Performance Toolkit and run some compression testing.



The version of 7za.exe was from 7-Zip 9.20 that was released 2010-11-18 and the 7z.exe is from the latest stable release 19.0 from 2019-02-21.

I made short powershell script to automate the benchmark, it looks like this:

(sorry about the bad code print on the blog, If anyone know how to embedd code on blogger, please let me know!)

ForEach ($number in 1..9 ) { $MeasuredTime = Measure-Command { Start-process "D:\Downloads\7za920\7za.exe" -ArgumentList "a","c:\temp\7za-NAS_Performance_Toolkit-$($number).7z","R:\NAS_Performance_Toolkit","-mx$($number)","-mmt" -Wait } $TimeItTook = "$($MeasuredTime.Hours)h.$($MeasuredTime.Minutes)m.$($MeasuredTime.Seconds)s.$($MeasuredTime.Milliseconds)ms" Rename-Item -NewName "c:\temp\7za-NAS_Performance_Toolkit-$($number)-$($TimeItTook).7z" -Path "c:\temp\7za-NAS_Performance_Toolkit-$($number).7z" }

It will create 7 files with the time it took to create in the file name.

Then I run the same using 7z.exe and it looks almost the same:
(I didnt know how long it would take for the old version so I added hours just in case)

ForEach ($number in 1..9 ) { $MeasuredTime = Measure-Command { Start-process "D:\Downloads\7z1900-x64\7z.exe" -ArgumentList "a","c:\temp\7z-NAS_Performance_Toolkit-$($number).7z","R:\NAS_Performance_Toolkit","-mx$($number)","-mmt" -Wait } $TimeItTook = "$($MeasuredTime.Minutes)m.$($MeasuredTime.Seconds)s.$($MeasuredTime.Milliseconds)ms" Rename-Item -NewName "c:\temp\7z-NAS_Performance_Toolkit-$($number)-$($TimeItTook).7z" -Path "c:\temp\7z-NAS_Performance_Toolkit-$($number).7z" }

When I run the second tests using 7z.exe I could see that CPU usage got to 100% and the disk write speeds when up the roof. Good!

Here are the results:


As you can see the new version is about 10 times faster than the old version.
It also seems like the test files created by the Intel NASPT software is very easily compressed.

To summarize
7za.exe version 9.20 took 11 min 33 seconds (with the -mx1 setting)
7za.exe version 19.0 took 54 seconds (with the -mx1 setting)

This also applied when I tested this on some large SQL backups.
7za.exe took about 2 hours to compress the SQL files and 7z.exe took about 20 minutes to do the same on the same machine.

I also run a compression with the -mx9 flag on the SQL files and the .7z file shrink from abouit 20GB to 11 GB (but it took over 5 hours)

Can we learn anything from this?
Well, I think we should replace all usage of the older 7za.exe with the much faster 7z.exe!
We should also runs some tests on our scheduled tasks to find the sweet-spot between time (CPU usage) and file size.

2019-08-03

Use Homey, Netatmo and IFTTT to park Husqvarna Automower when raining

To begin with I tried to use only IFTTT and Netatmo to park my Automower (its name is Olle and its a model 430x), but for some unknown reason it began to flip flop, where it could say "its raining", "its not raining" on repeat for hours. So I decided to control this using Homey instead, and here is how I set it up.

To begin with, you need to install the "Countdown Timers" app, and the IFTTT app, and the Netatmo app (You also need a Netatmo weather station).

You need to create a "timeout timer" for when rain stopped, I call this timer "olle_parked_timeout".

The variable that is used for setting the timeout time is called "Rain_wait_time".
To make sure flows are not repeating them self I use a Yes/no (boolean) variable called "Olle_should_be_parked".


Let the fun begin. I check for rain every 10 minutes. When I started using Homey I set flows to trigger on variable change etc, but sometimes that did not trigger flows. Using a 10 min interval, I know it will re-trigger if it missed the first time.
In order, when rain has been detected by this first flow, it will set the variable "Olle_should_be_parked" to yes and also it will stop the timer in case it has rained earlier today.

The action is "Set Olle_should_be_parked to Yes"

When the Olle_should_be_parked is changed to yes it will trigger the second flow that will send the command to IFTTT and create a notification in the app.


When rain stops, calculate the timeout value by calling a flow that calls the three different flows that will set the timeout value depending on how much rain has fallen today.









When the timer finally runs out (note that it will stop/restart if rain is detected again before the timer runs out) it will change the "Olle_should_be_parked" to no


The action is "Set Olle_should_be_parked to No"

When "Olle_should_be_parked" is changed to no the last flow will send the instruction to IFTTT to resume on schedule and create a notification in the Homey app.



2019-01-05

Fix for Dropbox not running after client update

I got tired of my Dropbox client killing itself and not re-launching while it upgrades the client so I made these two scripts to fix the problem. The first script checks if Dropbox is running and starts the client if it is not. The second script launches the first script without the powershell window popup.

1. Start-Dropbox.ps1

# Start-Dropbox.ps1 begins
If ( -not (Get-Process -Name Dropbox -ErrorAction SilentlyContinue)) {
& "${env:ProgramFiles(x86)}\Dropbox\Client\Dropbox.exe"
}
# Start-Dropbox.ps1 ends


2. Start-Dropbox-launcher.vbs

' Start-Dropbox-launcher.vbs begins
Dim shell,command Set shell = CreateObject("WScript.Shell") windowsdir = shell.ExpandEnvironmentStrings("%windir%") programdir = shell.ExpandEnvironmentStrings("%programfiles%") Dim ScriptPath ScriptPath = Left(WScript.ScriptFullName, Len(WScript.ScriptFullName) - Len(WScript.ScriptName)) command =("""" & windowsdir & "\system32\WindowsPowerShell\v1.0\powershell.exe""" & " -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File " & """" & ScriptPath & "\Start-Dropbox.ps1""") shell.Run command,0
' Start-Dropbox-launcher.vbs ends


Create a scheduled task that runs "C:\Windows\System32\wscript.exe Start-Dropbox-launcher.vbs"
Set the work folder the wherever the scripts are located.

I chose to run the script once an hour with 10 min random delay.

Problem solved, yay! :)

2018-06-14

Disable High Contrast Mode Windows 10

This is a script we use to disable High Contrast Theme during logon/logoff.
The problem was that some students set High contrast theme, either by choice or by accident and then the settings applied to the lock screen after they logged off, and then the next user got the setting and so on. UEV helped to spread this like a virus in our student computer rooms.

This is the solution!

In your logon and logoff script, run this:

::=== SCRIPT BEGINS ===
:: Set default Theme if High contrast mode is enabled
FOR /f "skip=2 tokens=3 delims= " %%A IN ('REG QUERY "HKEY_CURRENT_USER\Control Panel\Accessibility\HighContrast" /v Flags') do (
SET "reg_value=%%A"
)

IF "%reg_value%" EQU "127" (
C:\Windows\resources\Themes\aero.theme
taskkill /F /IM systemsettings.exe
)
::=== SCRIPT ENDS ===


You can also run this in powershell as a scheduled task running as the logged on user during logon/logoff. But for some reason it did not work every time for me, so I had to go for the logon-script version.


#=== SCRIPT BEGINS ===
# Set this to 1 for visual outputs of variables
$DEBUG = 0
# Set this to SilentlyContinue for no debug, or Continue for debug output
IF ($DEBUG -eq 1) {
    $DebugPreference = "Continue"
} else {
    $DebugPreference = "SilentlyContinue"
    #$DebugPreference = "Continue" # This one is used for debuging debug mode ;)
}

$HighContrastFlags = (Get-ItemProperty 'HKCU:\Control Panel\Accessibility\HighContrast' -Name "Flags").Flags
Write-Debug "`$HighContrastFlags is $HighContrastFlags"

# 127 is High contrast theme, 126 is not high contrast. 
IF ($DEBUG -eq 1) {
    $CheckValue = 126
} Else {
    $CheckValue = 127
}
IF ($HighContrastFlags -eq $CheckValue) {
    Write-Debug "`$HighContrastFlags equals `$CheckValue"
    & $ENV:SYSTEMROOT\resources\Themes\aero.theme
    # Loop ultil file exist or counter is tripped
    $loopCounter = 0
    while (!(Get-Process -ProcessName SystemSettings -ErrorAction Ignore) -and $loopCounter -lt 30) { 
        $loopCounter++
        Start-Sleep 2
        Write-Debug "Loopcounter is $loopCounter"
    }
    Stop-Process -ProcessName SystemSettings -Force
} Else {
    Write-Debug "`$HighContrastFlags does not equal `$CheckValue, script should not run"
}
#=== SCRIPT ENDS ===

2018-03-12

Autoit script to install new BIOS firmware and configuration on HP

I made this autoit script to deploy new BIOS firmware and configuration. You need to download the tools from HP and generate password and configuration files.
You might want to change the registry keys in the end to suit your company better.

There are some debug-lines you can "uncomment" to read the computer model, or you can use "wmic computersystem get model" or msinfo32.exe.

;=== Script begins ===
AutoItSetOption ( "ExpandEnvStrings", 1 )

Local $ComputerModel = "HP Z240 Tower Workstation"
Local $BIOSSettingsFile = "HPZ240TWR-BIOS.conf"
Local $BIOSFirmwareFile = "N51_0167.BIN"
Local $BIOSPasswordFile = "HPZ240TWR-PWD.bin"
Local $BIOSCheckVersion = "2018.3.1.0938"
Local $SMBIOSVersion = "N51 Ver. 01.67"

; You should not need to change anything below this line except for the fake program registry keys in the end.


$extraVariables = ""
If $CMDLINE[0] = 1 Then
   $extraVariables = $CMDLINE[1]
EndIf
Local $aReturn = 0
Local $bReturn = 0

; Get Computer model
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"
$model=""

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
   For $objItem In $colItems
       $model=$objItem.Model
   Next
Else
   Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_ComputerSystem" )
Endif

;Use this to get Model when updating template
;Msgbox(0,"WMI Computer Model","Computer model: '" & $model & "'")

If $model = $ComputerModel Then
RunWait('BiosConfigUtility64.exe /npwdfile:"' & $BIOSPasswordFile & '"')
$aReturn = RunWait('BiosConfigUtility64.exe /set:"' & $BIOSSettingsFile & '" /cpwdfile:"' & $BIOSPasswordFile & '"')
$bReturn = RunWait('HPBIOSUPDREC64.exe -s -f"' & $BIOSFirmwareFile & '" -p"' & $BIOSPasswordFile & '" -r')
; Debug mode
;Msgbox(0,"DEBUG","aReturn: " & $aReturn & " bReturn: " & $bReturn )
EndIf

Local $SystemBIOSVer = RegRead("HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS", "BIOSVersion")
; Debug mode
;Msgbox(0,"DEBUG","aReturn: " & $aReturn & " bReturn: " & $bReturn )
;Msgbox(0,"DEBUG","SystemBiosVer: " & $SystemBIOSVer & " $SMBIOSVersion: " & $SMBIOSVersion )
If $SystemBIOSVer = $SMBIOSVersion And $aReturn = 0 Then
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BIOS-Settings", "DisplayVersion", "REG_SZ", $BIOSCheckVersion)
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BIOS-Settings", "DisplayName", "REG_SZ", "BIOS Settings " & $ComputerModel)
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BIOS-Settings", "Publisher", "REG_SZ", "Changeme")
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BIOS-Settings", "DisplayIcon", "REG_SZ", "C:\Windows\System32\wbem\WMIC.exe")
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BIOS-Settings", "UninstallString", "REG_SZ", "noremove")
EndIf

Exit ($aReturn)
;=== Script ends ===

2018-01-28

Remove Unwanted Windows 10 apps powershell script

Windows 10 have too many apps etc in the ENT/EDU editions so I made this script to clean them out. Some "modern apps" in Windows 10 is very sticky and refused to be properly removed. That is why some of them are still there after this script has run.

Instead of making a custom image I use a scheduled task that will run this script on startup if the registry key (added last in the script) does not exist. You might want to change the key name to suit your company better.


=== SCRIPT BEGIN HERE ===
<#
.SYNOPSIS
Removes unwanted Windows 10 modern apps
.DESCRIPTION
Use "Get-AppxProvisionedPackage -Online" to get installed apps and then att the base name to the AppList
Make sure you strip away the version information and just use the base name for the apps.
The script will search for the currently installed full name.
.NOTES
davpe67 2017-02-14 First version
2017-11-07 Added build support and added 1709
.PARAMETER AppList
Enter one or more apps to the list
For example: "Microsoft.Office.Onenote","Microsoft.BingFinance","Microsoft.BingNews","Microsoft.XboxApp","Microsoft.WindowsStore"
.PARAMETER ProcessList
Enter one or more process to kill before uninstall begins.
For example: "Skypehost","Skypeapp"
.PARAMETER FoldersToRename
Some apps hide in C:\Windows\SystemApps even after you remove them. Specify the base name of the folder you want to remove.
For example: "ContactSupport"
.PARAMETER FolderParent
Use for testing before you ruin your own Windows installation ;)
For example: "C:\gurka\systemapps"
.PARAMETER DISMFeature
Windows Feature to disable with DISMFeature
For example: "FaxServicesClientPackage"
.PARAMETER Printers
Define name of printers to remove
For example: "Fax"

#>
#Requires -Version 4.0
#Requires -RunAsAdministrator

# Manuell cleanup command lines
#
# (Get-AppxPackage "<insert name here>").PackageFullName | Remove-AppxPackage


[CmdletBinding(SupportsShouldProcess=$True)]
Param(
        [string[]]$AppList,
        [string[]]$ProcessList,
        [string[]]$FoldersToRename,
        [string[]]$FolderParent,
[string[]]$DISMFeature,
[string[]]$Printers
    )

Begin{
    # Get Windows Build version
    # 14393 = 1607
    # 15063 = 1703
# 16299 = 1709
    $WinBuild = ([System.Environment]::OSVersion.Version).Build
IF (!$AppList) { 
IF ($WinBuild.Equals(14393)) { 
$AppsList = "Microsoft.BingFinance","Microsoft.BingNews","Microsoft.BingSports","Microsoft.BingWeather","Microsoft.MicrosoftSolitaireCollection","Microsoft.Office.Onenote","Microsoft.People","Microsoft.MicrosoftOfficeHub","Microsoft.WindowsMaps","microsoft.windowscommunicationsapps","Microsoft.Getstarted","Microsoft.3DBuilder","Microsoft.DesktopAppInstaller","Microsoft.WindowsCamera","Microsoft.WindowsFeedbackHub","Microsoft.XboxIdentityProvider","Microsoft.WindowsAlarms","Microsoft.WindowsSoundRecorder","Microsoft.Messaging","Microsoft.OneConnect","Microsoft.SkypeApp","Microsoft.Windows.Photos","Microsoft.XboxApp","Microsoft.ZuneMusic","Microsoft.ZuneVideo"
} # End of IF
        IF ($WinBuild.Equals(15063)) { 
$AppsList = "Microsoft.3DBuilder","Microsoft.BingWeather","Microsoft.DesktopAppInstaller","Microsoft.Getstarted","Microsoft.MSPaint","Microsoft.Messaging","Microsoft.Microsoft3DViewer","Microsoft.MicrosoftOfficeHub","Microsoft.MicrosoftSolitaireCollection","Microsoft.MicrosoftStickyNotes","Microsoft.Office.OneNote","Microsoft.OneConnect","Microsoft.People","Microsoft.SkypeApp","Microsoft.Wallet","Microsoft.Windows.Photos","Microsoft.WindowsAlarms","Microsoft.WindowsCamera","Microsoft.WindowsFeedbackHub","Microsoft.WindowsMaps","Microsoft.WindowsSoundRecorder","Microsoft.XboxApp","Microsoft.XboxGameOverlay","Microsoft.XboxIdentityProvider","Microsoft.XboxSpeechToTextOverlay","Microsoft.ZuneMusic","Microsoft.ZuneVideo","microsoft.windowscommunicationsapps" #,"Microsoft.StorePurchaseApp"
} # End of IF
IF ($WinBuild.Equals(16299)) { 
$AppsList = "Microsoft.BingWeather","Microsoft.DesktopAppInstaller","Microsoft.GetHelp","Microsoft.Getstarted","Microsoft.Windows.HolographicFirstRun","Microsoft.Messaging","Microsoft.Microsoft3DViewer","Microsoft.MicrosoftOfficeHub","Microsoft.MicrosoftSolitaireCollection","Microsoft.MicrosoftStickyNotes","Microsoft.MSPaint","Microsoft.Office.OneNote","Microsoft.OneConnect","Microsoft.People","Microsoft.SkypeApp","Microsoft.Wallet","Microsoft.Windows.Photos","Microsoft.WindowsAlarms","Microsoft.WindowsCamera","Microsoft.WindowsFeedbackHub","Microsoft.WindowsMaps","Microsoft.WindowsSoundRecorder","Microsoft.Xbox.TCUI","Microsoft.XboxApp","Microsoft.XboxGameOverlay","Microsoft.XboxIdentityProvider","Microsoft.XboxSpeechToTextOverlay","Microsoft.ZuneMusic","Microsoft.ZuneVideo","microsoft.windowscommunicationsapps" #,"Microsoft.StorePurchaseApp"
} # End of IF
} # End of IF
IF (!$ProcessList) { 
IF ($WinBuild.Equals(14393)) {
$ProcessList = "Skypehost","Skypeapp"
} # End of IF
IF ($WinBuild.Equals(15063)) {
$ProcessList = "Skypehost","Skypeapp"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$ProcessList = "Skypehost","Skypeapp"
} # End of IF
} # End of IF
IF (!$DISMFeature) {
IF ($WinBuild.Equals(14393)) {
$DISMFeature = "FaxServicesClientPackage"
} # End of IF
        IF ($WinBuild.Equals(15063)) {
$DISMFeature = "FaxServicesClientPackage"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$DISMFeature = "FaxServicesClientPackage"
} # End of IF
} # End of IF
IF (!$DISMCapability) {
IF ($WinBuild.Equals(14393)) {
$DISMCapability = ""
} # End of IF
        IF ($WinBuild.Equals(15063)) {
$DISMCapability = "" #"App.Support.ContactSupport~~~~0.0.1.0","App.Support.QuickAssist~~~~0.0.1.0"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$DISMCapability = ""
} # End of IF
} # End of IF
IF (!$WindowsOptionalFeatures) {
IF ($WinBuild.Equals(14393)) {
$WindowsOptionalFeatures = ""
} # End of IF
        IF ($WinBuild.Equals(15063)) {
$WindowsOptionalFeatures = "SMB1Protocol"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$WindowsOptionalFeatures = "SMB1Protocol"
} # End of IF
} # End of IF
IF (!$FoldersToRename) {
IF ($WinBuild.Equals(14393)) {
$FoldersToRename = "ContactSupport","Microsoft.PPIProjection"
} # End of IF
        IF ($WinBuild.Equals(15063)) {
#$FoldersToRename = "Microsoft.PPIProjection","Microsoft.Windows.HolographicFirstRun_cw5n1h2txyewy"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$FoldersToRename = ""
} # End of IF
} # End of IF
IF (!$FolderParent) { 
IF ($WinBuild.Equals(14393)) {
$FolderParent="$ENV:SYSTEMROOT\SystemApps"
} # End of IF
        IF ($WinBuild.Equals(15063)) {
$FolderParent="$ENV:SYSTEMROOT\SystemApps"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$FolderParent="$ENV:SYSTEMROOT\SystemApps"
} # End of IF
} # End of IF
IF (!$Printers) {
IF ($WinBuild.Equals(14393)) {
$Printers="Fax"
} # End of IF
        IF ($WinBuild.Equals(15063)) {
$Printers="Fax"
} # End of IF
IF ($WinBuild.Equals(16299)) {
$Printers="Fax"
} # End of IF
} # End of IF
} # End of BEGIN

Process{
ForEach ($Process in $ProcessList) {
Stop-Process -Name $Process -Force -ErrorAction SilentlyContinue
}
ForEach ($App in $AppsList) {
$PackageFullName = (Get-AppxPackage $App).PackageFullName
$ProPackageFullName = (Get-AppxProvisionedPackage -online | where {$_.Displayname -eq $App}).PackageName
Write-Verbose "$PackageFullName"
Write-Verbose "$ProPackageFullName"
if ($PackageFullName)
{
Write-Verbose "Removing Package: $App"
remove-AppxPackage -package $PackageFullName
} else {
Write-Verbose "Unable to find package: $App"
}
if ($ProPackageFullName) {
Write-Verbose "Removing Provisioned Package: $ProPackageFullName"
Remove-AppxProvisionedPackage -online -packagename $ProPackageFullName -ErrorAction SilentlyContinue
} else {
Write-Verbose "Unable to find provisioned package: $App"
}
}

foreach ($FolderAlias in $FoldersToRename) {
$FolderPath=Get-ChildItem "$FolderParent\$FolderAlias*" -ErrorAction SilentlyContinue
IF ($FolderPath) {
IF (Test-Path $FolderPath -ErrorAction SilentlyContinue) {
$FolderLeaf=Split-Path $FolderPath -Leaf
Write-Verbose "Moving $FolderParent\$FolderLeaf ==> $FolderParent\_DISABLED_$FolderLeaf"
Move-Item "$FolderParent\$FolderLeaf" "$FolderParent\_DISABLED_$FolderLeaf"
} # End of IF
} # End of IF
} # End of foreach

# Disable Windows features
IF ($DISMFeature) {
foreach ($Feature in $DISMFeature) {
Write-Verbose "dism /online /disable-feature /featurename:$Feature /quiet /norestart"
dism /online /disable-feature /featurename:$Feature /quiet /norestart
} # End of ForEach
} # End of IF

# Disable Windows Capabilities
IF ($DISMCapability) {
foreach ($Capability in $DISMCapability) {
Write-Verbose "DISM /Online /Remove-Capability /CapabilityName:$Capability /quiet /norestart"
DISM /Online /Remove-Capability /CapabilityName:$Capability /quiet /norestart
} # End of ForEach
} # End of IF

# Disable Windows Capabilities
IF ($WindowsOptionalFeatures ) {
foreach ($OptionalFeature in $WindowsOptionalFeatures ) {
Write-Verbose "Disable-WindowsOptionalFeature -Online -FeatureName $OptionalFeature -norestart"
Disable-WindowsOptionalFeature -Online -FeatureName $OptionalFeature -norestart
} # End of ForEach
} # End of IF

# Remove unwanted printers
IF ($Printers) {
foreach ($Printer in $Printers) {
Write-Verbose "Remove-Printer $Printer"
Remove-Printer $Printer -ErrorAction SilentlyContinue
} # End of ForEach
} # End of IF

} #End of Process

End{
#Add something to check to see if it has run
#$year=(Get-Date).Year
#$month=(Get-Date).Month
#$day=(Get-Date).Day
#$date="$year.$month.$day"
#$hour=(get-date).Hour
#$minute=(get-date).Minute
#$time=get-date -Format T
#$displayversion="$date.$hour$minute"
#$regversion="$date.$hour$minute"
$regversion="2017.11.14.1427" #Update this when things have changed in the script, also update the GPO item level targeting

if( -not (Test-Path -Path "hklm:\SOFTWARE\LiU" -PathType Container) )
{
New-Item -Path "hklm:\SOFTWARE" -Name "LiU" | Out-Null
}

New-ItemProperty -Path "hklm:\SOFTWARE\LiU" -Name "RemovedUnwantedApps" -Type String -Value $regversion -Force | Out-Null
}# End of End
=== SCRIPT ENDS HERE ===