Functions.ps1


function Clear-JRecycleBin {

    Clear-RecycleBin -Force -ea 0

}

function Clear-Notifications {
    [CmdletBinding()]
    param (
    )

    Start-Job -ScriptBlock {
        powershell -noprofile -Command {
            [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null

            # get the list of all registry keys
            $notifications = Get-ChildItem HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings | Select-Object Name

            # iterate through the keys, extract the name that will be used in the clear function, and clear the notifications
            for ($index = 0; $index -lt $notifications.Count; $index++) {
                $name = $notifications[$index]
                $split = $name -split "\\"
                $last = $split[$split.Count - 1]
                $last = $last.Substring(0, $last.Length - 1)
        ([Windows.UI.Notifications.ToastNotificationManager]::History).clear($last)
            }
        }
    } | Out-Null
}


function Convert-CmdletToSplat {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $CommandToProcess,
        [Parameter()] [switch] $CopyToClipBoard
    )


    function Find-LongestStringLength {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory)] $Array
        )

        # $Array

        $StrLen = @()
        foreach ($a in $Array) {
            $StrLen += $a.Length
        }



        $Return = $StrLen | Sort-Object | Select-Object -Last 1

        return $Return

    }


    # Ignore the following Parameters
    $CmdletBindings = @("Verbose", "Debug", "ErrorAction", "WarningAction", "InformationAction", "ErrorVariable", "WarningVariable", "InformationVariable", "OutVariable", "OutBuffer", "PipelineVariable")



    $CmdLet = $CommandToProcess.Trim().Split(" ")[0]

    $Verbouwen = @{}
    $i = 1

    $Verbouwen.$i = $CommandToProcess
    $i++; $Verbouwen.$i = ($Verbouwen.($i - 1)).replace($CmdLet, "")
    $i++; $Verbouwen.$i = ($Verbouwen.($i - 1)).replace("``", "")
    # $i++; $Verbouwen.$i = ($Verbouwen.($i - 1)).replace("`n", "")
    # $i++; $Verbouwen.$i = ($Verbouwen.($i - 1)).replace(" ", "")

    # $Verbouwen | Format-List


    $ParamArray = $Verbouwen.$i -Split " -"

    if ($ParamArray.Count -gt 1) {
        $Params = @()
        $ParamArray | ForEach-Object {

            $p = $_.Trim().split(" ")

            if ($p) {
                $obj = [PSCustomObject]@{
                    Parameter = $p[0]
                    Value     = $p[1..50]
                }
                $Params += $obj
            }

        }
        # $Params

        $Output = "`n"

        if ($Params) {
            $Output += "`$Params = @{`n"

            $MaxKeyLength = Find-LongestStringLength ($Params).Parameter
            $MaxKeyLength

            $Params | ForEach-Object {
                if ($_.Value) {
                    $Value = $_.Value
                } else {
                    $Value = "`$true"
                }
                if ($Value -like "*`$*") {
                    $quotes = ""
                } elseif ($Value -like "*`"*") {
                    $quotes = ""
                } else {
                    $quotes = "`""
                }

                $Output += " $($_.Parameter)"
                $FormatFillSpaces = $MaxKeyLength - ($_.Parameter).Length
                0..$FormatFillSpaces | ForEach-Object {
                    $output += " "
                }
                $Output += "= $($quotes)$($Value)$($quotes)`n"

            }

            $Output += "}`n`n"
        }
        $Output += "$($CmdLet) @Params`n`n"

        Write-Host $Output -ForegroundColor Yellow
        if ($CopyToClipBoard) {
            $Output | clip
        }
    }

    # Write-Host "##################################################" -ForegroundColor Green



    $Command = Get-Command $Cmdlet -ea 0

    if ($Command) {
        # $Command
        $Output = "`n"
        $Output += "`$Params = @{`n"

        foreach ($c in $Command) {

            $MaxKeyLength = Find-LongestStringLength ($c.Parameters).Keys
            # $MaxKeyLength

            ($c.Parameters).getenumerator() | ForEach-Object {
                if ($CmdletBindings -notcontains $_.Key) {

                    $Output += " $($_.Key)"
                    $FormatFillSpaces = $MaxKeyLength - ($_.Key).Length
                    0..$FormatFillSpaces | ForEach-Object {
                        $output += " "
                    }
                    $Output += "= "
                    if ($_.Value.SwitchParameter) {
                        $Output += "`$true"
                    } elseif ($_.Value.Attributes.ValidValues) {
                        $Output += "`"$(($_.Value.Attributes.ValidValues) -join ",")`""
                    } else {
                        $Output += "`"`""
                    }
                    $Output += "`n"

                }
            }
        }
        $Output += "}`n`n"
        $Output += "$($CmdLet) @Params`n`n"

        Write-Host $Output -ForegroundColor Yellow
    }

}



$scriptblock = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
    $o = Get-Command $wordToComplete*
    $o.Name | ForEach-Object {
        if ($_ -match " ") {
            "'$_'"
        } else {
            $_
        }
    }
}
Register-ArgumentCompleter -CommandName Convert-CmdletToSplat -ParameterName CommandToProcess -ScriptBlock $scriptblock


function Copy-WithRobocopy {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $Source,
        [Parameter(Mandatory)] [string] $Destination,
        [Parameter()] [switch] $Force
    )



    $Source = (Get-Item $Source).FullName
    if ($Source[($Source.Length - 1)] -eq "\") {
        $Source = $Source.Substring(0, ($Source.Length - 1))
    }


    if ($Destination[($Destination.Length - 1)] -eq "\") {
        $Destination = $Destination.Substring(0, ($Destination.Length - 1))
    }




    $Source
    $Destination


    if (Test-Path $Source) {
        if ((Test-Path $Destination) -and !($Force)) {
            Write-Warning "$($Destination) already exists"
        } else {
            robocopy "$Source" "$Destination" /MIR /W:1 /R:1 /MT:128
        }
    } else {
        Write-Warning "$($Source) does not exist"
    }


}




function Expand-MyArchive {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)] [string] $Path,
        [Parameter(Mandatory = $false, Position = 1)] [string] $DestinationPath
    )

    #region Checks

    # Check if the path is a valid file and exists
    if (-not (Test-Path $Path)) {
        Write-Error "The specified path '$Path' does not exist."
        return
    }

    # Check if the path is a file
    if (-not (Test-Path $Path -PathType Leaf)) {
        Write-Error "The specified path '$Path' is not a file."
        return
    }

    # Check if the destination path is provided, if not, use the same directory as the archive with archive name
    if (-not $DestinationPath) {
        $archiveFile = Get-Item $Path
        $DestinationPath = $archiveFile.DirectoryName + "\" + $archiveFile.BaseName
        Write-Verbose $DestinationPath
    }

    # Check if the destination path exists, if not, create it
    if (-not (Test-Path $DestinationPath)) {
        New-Item -Path $DestinationPath -ItemType Directory -Force | Out-Null
    }
    #endregion

    Write-Verbose $Path
    Write-Verbose $DestinationPath


    if (Test-Path "C:\Program Files\7-Zip\7z.exe") {

        Write-Host "Using 7z.exe to extract the archive." -ForegroundColor Green

        Start-Process -FilePath "7z.exe" -ArgumentList "x", "-y", "-o`"$DestinationPath`"", "`"$Path`"" -NoNewWindow -Wait -ErrorAction Stop


    } else {

        Write-Host "7z.exe not found, using Expand-Archive." -ForegroundColor Yellow

        Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force -ErrorAction Stop

    }

}


function Find-EmptyFolders {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $Path = "."

    )

    # Get-ChildItem $Path

    $Result = @()

    $items = Get-ChildItem $Path -Directory -Recurse -ea 0

    foreach ($item in $items) {
        # if ($item.PSIsContainer) {
        $subitems = Get-ChildItem -Recurse -Path $item.FullName
        if (!($subitems)) {
            $Result += $item.FullName
            # Remove-Item $item.FullName -Recurse
        }
        Remove-Variable subitems -Force -ea 0
        # }
    }

    return $Result

}

function Find-File {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $SearchString,
        [Parameter()] [switch] $ExactMatch,
        [Parameter()] [switch] $AndDirectories,
        [Parameter()] [string] $Path = "."
    )

    $Param = @{}
    if (!($AndDirectories)) {
        $Param.File = $true
    }
    if(!($ExactMatch)) {
        $SearchString = "*$SearchString*"
    }
    $Results = Get-ChildItem $Path $SearchString -Recurse @Param

    $Results = $Results.FullName


    return $Results

}

function Get-DeadLinks {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $Folder = ".",
        [Parameter()] [switch] $Remove
    )

    $shell = New-Object -ComObject WScript.Shell

    $Links = Get-ChildItem -Path $Folder -Recurse -Force -Filter "*.lnk" -ea 0
    # $Links

    foreach ($l in $Links) {

        $LinkProperties = $shell.CreateShortcut($l.FullName)
        if (!(Test-Path $LinkProperties.TargetPath)) {
            Write-Output "Link broken: `"$($LinkProperties.FullName)`" => `"$($LinkProperties.TargetPath)`""
            if ($Remove) {
                Remove-Item $LinkProperties.FullName -Force
                Write-Output "Removed link $($LinkProperties.FullName)"
            }
        }
    }

}

function Get-ExternalIpAddress {
    [CmdletBinding()]
    param (

    )

    $ip = Invoke-RestMethod http://ipinfo.io/json | Select-Object -ExpandProperty ip

    return $ip

}

function Get-FolderSize {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $Path = ".",
        [Parameter()] [int] $Depth = 0,
        [Parameter()] [switch] $IncludeFiles
    )


    function Get-FolderSizePerItem {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory)] [string] $Path
        )

        $Path = Resolve-Path $Path

        function Format-ItemSize {
            [CmdletBinding()]
            param (
                [Parameter(Mandatory)] [float] $size
            )

            if ($size -gt 1024 * 1024 * 1024) {
                $size = $size / 1024 / 1024 / 1024
                $UnitOfMeasurement = "GB"
            } elseif ($size -gt 1024 * 1024) {
                $size = $size / 1024 / 1024
                $UnitOfMeasurement = "MB"
            } elseif ($size -gt 1024) {
                $size = $size / 1024
                $UnitOfMeasurement = "kB"
            } else {
                $UnitOfMeasurement = "B"
            }
            $size = [math]::Round($size, 2)
            $returnSize = "$($size.ToString()) $UnitOfMeasurement"

            return $returnSize

        }



        $Results = @()

        $TotalSize = 0
        $SizeBytes = 0
        $Files = Get-ChildItem $Path -Recurse -File -Force -ErrorAction SilentlyContinue

        $Files | ForEach-Object {
            # $_.Length
            $TotalSize += $_.Length
            $SizeBytes += $_.Length
        }


        $Results += [PSCustomObject]@{
            Path       = $Path
            Type       = "Folder"
            TotalSize  = Format-ItemSize $TotalSize
            TotalItems = ($Files).Count
            SizeBytes  = $SizeBytes
        }

        if ($IncludeFiles) {
            $Files = Get-ChildItem $Path -File -Force -ErrorAction SilentlyContinue
            $Files | ForEach-Object {
                $Results += [PSCustomObject]@{
                    Path       = $_.FullName
                    Type       = "File"
                    TotalSize  = Format-ItemSize $_.Length
                    TotalItems = 1
                    SizeBytes  = $_.Length
                }
            }
        }

        return $Results


    }

    if ($Depth -ge 1) {
        $Result = @()
        Get-ChildItem -Path $Path -Depth ($Depth - 1) -Directory -ErrorAction SilentlyContinue | ForEach-Object {
            $Result += Get-FolderSizePerItem $_.FullName
        }
    } else {
        $Result = Get-FolderSizePerItem $Path
    }


    return $Result


}

function Get-InstalledModuleVersion {
    [CmdletBinding()]
    param (
    )

    $result = @()

    $excludeList = "Az.|Microsoft.Graph.Beta."

    Get-InstalledModule | Where-Object Name -NotMatch $excludeList | ForEach-Object {
        Write-Verbose "$($_.Name) $($_.Version)"
        $foundModule = Find-Module $_.Name -ea 0
        Write-Verbose "$($foundModule.Name) $($foundModule.Version))"
        if ($_.Version -eq $foundModule.Version) {
            $updateNeeded = $false
        } else {
            $updateNeeded = $true
        }
        $obj = [PSCustomObject]@{
            Name           = $_.Name
            CurrentVersion = $_.Version
            NewVersion     = $foundModule.Version
            UpdateNeeded   = $updateNeeded
        }
        $result += $obj
    }

    return $result

}

function Get-InstalledPrograms {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $SearchString,
        [Parameter()] [switch] $ExtendedInfo,
        [Parameter()] [switch] $CopyToClipboard
    )

    # $Installed1 = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
    # $Installed2 = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
    # $Installed3 = Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*

    # $Installed = $Installed1 + $Installed2 + $Installed3

    # $Installed = $Installed | Where-Object DisplayName

    $Installed = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*) +
    (Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*) +
    (Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*)

    $Installed = $Installed | Where-Object { $_.DisplayName }


    if ($SearchString) {
        $Apps = $Installed | Where-Object { ($_.DisplayName -Like "*$($SearchString)*") -or ($_.Publisher -Like "*$($SearchString)*") }
    } else {
        $Apps = $Installed
    }

    $Apps = $Apps | Select-Object PSChildName, DisplayName, DisplayVersion, Publisher, InstallDate, UninstallString | Sort-Object DisplayName

    $return = foreach ($r in $Apps) {
        if ($r.UninstallString -like "*msiexec*") {
            $PSUninstallString = "cmd /c msiexec.exe /X$(($r.PSChildName)) /qn"
        } else {
            $PSUninstallString = "Start-Process '$($r.UninstallString)'"
        }

        $obj = [PSCustomObject]@{
            DisplayName    = $r.DisplayName
            DisplayVersion = $r.DisplayVersion
            Publisher      = $r.Publisher
        }

        if ($ExtendedInfo) {
            $obj | Add-Member -MemberType NoteProperty -Name PSChildName -Value $r.PSChildName
            $obj | Add-Member -MemberType NoteProperty -Name InstallDate -Value $r.InstallDate
            $obj | Add-Member -MemberType NoteProperty -Name UninstallString -Value $r.UninstallString
            $obj | Add-Member -MemberType NoteProperty -Name PSUninstallString -Value $PSUninstallString
        }

        $obj
    }

    if ($CopyToClipboard) {
        $return[-1].PSUninstallString | clip
    }

    return $return
}


function Get-OsStartupsAndShutdowns {
    [CmdletBinding()]
    param (

    )

    $filter = @{
        logname   = 'System'
        starttime = (Get-Date).AddDays(-10).date
    }
    $events = Get-WinEvent -FilterHashtable $filter | Where-Object { $_.Id -eq 12 -or $_.Id -eq 13 -and $_.Message -notmatch "Credential" }

    # $filter = @{
    # logname = 'System'
    # starttime = (Get-Date).date
    # id = 12
    # }

    # $events = Get-WinEvent -FilterHashtable $filter

    # $filter = @{
    # logname = 'System'
    # id = 12
    # starttime = (Get-Date).date
    # }

    # $events += Get-WinEvent -FilterHashtable $filter
    # Get-WinEvent -FilterHashtable @{logname = 'security'; id = 4624; starttime = (Get-Date).date } | Where-Object { $_.properties[8].value -eq 2 }

    $returnEvents = @()
    $events | ForEach-Object {
        
        if ($_.Id -eq 12) {
            $eventType = "Startup"
        } elseif ($_.Id -eq 13) {
            $eventType = "Shutdown"
        }
        $eventDate = ($_.TimeCreated).Date -replace " 00:00:00"
        if($eventDate -ne $previousEventDate) {
            $obj = [PSCustomObject]@{
                Event = "------------"
                Date  = "------------"
                Time  = "------------"
            }
            $returnEvents += $obj
        }

        $obj = [PSCustomObject]@{
            Event = $eventType
            Date  = $eventDate
            # Time = "$(($_.TimeCreated).TimeOfDay.Hours):$(($_.TimeCreated).TimeOfDay.Minutes):$(($_.TimeCreated).TimeOfDay.Seconds)"
            Time  = $(($_.TimeCreated).TimeOfDay -split "\.")[0]
        }
        $returnEvents += $obj

        $previousEventDate = $eventDate

    }

    return $returnEvents

}


function Get-PrinterDetails {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $Name
    )


    $printers = Get-Printer
    if ($Name) {
        $printers = $printers | Where-Object Name -EQ $Name
    }

    $Result = @()

    foreach ($p in $printers) {

        $PortDetails = Get-PrinterPort -Name $p.PortName -ea 0
        # $PrinterProperties = Get-PrinterProperty -PrinterName $p.Name

        $obj = [PSCustomObject]@{
            PrinterName           = $p.Name
            ComputerName          = $p.ComputerName
            PrinterType           = $p.Type
            PrinterShareName      = $p.ShareName
            PrinterPortName       = $p.PortName
            PrinterDriverName     = $p.DriverName
            PrinterLocation       = $p.Location
            PrinterComment        = $p.Comment
            PrinterPrintProcessor = $p.PrintProcessor
            PrinterDatatype       = $p.Datatype
            PrinterShared         = $p.Shared
            PrinterPublished      = $p.Published
            PrinterDeviceType     = $p.DeviceType
            PrinterPrinterStatus  = $p.PrinterStatus
            Name                  = $PortDetails.Name
            PortDescription       = $PortDetails.Description
            PortMonitor           = $PortDetails.PortMonitor
            PrinterHostAddress    = $PortDetails.PrinterHostAddress
            PrinterHostIP         = $PortDetails.PrinterHostIP
            Protocol              = $PortDetails.Protocol
        }

        $Result += $obj


        # Get-PrinterDriver
        # Get-PrintConfiguration -PrinterName $p.Name
    }

    return $Result
}


$scriptblock = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
    $o = Get-Printer | Where-Object { $_.Name -like "$wordToComplete*" }
    $o.Name | ForEach-Object {
        if ($_ -match " ") {
            "'$_'"
        } else {
            $_
        }
    }
}
Register-ArgumentCompleter -CommandName Get-PrinterDetails -ParameterName Name -ScriptBlock $scriptblock



function Get-SpecialFolders {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $SpecialFolderName
    )



    $SpecialFolders = @()

    [Enum]::GetNames([Environment+SpecialFolder]) | Sort-Object | ForEach-Object {
        $ThisSpecialFolder = [PSCustomObject]@{
            Name      = $_
            PSCommand = "[Environment]::GetFolderPath(`"$_`")"
            Path      = [Environment]::GetFolderPath($_)
        }
        $SpecialFolders += $ThisSpecialFolder
    }
    if ($SpecialFolderName) {
        $SpecialFolders = $SpecialFolders | Where-Object Name -EQ $SpecialFolderName
    }



    return $SpecialFolders

}


$scriptblock = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
    $o = [Enum]::GetNames([Environment+SpecialFolder]) | Sort-Object | Where-Object { $_ -like "$wordToComplete*" }
    $o | ForEach-Object {
        if ($_ -match " ") {
            "'$_'"
        } else {
            $_
        }
    }
}
Register-ArgumentCompleter -CommandName Get-SpecialFolders -ParameterName SpecialFolderName -ScriptBlock $scriptblock


function Get-UserProfiles {
    [CmdletBinding()]
    param (

    )


    $Profiles = Get-CimInstance Win32_UserProfile
    $ProfilesFiltered = $Profiles | Where-Object { $_.LastUseTime -and $_.Special -eq $false }
    # $Profiles | Select-Object LocalPath, LastUseTime, SID, Loaded, Special, HealthStatus | ft
    return $ProfilesFiltered



}

# Get-UserProfiles | Where-Object { $_.LastUseTime -lt (Get-Date).AddDays(-180) } | Remove-CimInstance

function Get-WifiNetworks {
    [CmdletBinding()]
    param (
        [Parameter()] [switch] $SaveToOneDrive
    )


    $result = @()

    $wifi = $(netsh.exe wlan show profiles)

    if ($wifi -match "There is no wireless interface on the system.") {
        Write-Output $wifi
        exit
    }

    $ListOfSSID = ($wifi | Select-String -Pattern "\w*All User Profile.*: (.*)" -AllMatches).Matches | ForEach-Object { $_.Groups[1].Value }
    # $NumberOfWifi = $ListOfSSID.count
    # Write-Warning "[$(Get-Date)] I've found $NumberOfWifi Wi-Fi Connection settings stored in your system $($env:computername) : "
    foreach ($SSID in $ListOfSSID) {
        try {
            $passphrase1 = ($(netsh.exe wlan show profiles name="$SSID" key=clear) | Select-String -Pattern ".*Key Content.*:(.*)" -AllMatches).Matches.Value
            Write-Verbose $passphrase1
            $passphrase = ($passphrase1 -split ":")[1]
            Write-Verbose $passphrase
        } catch {
            $passphrase = "N/A"
        }
        $obj = [PSCustomObject]@{
            Name       = ($SSID).Trim()
            PassPhrase = ($passphrase).Trim()
        }
        $result += $obj
    }

    if ($SaveToOneDrive) {
        $OutFile = "$($env:OneDrive)\WiFi_$($env:COMPUTERNAME).csv"
        Remove-Item $OutFile -Force -ea 0
        $result | Export-Csv $OutFile -NoClobber -Force -Verbose
    }

    return $result

}


function Get-WorkingTime {

    # version 1


    # $Date = Get-Date

    # $Today = [string]$Date.Day + [string]$Date.Month + [string]$Date.Year

    #$ComputerinfoTempFile =

    # $ComputerinfoTempFile = "$($env:TEMP)\ComputerInfo_$($Today).csv"

    # if (!(Test-Path $ComputerinfoTempFile)) {
    # Get-ComputerInfo | Export-Csv -Path $ComputerinfoTempFile -NoTypeInformation
    # }

    $WT = [ordered]@{}

    # $Computerinfo = Import-Csv $ComputerinfoTempFile

    # $OsLastBootUpTime = Get-Date -Date $Computerinfo.OsLastBootUpTime

    $WTFolderPath = "C:\temp\WorkingTime"
    if(-not(Test-Path $WTFolderPath)) {
        New-Item $WTFolderPath -ItemType Directory -Force | Out-Null
    }
    $WTFilePath = Join-Path $WTFolderPath "wt_$(Get-Date -Format "yyyy-MM-dd").json"
    # Remove-Item $WTFilePath -Force -ea 0
    if (Test-Path $WTFilePath) {
        $WTInfo = Get-Content $WTFilePath | ConvertFrom-Json
        $WMI_OsLastBootUpTime = $WTInfo.LastBootUpTime
    } else {
        # $WMI_OsLastBootUpTime = Get-CimInstance win32_operatingsystem | Select-Object @{LABEL = 'LastBootUpTime'; EXPRESSION = { ($_.ConverttoDateTime($_.lastbootuptime)).DateTime } }
        $WMI_OsLastBootUpTime = Get-CimInstance win32_operatingsystem | Select-Object LastBootUpTime
        $WMI_OsLastBootUpTime | ConvertTo-Json | Out-File $WTFilePath
        $WMI_OsLastBootUpTime = $WMI_OsLastBootUpTime.LastBootUpTime
    }
    # $WMI_OsLastBootUpTime


    $OsLastBootUpTime = Get-Date $WMI_OsLastBootUpTime

    $WT["StartTijd"] = Get-Date $OsLastBootUpTime -Format "HH:mm:ss"

    $WorkingTime = (Get-Date) - $OsLastBootUpTime

    $WT["TijdGewerkt"] = $WorkingTime


    $HoeLangNog = (Get-Date -Hour 8 -Minute 30 -Second 0) - $WorkingTime

    $WT["HoeLangNog"] = Get-Date $HoeLangNog -Format "HH:mm:ss"

    $HoeLangNogHalveDag = (Get-Date -Hour 4 -Minute 0 -Second 0) - $WorkingTime

    $WT["HoeLangNogHalveDag"] = Get-Date $HoeLangNogHalveDag -Format "HH:mm:ss"

    $WT["JeMoetTot"] = Get-Date $OsLastBootUpTime.AddMinutes(510) -Format "HH:mm:ss"

    return $WT

}


function Import-MyModule {

    [CmdletBinding()]

    param (
        [Parameter()]
        [ArgumentCompleter( {
                param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters )
                Get-ChildItem "$(Join-Path $($env:USERPROFILE) -ChildPath "Git\")$wordToComplete*" -Directory -Name | ForEach-Object { $_ } }
        )]
        [ValidateScript( {
                $_ -in (Get-ChildItem "$(Join-Path $($env:USERPROFILE) -ChildPath "Git\")" -Directory -Name)
            } ) ]
        [string] $Module,
        [Parameter()] [switch] $All,
        [Parameter()] [switch] $ShowVersion
    )


    function Import-MyModuleInternal {

        [CmdletBinding()]
        param (
            [Parameter(Mandatory)] [string] $InternalModule
        )

        $ShowVersion = $true

        $ModuleManifest = "$(Join-Path $($env:USERPROFILE) -ChildPath "Git")\$($InternalModule)\$InternalModule.psd1"

        if (Test-Path $ModuleManifest) {
            if ($ShowVersion) {
                $ModuleVersion = Get-Module $InternalModule | Where-Object Path -Like "*\git\*" | Select-Object Name, Version
                Write-Verbose "Old version: $($ModuleVersion.Name) $($ModuleVersion.Version)" -Verbose
            }

            Import-Module $ModuleManifest -Force -Global

            if ($ShowVersion) {
                $ModuleVersion = Get-Module $InternalModule | Where-Object Path -Like "*\git\*" | Select-Object Name, Version
                Write-Verbose "New version: $($ModuleVersion.Name) $($ModuleVersion.Version)" -Verbose
            }
        } else {
            Write-Warning "Module $ModuleManifest not found"
        }

    }





    if ($All) {

        $Folders = Get-ChildItem (Join-Path $env:USERPROFILE "Git") | Where-Object Name -NE "JaapsTools"
        # Write-Verbose ($Folders | Out-String) -Verbose
        foreach ($folder in $Folders) {
            Write-Verbose $folder.Name
            Import-MyModuleInternal -InternalModule $folder.Name
        }
        Import-MyModuleInternal -InternalModule JaapsTools

    } else {

        if (!($Module)) {
            $PossibleModulename = Get-Item . | Select-Object -ExpandProperty Name
            $ModuleFile = "$PossibleModulename.psd1"
            # Write-Verbose $PossibleModulename -Verbose
            # Write-Verbose $ModuleFile -Verbose
            if (Test-Path $ModuleFile) {
                $Module = $PossibleModulename
                Write-Verbose $PossibleModulename -Verbose
            }
        }

        if ($Module) {
            Import-MyModuleInternal -InternalModule $Module
        } else {
            Write-Warning "No module file found in this folder"
        }
    }

}

function Invoke-ChocoOutdated {

    # version 1

    choco outdated --ignore-pinned

}

function Invoke-ChocoUpgradeAll {

    # version 1

    choco upgrade all -y

}

function Invoke-ParallelRobocopy {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $Source,
        [Parameter(Mandatory)] [string] $Destination,
        [Parameter()] [string] $ExcludeDirectories,
        [Parameter()] [int] $MaxParallelJobs = 2
    )

    if ($Source[-1] -eq "\") {
        $Source = $Source.Substring(0, ($Source.Length - 1))
    }
    if ($Destination[-1] -eq "\") {
        $Destination = $Destination.Substring(0, ($Destination.Length - 1))
    }
    Write-Verbose $Source
    Write-Verbose $Destination

    $dirs = Get-ChildItem $Source -Directory
    if ($ExcludeDirectories) {
        $dirs = $dirs | Where-Object Name -NotMatch $ExcludeDirectories
    }
    Write-Verbose ($dirs | Format-Table | Out-String)

    $processRc = @{}

    $dirs | ForEach-Object {

        $i++
        $subSource = $_.FullName
        $subDestination = Join-Path $Destination $_.Name
        $processRc[$i] = Start-Process -FilePath "robocopy.exe" -ArgumentList "`"$($subSource)`" `"$($subDestination)`" /MIR /NFL /NDL /W:1 /R:1 /MT:32" -PassThru -WindowStyle Minimized

        while (($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count -ge $MaxParallelJobs) {
            Write-Warning "Waiting to finish $(($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count) robocopy jobs"
            Start-Sleep 1
        }

    }

    while ($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }) {
        Write-Warning "Waiting to finish $(($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count) robocopy jobs before final sync"
        Start-Sleep 1
    }

    Start-Process -FilePath "robocopy.exe" -ArgumentList "`"$($Source)`" `"$($Destination)`" /MIR /NFL /NDL /W:1 /R:1 /MT:128 /XD $($ExcludeDirectories)" -NoNewWindow -Wait

}

function Invoke-Timer {

    [CmdletBinding()]


    param (
        [parameter()] [int] $Time = 3,
        [Parameter()] [string] [ValidateSet("Seconds", "Minutes", "Hours")] $HMS = "Seconds",
        [parameter()] [string] $At
    )


    switch ($HMS) {
        "Hours" {
            $Seconds = ($time * 60 * 60)
        }
        "Minutes" {
            $Seconds = ($time * 60)
        }
        "Seconds" {
            $Seconds = $time
        }
    }





    if ($At) {

        if ($At.Length -eq 3) {
            # $At

            $At = "0$($At)"
            $At

        } elseif ($At.Length -eq 4) {

        } else {
            Write-Error "`"At`" not in correct format"
        }

        $ShutdownHour = $At[0] + $At[1]
        $ShutdownHour = [int]$ShutdownHour
        # $ShutdownHour

        $ShutdownMinute = $At[2] + $At[3]
        $ShutdownMinute = [int]$ShutdownMinute
        # $ShutdownMinute

        if ($ShutdownHour -gt 23 -or $ShutdownMinute -gt 59) {
            Write-Error "Time input not correct"
            break
        }

        $EndTime = Get-Date -Hour $ShutdownHour -Minute $ShutdownMinute -Second 00

        if ($EndTime -lt (Get-Date)) {
            $EndTime = $EndTime.AddDays(1)
        }

    } else {
        $EndTime = (Get-Date).AddSeconds($Seconds)
    }

    while (($TimeRemaining = ($EndTime - (Get-Date))) -gt 0) {

        Write-Progress -Activity 'Timer running until...' -Status $EndTime -SecondsRemaining $TimeRemaining.TotalSeconds
        Start-Sleep 1

    }


}


function logout {
    [CmdletBinding()]
    param (

    )

    Stop-ProcessSoft msedge -Silent
    Stop-ProcessSoft -ProcessName chrome -Silent
    Stop-ProcessSoft -ProcessName EXCEL -Silent

    Start-Sleep 1

    logoff

}

function Maintenance {
    [CmdletBinding()]
    param (
        [Parameter()] [switch] $UpdateAll,
        [Parameter()] [switch] $UpdatePSModules,
        [Parameter()] [switch] $UpdateHelp
    )

    cua
    cr
    rdi

    Write-Host "`n----`n"
    Remove-DownloadFolderItems
    Show-TrayIcons

    # Backup-MySettings -All
    # Set-ChocoPinList


    if (Get-Command Get-MpComputerStatus -ea 0) {
        $MpScan_Params = @{
            AsJob = $true
        }
        if ((Get-MpComputerStatus).FullScanOverdue -eq $true) {
            $MpScan_Params.Add('ScanType', 'FullScan')
        }

        if ((Get-MpComputerStatus).QuickScanOverdue -eq $true -or (Get-MpComputerStatus).FullScanOverdue -eq $true) {
            Start-MpScan @MpScan_Params
        }
    }

    if ($UpdateAll -or $UpdatePSModules) {
        Start-Job -ScriptBlock {
            Update-InstalledModule
            Uninstall-OldInstalledModules
        }
    }
    if ($UpdateAll -or $UpdateHelp) {
        Start-Job -ScriptBlock { Update-Help -Scope AllUsers -Force -ea 0 }
    }



}


function New-ChromiumProfile {
    [CmdletBinding()]
    param (

    )

    $Params = @{
        FilePath     = "C:\Program Files\Chromium\Application\chrome.exe"
        ArgumentList = "--profile-directory=Profile$(Get-Random)"
    }
    Start-Process @Params -Verbose

}

function New-GitBranch {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $BranchName
    )


    git branch $BranchName
    git switch $BranchName
    git push --set-upstream origin $BranchName

}

function New-GitHubIssue {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $Title,
        [Parameter(Mandatory)] [ValidateSet("enhancement", "bug")] [string[]] $Labels,
        [Parameter()] [string] $Body = ""
    )

    if (!(Test-Path "C:\Program Files\GitHub CLI\gh.exe")) {
        throw "Github CLI not installed. Missing `"C:\Program Files\GitHub CLI\gh.exe`""
    }

    if (!(gh api /user)) {
        throw "Not logged in to GitHub"
    }

    # if (!(Test-Path ".git")) {
    # throw "not a git repository"
    # }


    gh issue create --label $Labels --title "$($Title)" --assignee '@me' --body $Body



}

function New-GitHubPullRequest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $Title,
        [Parameter()] [int] $IssueNo,
        [Parameter()] [string] $Body,
        [Parameter()] [switch] $Merge
    )

    $BodyString = ""
    if ($Body) {
        $BodyString = "$($BodyString) $($Body)"
    }
    if ($IssueNo) {
        $BodyString = "$($BodyString) - Fixes #$($IssueNo)"
    }
    $BodyString = $BodyString.Trim()

    gh pr create -t $Title -b $BodyString

    gh pr list

    if ($Merge) {
        gh pr merge
    }

}

function New-GuitarRecord {

    $VideoRecordFolder = "$($env:OneDrive)\Guitar\VideoRecord"
    $Date = Get-Date -Format "yyyyMMdd"
    
    $CakewalkTemplateProject = "$VideoRecordFolder\Template\Template"
    $ShotcutTemplateProject = "$VideoRecordFolder\Template\Template.mlt"

    $Artist = Read-Host -Prompt "Artist" 

    $Title = Read-Host -Prompt "Title"

    if(!($Artist) -or !($Title)) {
        break
    }

    #$NewProjectName = "Dragon Force - Through the fire and the Flames"
    $NewProjectName = "$Artist - $Title"

    $NewProjectFolder = "$VideoRecordFolder\$Date - $NewProjectName"
    $NewProjectFolderAudio = "$NewProjectFolder\A"
    $NewProjectFolderVideo = "$NewProjectFolder\V"
    

    ##

    #ls $VideoRecordFolder

    #$Date

    ##

    New-Item -ItemType Directory $NewProjectFolder -Force
    New-Item -ItemType Directory $NewProjectFolderVideo -Force
    New-Item -ItemType Directory $NewProjectFolderAudio -Force


    #Start-Process "Robocopy" -ArgumentList "$CakewalkTemplateProject $NewProjectFolderAudio /MIR" -Wait -PassThru
    Robocopy.exe $CakewalkTemplateProject $NewProjectFolderAudio /MIR

    Rename-Item "$NewProjectFolderAudio\Template.cwp" "$NewProjectFolderAudio\$NewProjectName.cwp"

    Copy-Item $ShotcutTemplateProject $NewProjectFolderVideo
    Rename-Item "$NewProjectFolderVideo\Template.mlt" "$NewProjectName.mlt"

    explorer $NewProjectFolder

    ##

}

function New-MyVolume {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateScript( {
                $_ -in ((Get-Disk).Number)
            } ) ]
        [string] $Disk,
        [Parameter(Mandatory)] [string] $DriveLetter
    )

    if ((Get-Disk -Number $Disk).AllocatedSize -ne 0) {
        Write-Warning "Unable to create partition, the disk already has data present."
    } elseif (Get-Volume $DriveLetter -ea 0) {
        Write-Warning "Unable to create partition, a volume with driveletter $DriveLetter already exists."
    } else {
        Clear-Disk $Disk -Confirm:$false -ea 0
        Initialize-Disk $Disk -PartitionStyle GPT
        New-Volume -DiskNumber $Disk -FileSystem NTFS -DriveLetter $DriveLetter -FriendlyName $DriveLetter
    }
}

function New-Password {
    [CmdletBinding()]
    param (
    )


    $words = @(
        "Appel"
        "Banaan"
        "Balpen"
        "Circus"
        "Camera"
        "Camper"
        "Koffie"
        "Kleuren"
        "Liefde"
        "Bloemen"
        "Laptop"
        "Fietsen"
        "Visser"
        "Winter"
        "Zomer"
        "Jurken"
        "Zwemmer"
        "Strand"
        "Hotel"
        "Vlinder"
        "Paddestoel"
        "Bossen"
        "Bergen"
        "Golven"
        "Vijver"
        "Tomaat"
        "Schip"
        "Kaars"
        "Toren"
        "Wolk"
        "Steen"
        "Kamer"
        "Vlam"
        "Kasteel"
        "Honing"
        "Vleugel"
        "Kabel"
        "Zeil"
        "Inktvis"
        "Puzzel"
        "Kussen"
        "Spiegel"
        "Schilder"
        "Stoelen"
        "Scharen"
        "Knopen"
        "Bellen"
        "Schroeven"
        "Schop"
        "Ketting"
        "Tapijt"
        "Horloge"
        "Stral"
        "Kist"
        "Ballon"
        "Torpedo"
        "Ladder"
        "Gordijn"
        "Baksteen"
        "Komeet"
        "Paraplu"
        "Spijker"
        "Laars"
        "Schaats"
        "Redder"
        "Raam"
        "Tafel"
        "Metaal"
        "Staaf"
        "Potlood"
        "Sleutel"
        "Zwaard"
        "Kraan"
        "Container"
        "Zaklamp"
        "Fotolijst"
        "Schilderij"
        "Hanger"
        "Schelp"
        "Beker"
        "Liniaal"
        "Bomen"
        "Struiken"
        "Poeders"
        "Radijs"
        "Olijven"
        "Meloen"
        "Avocados"
        "Ananas"
        "Pompelmoes"
        "Sinaasappel"
        "Citroen"
        "Mandarijn"
        "Abrikoos"
        "Aardbei"
        "Framboos"
        "Guave"
        "Wortels"
        "Spinazie"
        "Broccoli"
        "Tomaten"
        "Radijzen"
        "Komkommers"
        "Pompoenen"
        "Komijn"
        "Knoflook"
        "Paprika"
        "Courgette"
        "Boontjes"
        "Peterselie"
        "Rozemarijn"
        "Tijm"
        "Oregano"
        "Dille"
        "Dragon"
        "Salie"
        "Kervel"
        "Bieslook"
        "Munt"
        "Kamille"
        "Laurier"
        "Anijs"
        "Kaneel"
        "Gember"
        "Vanille"
        "Nootmuskaat"
        "Kruidnagel"
        "Kardemom"
        "Koriander"
        "Karwij"
        "Venkel"
        "Selderij"
        "Mosterd"
        "Peper"
        "Zout"
        "Suiker"
        "Siroop"
        "Karamel"
        "Marshmallow"
        "Praline"
        "Marsepein"
        "Braam"
        "Bosbes"
        "Aalbes"
        "Kers"
        "Druif"
        "Papaja"
        "Perzik"
        "Pruim"
        "Nectarine"
        "Kiwi"
        "Mango"
        "Vrucht"
        "Bonbon"
        "Chocolade"
        "Cupcake"
        "Dropveter"
        "Kauwgom"
        "Kaneelstok"
        "Kruidnoot"
        "Lolly"
        "Napoleon"
        "Noga"
        "Paasei"
        "Pepermunt"
        "Pepernoot"
        "Salmiak"
        "Schuimpje"
        "Skittles"
        "Suikerspin"
        "Toffee"
        "Toverbal"
        "Tumtum"
        "Winegum"
        "Zoethout"
        "Zuremat"
        "Zuurstok"
        "Zuurtje"
        "Zwartwit"
        "Avocado"
        "Cranberry"
        "Dadel"
        "Granaatappel"
        "Grapefruit"
        "Kokosnoot"
        "Limoen"
        "Moerbei"
        "Olijf"
        "Peer"
        "Vlierbes"
        "Watermeloen"
        # Gereedschap toevoegen
    )


    $word = Get-Random $words

    $specialChar = Get-Random @("!", "@", "#", "$", "%", "&", "*", "(", ")", "-", "=")

    $number = Get-Random -Minimum 101 -Maximum 998


    $password = "$($word)$($specialChar)$($number)"

    return $password

}




function New-RegKey {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $Path,
        [Parameter(Mandatory)] [string] $Name,
        [Parameter(Mandatory)] [ValidateSet("SEG_SZ", "SEG_EXPAND_SZ", "REG_BINARY", "REG_DWORD", "SEG_MULTI_SZ", "REG_QWORD")] [string] $PropertyType,
        [Parameter(Mandatory)] [string] $Value
    )

    $PropertyTypes = @{
        SEG_SZ        = "String"
        SEG_EXPAND_SZ = "ExpandString"
        REG_BINARY    = "Binary"
        REG_DWORD     = "DWord"
        SEG_MULTI_SZ  = "MultiString"
        REG_QWORD     = "QWord"
    }

    $Param = @{
        Path         = $Path
        Name         = $Name
        PropertyType = $PropertyTypes[$PropertyType]
        Value        = $Value
    }


    $Param

    New-ItemProperty @Param -Force -ErrorAction 0


}

function New-Shortcut {
    [CmdletBinding()]
    param (
        [parameter(mandatory = $true)][string]$ShortcutLocation,
        [parameter(mandatory = $true)][string]$ShortcutTarget,
        [string]$Arguments,
        [string]$IconLocation
    )

    Write-Verbose "Creating shortcut with parameters:"
    Write-Verbose ($PSCmdlet.MyInvocation.BoundParameters | Out-String)

    $shortcutTargetParent = Split-Path $ShortcutTarget -Parent

    $WshShell = New-Object -ComObject WScript.Shell

    $Shortcut = $WshShell.CreateShortcut($ShortcutLocation)
    if ($Arguments) {
        $Shortcut.Arguments = $Arguments
    }
    $Shortcut.TargetPath = $ShortcutTarget
    if ($shortcutTargetParent) {
        $Shortcut.WorkingDirectory = $shortcutTargetParent
    }
    if ($IconLocation) {
        $Shortcut.IconLocation = $IconLocation
    }

    if ($Shortcut.Save()) {

        Write-Verbose "Shortcut created with the following parameters:"
        Write-Verbose ($Shortcut | Out-String)

    }
}


function New-ShortcutAdvanced {
    param (
        [parameter(Mandatory = $true)] [string] $ShortcutLocation,
        [parameter(Mandatory = $true)] [string] $ShortcutTarget,
        [parameter()] [string] $Arguments,
        [parameter()] [string] $IconLocation,
        [parameter()] [switch] $Force
    )


    function Test-URI {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory = $true)]
            [String]
            $URI
        )

        $URI2 = $URI -as [System.Uri]
        $validation = ($null -ne $URI2.AbsoluteURI) -and ($URI2.Scheme -match '[http|https]')
        return $validation

    }


    if ($Force) {
        New-Item $ShortcutLocation -ItemType File -Force -ErrorAction Stop | Out-Null
        Write-Verbose "File created: $($ShortcutLocation)"
    }

    $ShortcutParent = Split-Path $ShortcutLocation -Parent
    Write-Verbose "ShortcutParent: $($ShortcutParent)"
    $ShortcutLeaf = Split-Path $ShortcutLocation -Leaf
    Write-Verbose "ShortcutLeaf: $($ShortcutLeaf)"


    $ShortcutParent = Resolve-Path $ShortcutParent -ErrorAction Stop
    Write-Verbose "ShortcutParent: $($ShortcutParent)"
    if (!($Force)) {
        if (Test-URI $ShortcutTarget) {

        } else {
            $ShortcutTarget = Resolve-Path $ShortcutTarget -ErrorAction Stop
        }
    }
    Write-Verbose "ShortcutTarget: $($ShortcutTarget)"
    if ($ShortcutTarget -match '[http|https]') {
    } else {
        $shortcutTargetParent = Split-Path $ShortcutTarget -Parent
        Write-Verbose "shortcutTargetParent: $($shortcutTargetParent)"
    }

    if ($IconLocation) {
        $IconSplitString = $IconLocation -split ","
        $IconLocation = Resolve-Path $IconSplitString[0] -ErrorAction Stop
        if ($IconSplitString[1]) {
            $IconLocation = "$($IconLocation),$($IconSplitString[1])"
        }
        Write-Verbose "IconLocation: $($IconLocation)"
    }


    $ShortcutLocationDefinitive = Join-Path $ShortcutParent $ShortcutLeaf
    Write-Verbose "ShortcutLocationDefinitive: $($ShortcutLocationDefinitive)"


    $WshShell = New-Object -ComObject WScript.Shell

    $Shortcut = $WshShell.CreateShortcut($ShortcutLocationDefinitive)
    if ($Arguments) {
        $Shortcut.Arguments = $Arguments
    }
    $Shortcut.TargetPath = $ShortcutTarget
    if ($shortcutTargetParent) {
        $Shortcut.WorkingDirectory = $shortcutTargetParent
    }
    if ($IconLocation) {
        $Shortcut.IconLocation = $IconLocation
    }
    # $Shortcut
    $Shortcut.Save()



}


function Open-InExplorer {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $Path = "."
    )

    Write-Verbose $Path

    $NewPath = (Resolve-Path $Path).Path

    Write-Verbose $NewPath

    if (Test-Path $NewPath) {

        if($NewPath[$NewPath.Length - 1] -eq "\") {
            $NewPath2 = $NewPath.Substring(0, ($NewPath.Length - 1))
        } else {
            $NewPath2 = $NewPath
        }


        Write-Verbose $NewPath2

        explorer.exe $NewPath2

    } else {
        Write-Warning "$NewPath not found"
    }


}

function Open-JPSHistory {
    
    # version 1

    notepad++.exe (Get-PSReadlineOption).HistorySavePath

}

function Open-NewWindowsinstallScript {
    [CmdletBinding()]
    param (

    )

    $ScriptLoc = "$(Split-Path (Get-Module JaapsTools).path)\scripts\New-Windowsinstall.ps1"

    $PreferredApps = @(
        # "C:\Program Files\Microsoft VS Code\Code.exe"
        "C:\Program Files\Notepad++\notepad++.exe"
    )

    foreach ($app in $PreferredApps) {
        if (Test-Path $app) {
            Start-Process $app -ArgumentList "`"$ScriptLoc`""
            $AppFound = $true
            break
        }
    }

    if (!($AppFound)) {
        notepad.exe $ScriptLoc
    }



}

function Remove-DesktopIcons {

    # version 1

    Get-ChildItem $env:OneDrive\Bureaublad -ErrorAction 0 | Remove-Item -Recurse -Force
    Get-ChildItem $env:OneDrive\Desktop -ErrorAction 0 | Remove-Item -Recurse -Force
    Get-ChildItem $env:PUBLIC\Bureaublad -ErrorAction 0 | Remove-Item -Recurse -Force
    Get-ChildItem $env:PUBLIC\Desktop -ErrorAction 0 | Remove-Item -Recurse -Force
    Get-ChildItem $env:USERPROFILE\Desktop -ErrorAction 0 | Remove-Item -Recurse -Force

}

function Remove-DownloadFolderItems {
    [CmdletBinding()]
    param (
        # [Parameter()] [string] $ParameterName
    )

    $DownloadFolder = "$($env:USERPROFILE)\Downloads"

    $Items = Get-ChildItem $DownloadFolder -File

    $RemoveMatch = @()
    $RemoveMatch += "*.ica"
    $RemoveMatch += "*.rdp"

    if ($Items) {
        foreach ($rm in $RemoveMatch) {
            $Items.FullName -like $rm | ForEach-Object {
                Write-Host "Removing: $($_)" -ForegroundColor Yellow
                Remove-Item $_
            }
        }
    }
}

function Remove-GitBranchesNotExistantOnline {
    [CmdletBinding()]
    param (
    )

    $GitConfigPath = Join-Path . ".git"

    if (Test-Path $GitConfigPath) {

        $Ignorelist = @("HEAD", "main", "master")

        git fetch -a -p

        $gitBranchesLocal = ((git branch) -replace '\*', "").Trim()
        $gitBranchesRemote = (git branch -r).Trim()

        if ($gitBranchesLocal -match "main") {
            $defaultBranch = "main"
        } elseif ($gitBranchesLocal -match "master") {
            $defaultBranch = "master"
        } else {
            break
        }
        Write-Host "Switching to branch $($defaultBranch)" -ForegroundColor Green
        git switch $defaultBranch

        "-------------------------"
        Write-Host "Local branches" -ForegroundColor Yellow
        $gitBranchesLocal
        # ($gitBranchesLocal).GetType()
        "-------------------------"
        Write-Host "Remote branches" -ForegroundColor Yellow
        $gitBranchesRemote
        "-------------------------`n`n`n"
        "-------------------------"
        $gitBranchesLocal | ForEach-Object {
            # $_
            # "next`n"
            Write-Host "Checking local branch `"$($_)`"" -ForegroundColor Yellow
            if ($Ignorelist -contains $_) {
                Write-Host "Branch $($_) will be ignored" -ForegroundColor Red
            } else {
                # $branchName = ($_ -split "/")[-1]
                if ($gitBranchesRemote -match $_) {
                    Write-Host "This branch exists remote and locally" -ForegroundColor Green
                } else {
                    Write-Host "This branch exists only locally" -ForegroundColor Red
                    if ((Read-Host -Prompt "Delete branch $_? (y/N)") -eq "y") {
                        git branch -d $_
                    }
                }
            }

            "-------------------------"
        }

    } else {
        Write-Warning "This folder is not git folder"
    }
}

function Resize-MyVolume {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $DriveLetter
    )

    Get-Disk | Update-Disk

    $MaxPartitionSize = Get-Partition -DriveLetter $DriveLetter | Get-PartitionSupportedSize | Select-Object -ExpandProperty SizeMax
    # Write-Host $MaxPartitionSize
    if ((Get-Partition -DriveLetter $DriveLetter).size -eq $MaxPartitionSize) {
        Write-Warning "Partition $DriveLetter is already the maximum size"
    } else {
        Resize-Partition -DriveLetter $DriveLetter -Size $MaxPartitionSize
    }

}

function Send-WOL {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $MacAddress
    )

    Write-Verbose "$($MacAddress)"
    Start-Process "$($PSScriptRoot)\..\Resources\wakemeonlan\WakeMeOnLan.exe" -ArgumentList "/wakeup $($MacAddress)" -Wait -NoNewWindow


}


function Set-ClevoPowerMode {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [ValidateSet("Quiet", "Powersaving", "Performance", "Entertainment")] [string] $PowerMode
    )

    Start-Process $PSScriptRoot\..\resources\opencontrol\opencontrol.exe -ArgumentList "Power $PowerMode" -NoNewWindow -Wait

}

function Set-IPAddress {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, ParameterSetName = 'IP')] [string] $IP,
        [Parameter(Mandatory, ParameterSetName = 'IP')] [string] $Prefix,
        [Parameter(Mandatory, ParameterSetName = 'IP')] [string] $Gateway,
        [Parameter(Mandatory, ParameterSetName = 'IP')] [string[]] $DNSServers,
        [Parameter(ParameterSetName = 'Dynamic')] [switch] $Dynamic,
        [Parameter()] [int] $IfIndex
    )

    if (-not($IfIndex)) {
        if ((Get-NetAdapter).count -gt 1) {
            Get-NetAdapter
            Write-Host "Choose interface index" -ForegroundColor Yellow
            $IfIndex = Read-Host -Prompt "Choose interface index"
            if (Get-NetAdapter -ifIndex $IfIndex -ea 0) {
            } else {
                Write-Host "Interface with index $IfIndex does not exist" -ForegroundColor Red
                Remove-Variable IfIndex
            }
        } else {
            $IfIndex = (Get-NetAdapter).InterfaceIndex
        }
    }


    if ($IfIndex) {
        if ($Dynamic) {
            Remove-NetIPAddress -InterfaceIndex $IfIndex -Confirm:$false
            Remove-NetRoute -ifIndex $IfIndex -Confirm:$false
            Set-DnsClientServerAddress -ResetServerAddresses -InterfaceIndex $IfIndex
            Set-NetIPInterface -ifIndex $IfIndex -Dhcp Enabled
            ipconfig.exe /renew
        } else {
            Remove-NetIPAddress -InterfaceIndex $IfIndex -Confirm:$false
            Remove-NetRoute -ifIndex $IfIndex -Confirm:$false
            New-NetIPAddress -IPAddress $IP -DefaultGateway $Gateway -PrefixLength $Prefix -InterfaceIndex $IfIndex
            Set-DnsClientServerAddress -ServerAddresses $DNSServers -InterfaceIndex $IfIndex
        }
    }




}

function Set-Mylocation {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [ValidateSet("Git", "DevOps", "OneDrive", "WindowsPowershell", "WindowsPowershellProgramFiles", "Downloads", "MyDocuments", "SharePoint", "SharePoint2", "Powershell", "PowershellProgramFiles", "CameraRoll")] [string] $Folder,
        [Parameter()] [switch] $OpenInExplorer
    )


    switch ($Folder) {
        "Git" {
            $Path = "$([Environment]::GetFolderPath("UserProfile"))\Git"
            if(-not(Test-Path $Path)) {
                New-Item $Path -ItemType Directory
            }
        }
        "DevOps" {
            $Path = "$([Environment]::GetFolderPath("UserProfile"))\DevOps"
            if (-not(Test-Path $Path)) {
                New-Item $Path -ItemType Directory
            }
        }
        "OneDrive" {
            $Path = $env:OneDrive
        }
        "WindowsPowershell" {
            $Path = "$([Environment]::GetFolderPath("MyDocuments"))\WindowsPowerShell"
        }
        "WindowsPowershellProgramFiles" {
            $Path = "$([Environment]::GetFolderPath("ProgramFiles"))\WindowsPowerShell"
        }
        "Powershell" {
            $Path = "$([Environment]::GetFolderPath("MyDocuments"))\PowerShell"
        }
        "PowershellProgramFiles" {
            $Path = "$([Environment]::GetFolderPath("ProgramFiles"))\PowerShell"
        }
        "Downloads" {
            $Path = "$([Environment]::GetFolderPath("UserProfile"))\Downloads"
        }
        "MyDocuments" {
            $Path = "$([Environment]::GetFolderPath("MyDocuments"))"
        }
        "SharePoint" {
            $RegKey = "HKCU:\SOFTWARE\Microsoft\OneDrive\Accounts\Business1\Tenants"
            if (!(Test-Path $RegKey)) {
                break
            }
            $Regpath = Get-ChildItem $RegKey | Where-Object PSChildName -NotLike "*OneDrive*"
            if (!($Regpath)) {
                break
            }
            $Regpath2 = $Regpath[0].Property[0]
            $Regpath3 = Split-Path $Regpath2
            $Path = $Regpath3

        }
        "SharePoint2" {
            $RegKey = "HKCU:\SOFTWARE\Microsoft\OneDrive\Accounts\Business1\Tenants"
            if (!(Test-Path $RegKey)) {
                break
            }
            $Regpath = Get-ChildItem $RegKey | Where-Object PSChildName -NotLike "*OneDrive*"
            if (!($Regpath)) {
                break
            }
            $Regpath2 = $Regpath[1].Property[0]
            $Regpath3 = Split-Path $Regpath2
            $Path = $Regpath3

        }
        "CameraRoll" {
            $Date = Get-Date
            $Path = "$($env:OneDrive)\Pictures\Camera Roll\$($Date.Year)\$(Get-Date -Format "MM")"
            if(!(Test-Path $Path)) {
                $Path = "$($env:OneDrive)\Pictures\Camera Roll\$($Date.Year)"
                if(!(Test-Path $Path)) {
                    $Path = "$($env:OneDrive)\Pictures\Camera Roll"
                }
            }
        }
    }

    # return $Path
    if (Test-Path $Path) {
        Set-Location $Path
        if ($OpenInExplorer) {
            explorer.exe $Path
        }
    } else {
        Write-Error "$Path not found"
    }

}

function Set-OnedriveItemAvailability {
    [CmdletBinding()]
    param (
        [Parameter()] [ValidateSet("Online", "Offline", "FreeUpSpace")] [string] $Setting = "Offline",
        [Parameter()] [string] $Path = ((Get-Location).Path),
        [Parameter()] [string] $Filter
    )


    $loc = Get-Location

    Set-Location $Path
    if ($Filter) {
        switch ($Setting) {
            "Offline" {
                attrib +P /S /D $Filter
            }
            "Online" {
                attrib -P /S /D $Filter
            }
            "FreeUpSpace" {
                attrib -P +U /S /D $Filter
            }
        }
    } else {
        switch ($Setting) {
            "Offline" {
                attrib +P /S /D
            }
            "Online" {
                attrib -P /S /D
            }
            "FreeUpSpace" {
                attrib -P +U /S /D
            }
        }
    }

    Set-Location $loc

}

function Set-PSWindowsTitle {
    param (
        [Parameter(Mandatory = $true)] [ArgumentCompleter( {
                param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters )
                $possibleValues = @('HyperV', 'WI')
                $possibleValues | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { $_ }
            })] [string] $Title
    )

    $host.ui.RawUI.WindowTitle = $Title

}

function Set-Scaling {
    # Posted by IanXue-MSFT on
    # https://learn.microsoft.com/en-us/answers/questions/197944/batch-file-or-tool-like-powertoy-to-change-the-res.html
    # $scaling = 0 : 100% (default)
    # $scaling = 1 : 125%
    # $scaling = 2 : 150%
    # $scaling = 3 : 175%
    param($scaling)
    $source = @'
    [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
    public static extern bool SystemParametersInfo(
                      uint uiAction,
                      int uiParam,
                      uint pvParam,
                      uint fWinIni);
'@

    $apicall = Add-Type -MemberDefinition $source -Name WinAPICall -Namespace SystemParamInfo -PassThru
    $apicall::SystemParametersInfo(0x009F, $scaling, $null, 1) | Out-Null
}



function Show-TrayIcons {
    [CmdletBinding()]
    param (
        [Parameter()] [switch] $Hide
    )

    $regLocation = "HKCU:\Control Panel\NotifyIconSettings\"

    if (Test-Path $regLocation) {
        $TrayIcons = Get-ChildItem $regLocation

        # $TrayIcons

        foreach ($t in $TrayIcons) {

            Write-Verbose $t.Name
            # $IsPromoted = Get-ItemProperty "registry::$($t)" -Name IsPromoted | Select-Object -ExpandProperty IsPromoted

            if ($Hide) {
                $value = 0
            } else {
                $value = 1
            }
            # if ($IsPromoted -ne 1) {
                New-ItemProperty "registry::$($t)" -Name IsPromoted -Value $value -Force | Out-Null
            # }
            # Get-ItemProperty "$($reglocation)\$($t)" -Name IsPromoted

        }
    } else {
        Write-Warning "Reg key `"$($regLocation)`" not found"
    }



}


function ShutdownTimer {

    [CmdletBinding()]


    param (
        [parameter()] [int] $Time = 2,
        [Parameter()] [string] [ValidateSet("Seconds", "Minutes", "Hours")] $HMS = "Seconds",
        [parameter()] [string] $At,
        [parameter()] [switch] $Restart,
        [parameter()] [switch] $Lock
    )


    switch ($HMS) {
        "Hours" {
            $Seconds = ($time * 60 * 60)
        }
        "Minutes" {
            $Seconds = ($time * 60)
        }
        "Seconds" {
            $Seconds = $time
        }
    }





    if ($At) {

        if ($At.Length -eq 3) {
            # $At

            $At = "0$($At)"
            $At

        } elseif ($At.Length -eq 4) {

        } else {
            Write-Error "`"At`" not in correct format"
        }

        $ShutdownHour = $At[0] + $At[1]
        $ShutdownHour = [int]$ShutdownHour
        # $ShutdownHour

        $ShutdownMinute = $At[2] + $At[3]
        $ShutdownMinute = [int]$ShutdownMinute
        # $ShutdownMinute

        if ($ShutdownHour -gt 23 -or $ShutdownMinute -gt 59) {
            Write-Error "Time input not correct"
            break
        }

        $EndTime = Get-Date -Hour $ShutdownHour -Minute $ShutdownMinute -Second 00

        if ($EndTime -lt (Get-Date)) {
            $EndTime = $EndTime.AddDays(1)
        }

    } else {
        $EndTime = (Get-Date).AddSeconds($Seconds)
    }


    $i = 0

    while (($TimeRemaining = ($EndTime - (Get-Date))) -gt 0) {

        if (($EndTime - (Get-Date)).TotalSeconds -lt 5) {
            Stop-ProcessSoft msedge -Silent
            Stop-ProcessSoft -ProcessName chrome -Silent
            Stop-ProcessSoft -ProcessName EXCEL -Silent
        }

        if ($Restart) {
            $ActivityText = "Restarting in..."
        } else {
            $ActivityText = "Shutting down in..."
        }
        Write-Progress -Activity $ActivityText -Status $EndTime -SecondsRemaining $TimeRemaining.TotalSeconds
        Start-Sleep 1

        $i++
        if ($Lock -and ($i -eq 2)) {
            $Users = (quser) -ireplace '\s{2,}', ',' | ConvertFrom-Csv
            if (($Users | Where-Object Username -Match ">").Sessionname -eq "console") {
                Rundll32.exe user32.dll, LockWorkStation
            } else {
                tsdiscon.exe
            }
        }


    }

    if ($Restart) {
        Restart-Computer -Force
    } else {
        Stop-Computer -Force
    }

}


function Start-RDP {
    [CmdletBinding()]
    param (
        [Parameter()] [string] $ComputerName,
        [Parameter()] [int] $Port = 3389,
        [Parameter()] [ValidateSet("1080", "1440", "Fullscreen")] [string] $Resolution = "1440",
        [Parameter()] [ValidateSet("AudioDontPlay", "AudioRemote", "AudioRedirect")] [string] $AudioMode = "AudioRemote",
        [Parameter()] [switch] $NoCredSSP
    )



    $WindowSizes = [PSCustomObject]@{
        1080       = @"
screen mode id:i:1
desktopwidth:i:1917
desktopheight:i:1006

"@


        1440       = @"
screen mode id:i:1
desktopwidth:i:2558
desktopheight:i:1366

"@


        Fullscreen = @"
screen mode id:i:2

"@


    }

    $AudioModes = [PSCustomObject]@{
        AudioDontPlay = @"
audiomode:i:2

"@

        AudioRemote   = @"
audiomode:i:1

"@

        AudioRedirect = @"
audiomode:i:0

"@

    }


    if ($NoCredSSP) {
        $CredSSPContent = @"
enablecredsspsupport:i:0

"@

    } else {
        $CredSSPContent = ""
    }


    if ($ComputerName) {
        $ContentFullAddress = @"
full address:s:$($ComputerName):$($Port)

"@

    } else {
        $ContentFullAddress = @"
full address:s:

"@

    }


    $DefaultRdpFileContent = @"
use multimon:i:0
session bpp:i:32
winposstr:s:0, 3, 0, 0, 800, 600
compression:i:1
keyboardhook:i:1
audiocapturemode:i:0
videoplaybackmode:i:1
connection type:i:7
networkautodetect:i:1
bandwidthautodetect:i:1
displayconnectionbar:i:1
enableworkspacereconnect:i:0
disable wallpaper:i:0
allow font smoothing:i:1
allow desktop composition:i:1
disable full window drag:i:0
disable menu anims:i:0
disable themes:i:0
disable cursor setting:i:0
bitmapcachepersistenable:i:1
redirectprinters:i:0
redirectcomports:i:0
redirectsmartcards:i:1
redirectclipboard:i:1
redirectposdevices:i:0
drivestoredirect:s:
autoreconnection enabled:i:1
authentication level:i:2
prompt for credentials:i:0
negotiate security layer:i:1
remoteapplicationmode:i:0
alternate shell:s:
shell working directory:s:
gatewayhostname:s:
gatewayusagemethod:i:4
gatewaycredentialssource:i:4
gatewayprofileusagemethod:i:0
promptcredentialonce:i:0
gatewaybrokeringtype:i:0
use redirection server name:i:0
rdgiskdcproxy:i:0
kdcproxyname:s:

"@








    $RdpFileContent = $DefaultRdpFileContent + $ContentFullAddress + $WindowSizes.$Resolution + $AudioModes.$AudioMode + $CredSSPContent
    if ($ComputerName) {
        $Outfile = "$($env:TEMP)\$($Computername).rdp"
    } else {
        $Outfile = "$($env:TEMP)\RDP.rdp"
    }

    $RdpFileContent | Out-File $Outfile

    Start-Process $Outfile

    Get-Content $Outfile
    # Remove-Item $Outfile -Force

}



function Stop-ProcessSoft {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string] $ProcessName,
        [Parameter()] [switch] $Silent
    )

    if (!(Get-Process $ProcessName -ErrorAction 0)) {
        if (-not($Silent)) {
            Write-Warning "Process $($ProcessName) not found"
        }
    } else {
        1..100 | ForEach-Object {
            $Process = (Get-Process $ProcessName -ErrorAction 0)
            if ($Process) {
                $Process.CloseMainWindow() | Out-Null
            }
        }
    }

}


$scriptblock = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
    $ps = Get-Process "$wordToComplete*"
    $ps.Name | ForEach-Object {
        if ($_ -match " ") {
            "'$_'"
        } else {
            $_
        }
    }
}
Register-ArgumentCompleter -CommandName Stop-ProcessSoft -ParameterName ProcessName -ScriptBlock $scriptblock



function Sync-GitRepos {
    [CmdletBinding()]
    param (
        [Parameter()] [switch] $Pull,
        [Parameter()] [switch] $RunMaintenance,
        [Parameter()] [switch] $CommitAndPush,
        [Parameter()] [string[]] $GitFolder = @("$($env:USERPROFILE)\Git", "$($env:USERPROFILE)\DevOps")
    )

    $currentLocation = $PWD.Path

    foreach ($gf in $GitFolder) {

        Write-Host "$($gf)" -ForegroundColor Yellow

        if (Test-Path $gf) {

            "---------------------------------"

            Get-ChildItem $gf -Directory | ForEach-Object {

                $GitConfigPath = Join-Path $_.FullName ".git"
                if (Test-Path $GitConfigPath) {
                    Set-Location $_.FullName
                    Write-Host $_.Name -ForegroundColor Green
                    "`n"
                    Write-Host "get all branches and switch to main/master" -ForegroundColor Yellow
                    $Branches = git branch -a
                    if ($Branches -match "main") {
                        git switch main
                    } elseif ($Branches -match "master") {
                        git switch master
                    } else {
                        Write-Warning "Master or main branch not found, leaving branch unchanged"
                    }

                    Write-Host "Fetch all and prune (git fetch --all --prune)" -ForegroundColor Yellow
                    git fetch --all --prune
                    Write-Host "Run git status (git status)" -ForegroundColor Yellow
                    git status
                    Write-Host "Get git branches (git branch -a)" -ForegroundColor Yellow
                    git branch -a

                    if ($Pull) {
                        Write-Host "Git pull" -ForegroundColor Yellow
                        git pull
                    }
                    if ($RunMaintenance) {
                        Write-Host "Run git lfs prune" -ForegroundColor Yellow
                        git lfs prune
                        Write-Host "Run git gc" -ForegroundColor Yellow
                        git gc
                        Write-Host "Run git fsck" -ForegroundColor Yellow
                        git fsck
                    }
                    if ($CommitAndPush) {
                        git add .
                        git commit -a -m 'Commit All'
                        git push
                    }
                    "---------------------------------------------------------------`n"

                }

            }

            Set-Location $gf

        }
    }
    Set-Location $currentLocation

}

function Uninstall-OldInstalledModules {
    [CmdletBinding()]
    param (

    )
    Start-Job -ScriptBlock {
        foreach ($Module in Get-InstalledModule) {
            Get-InstalledModule $Module.Name -AllVersions | Where-Object { $_.Version -ne $Module.Version } | ForEach-Object {
                Write-Output "Uninstalling module $($_.Name) version $($_.Version)"
                Uninstall-Module -Name $_.Name -MaximumVersion $_.Version -Force
            }
        } -ArgumentList $m

    }
}

function Update-InstalledModule {
    [CmdletBinding()]
    param (
    )

    $excludeList = "Az.|Microsoft.Graph.Beta."

    Get-InstalledModule | Where-Object Name -NotMatch $excludeList | ForEach-Object {

        Write-Output $_.Name
        Update-Module $_.Name -AcceptLicense -Scope AllUsers

    }

}

function Update-MyModuleManifest {
    [CmdletBinding()]
    param (
        [Parameter()]
        [ArgumentCompleter( {
                param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters )
                Get-ChildItem "$($env:USERPROFILE)\Git\$wordToComplete*" -Directory -Name | ForEach-Object { $_ } }
        )]
        [string]
        $Module,
        [Parameter()] [ValidateSet("Minor", "Major", "Build")] [string] $VersionChange = "Build"
    )

    if (!($Module)) {
        $PossibleModulename = Get-Item . | Select-Object -ExpandProperty Name
        $ModuleFile = "$PossibleModulename.psd1"
        Write-Verbose "ModuleFile: $ModuleFile"
        if (Test-Path $ModuleFile) {
            $Module = $PossibleModulename
            Write-Verbose "Module: $Module"
        }
    }

    Write-Verbose "Module: $Module"

    $FullPath = Join-Path "$($env:USERPROFILE)\Git" $Module
    Write-Verbose $FullPath
    Write-Verbose "Test-Path $FullPath"
    if (Test-Path $FullPath) {
        $ModuleFolders = Get-Item $FullPath
    } else {
        throw "No module file found"
        # #Set-Location $MyModulePath
        # $MyModulePath = "$($env:USERPROFILE)\Git"

        # if ($Module) {
        # $ModuleFolders = Get-ChildItem $MyModulePath -Directory -Exclude ".git" | Where-Object Name -EQ $Module
        # } else {
        # $ModuleFolders = Get-ChildItem $MyModulePath -Directory -Exclude ".git", "PackageManagement"
        # }
    }


    foreach ($m in $ModuleFolders) {

        Write-Output "Updating module: $($m.BaseName)"
        Write-Verbose $m.FullName

        $FunctionsToExport = (Get-ChildItem (Join-Path $m.FullName -ChildPath "Functions") -File).BaseName

        Get-ChildItem (Join-Path $m.FullName -ChildPath "Functions") -File | Get-Content | Out-File (Join-Path $m.FullName -ChildPath "Functions.ps1") -Force

        $VariablesToExport = @('-')
        if (Test-Path (Join-Path $m.FullName -ChildPath "Variables")) {
            $VariablesToExport = (Get-ChildItem (Join-Path $m.FullName -ChildPath "Variables")).BaseName
        }

        if (Test-Path (Join-Path $m.FullName -ChildPath "Other\RequiredModules.csv")) {
            $RequiredModules = Import-Csv (Join-Path $m.FullName -ChildPath "Other\RequiredModules.csv") | Select-Object -ExpandProperty Modulename
        } else {
            $RequiredModules = @()
        }

        if (Test-Path (Join-Path $m.FullName -ChildPath "Other\ModuleDescription.txt")) {
            $ModuleDescription = Get-Content (Join-Path $m.FullName -ChildPath "Other\ModuleDescription.txt")
        } else {
            $ModuleDescription = $m.BaseName
        }

        if (Test-Path (Join-Path $m.FullName -ChildPath ($m.BaseName + ".psd1"))) {
            $ModuleInfo = Get-Module $m.FullName -ListAvailable
            if ($VersionChange -eq "Major") {
                $CurrentVersion = $ModuleInfo.Version.Major
                $NewVersion = $CurrentVersion + 1
                $NewVersion = "$($NewVersion).0.0"
            } elseif ($VersionChange -eq "Minor") {
                $CurrentVersion = $ModuleInfo.Version.Minor
                $NewVersion = $CurrentVersion + 1
                $NewVersion = "$($ModuleInfo.Version.Major).$($NewVersion).0"
            } elseif ($VersionChange -eq "Build") {
                $CurrentVersion = $ModuleInfo.Version.Build
                $NewVersion = $CurrentVersion + 1
                $NewVersion = "$($ModuleInfo.Version.Major).$($ModuleInfo.Version.Minor).$NewVersion"
            }
        } else {

            $NewVersion = "0.0.1"

        }

        $ModuleManifestParameters = @{
            Path              = (Join-Path $m.FullName -ChildPath ($m.BaseName + ".psd1"))
            RootModule        = $m.BaseName + ".psm1"
            ModuleVersion     = $NewVersion
            FunctionsToExport = $FunctionsToExport
            VariablesToExport = $VariablesToExport
            Copyright         = "(c) $((Get-Date).Year) JT. All rights reserved."
        }
        if ($RequiredModules) {
            $ModuleManifestParameters.Add("RequiredModules", $RequiredModules)
        }
        if ($ModuleDescription) {
            $ModuleManifestParameters.Add("Description", $ModuleDescription)
        }

        #$ModuleManifestParameters


        if (Test-Path $ModuleManifestParameters.Path) {
            Update-ModuleManifest @ModuleManifestParameters
        } else {

            $psmContent = @"
(Get-ChildItem "`$PSScriptRoot\Functions") | ForEach-Object {
    . `$_.FullName
}
"@

            $psmContent | Out-File (Join-Path $m.FullName -ChildPath ($m.BaseName + ".psm1"))

            New-ModuleManifest @ModuleManifestParameters

        }


        if (Test-Path (Join-Path $m.FullName ".git")) {
            $CurrentLocation = Get-Location

            Set-Location $m.FullName
            # $m.FullName
            Write-Host "$($m.BaseName).psd1"
            git add ".\$($m.BaseName).psd1"
            git commit -i ".\$($m.BaseName).psd1" -m "Version update"

            Set-Location $CurrentLocation

        }

    }

    Test-ModuleManifest $ModuleManifestParameters.Path | Format-List
    $ModuleManifestParameters | Format-Table

}