View/2-ApplySettings.ps1

[Flags()]Enum MSFT_ScheduledTaskDaysOfWeek{
    Sunday = 1
    Monday = 2
    Tuesday = 4
    Wednesday = 8
    Thursday = 16
    Friday = 32
    Saturday = 64
}
[Flags()]Enum MSFT_ScheduledTaskWeeksOfMonth{
    First = 1
    Second = 2
    Third = 4
    Fourth = 8
}
[Flags()]Enum MSFT_ScheduledTaskTrigger{
    Event = 0
    Time = 1
    Daily = 2
    Weekly = 3
    Monthly = 4
    MonthlyDayOfWeek = 5
    Idle = 6
    Registration = 7
    Boot = 8
    Logon = 9
    SessionStateChange = 11
    CustomTrigger01 = 12
}
[Flags()]Enum MSFT_TaskCreation{
    ValidateOnly = 1
    Create = 2
    Update = 4
    CreateOrUpdate = 6
    Disable = 8
    DontAddPrincipalAce = 16
    IgnoreRegistrationTriggers = 32
}
[Flags()]Enum MSFT_TaskLogonType{
    LogonNone = 0
    LogonPassword = 1
    LogonS4u = 2
    LogonInteractiveToken = 3
    LogonGroup = 4
    LogonServiceAccount = 5
    LogonInteractiveTokenOrPassword = 6
}
[Flags()]Enum MSFT_TaskMonthlyTriggerMonthsOfYear{
    January = 1
    February = 2
    March = 4
    April = 8
    May = 16
    June = 32
    July = 64
    August = 128
    September = 256
    October = 512
    November = 1024
    December = 2048
}

Function Global:Set-MainWindowSettings{
    Function Set-ValueWsusPool($ItemName, $DisplayName, $NewValue){
        $BeforeValue = (Get-ItemProperty $CurrentConfig.Wsus.IisWsusPoolPath -Name $ItemName).Value
        Set-ItemProperty $CurrentConfig.Wsus.IisWsusPoolPath -Name ([System.String]$ItemName) -Value $NewValue
        $AfterValue = (Get-ItemProperty $CurrentConfig.Wsus.IisWsusPoolPath -Name $ItemName).Value
        Write-Verbose "$($DisplayName): (変更前: $BeforeValue, 変更後: $AfterValue)"
    }
    Function Get-SqlMinimumMemorySize{
        $SqlQueryPath = "Assets\Get-SqlMinimumMemorySize.sql"
    }
    Function Set-SqlMinimumMemorySize($MinimumMemorySize){
        $SqlQueryPath = (Join-Path (Get-ProgramDataDirectory) "Assets\Set-SqlMinimumMemorySize.sql")
        (Get-Content "Assets\Set-SqlMinimumMemorySize.sql.txt" -Encoding UTF8).Replace("{Value}", $MinimumMemorySize) | Out-File  -Encoding UTF8
        If ($Config.MaintenanceSql.SqlCmdExeMode -eq "psmodule"){
            Invoke-Sqlcmd -ServerInstance "np:\\.\pipe\Microsoft##WID\tsql\query" -InputFile $SqlQueryPath
        }
        Else{
            Start-Process 
        }
    }
    Write-Verbose "選択された構成を確認しています..."

    # Options
    If ([String]::IsNullOrEmpty($CurrentConfig.MaintenanceSql.SqlCmdPath)){
        Write-Verbose "[削除] CurrentConfig.MaintenanceSql.SqlCmdPath が空です"
        $Global:CurrentConfig.MaintenanceSql.PsObject.Members.Remove("SqlCmdPath")
    }
    ElseIf (-not (Test-Path $CurrentConfig.MaintenanceSql.SqlCmdPath)){
        Write-Verbose "[削除] CurrentConfig.MaintenanceSql.SqlCmdPath $($CurrentConfig.MaintenanceSql.SqlCmdPath) が見つかりません"
        $Global:CurrentConfig.MaintenanceSql.PsObject.Members.Remove("SqlCmdPath")
    }
    
    # ChooseProducts
    $Global:CurrentConfig.ChooseProducts."Windows 11" = $Windows11Products | Sort-Object Version -Unique | Select-Object Version, @{Name="arm64";Expression={$_.SelectedArm64}}, @{Name="x64";Expression={$_.SelectedX64}}
    $Global:CurrentConfig.ChooseProducts."Windows 10" = $Windows10Products | Sort-Object Version -Unique | Select-Object Version, @{Name="arm64";Expression={$_.SelectedArm64}}, @{Name="x64";Expression={$_.SelectedX64}}, @{Name="x86";Expression={$_.SelectedX86}}
    $Global:CurrentConfig.ChooseProducts."Windows 8.1".x86 = $MainWindow.FindName("SynWindowsChooseWindows81x86CheckBox").IsChecked
    $Global:CurrentConfig.ChooseProducts."Windows 8.1".x64 = $MainWindow.FindName("SynWindowsChooseWindows81x64CheckBox").IsChecked
    $Global:CurrentConfig.ChooseProducts."Microsoft Edge".x86 = $MainWindow.FindName("SynWindowsChooseMsEdgeX86CheckBox").IsChecked
    $Global:CurrentConfig.ChooseProducts."Microsoft Edge".x64 = $MainWindow.FindName("SynWindowsChooseMsEdgeX64CheckBox").IsChecked
    $Global:CurrentConfig.ChooseProducts."Microsoft Edge".arm64 = $MainWindow.FindName("SynWindowsChooseMsEdgeArm64CheckBox").IsChecked

    # ApproveRule
    $Global:CurrentConfig.ApproveRule = ($MainWindow.FindName("ApproveRuleList").DataContext | Select-Object "FeatureUpdates", "QualityUpdates", "ApproveWaitDays", "TargetGroupName", "TargetGroupNameDisplayText", "ToStringWithoutTargetGroupName")
    $MainWindow.FindName("ApproveRuleList").DataContext | ForEach-Object{
        Write-Verbose "-> $($_.TargetGroupName): [QualityUpdates:$($_.QualityUpdates)], [ApproveWaitDays:$($_.ApproveWaitDays)]"
    }

    $CurrentConfig | ConvertTo-Json -Depth 10 | Out-File -FilePath (Join-Path (Get-ProgramDataDirectory) "Config.json") -Encoding UTF8

    # Schedule
    If ($MainWindow.FindName("EditiingScheduleTriggersCheckBox").IsChecked){
        Write-Verbose "EditiingScheduleTriggersCheckBox is checked."
        $Schedule = $MainWindow.FindName("ScheduleTab").DataContext

        $DaysOfWeek = 0
        $WeeksOfMonth = 0

        # Weekly
        If ($Schedule.Sunday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Sunday}
        If ($Schedule.Monday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Monday}
        If ($Schedule.Tuesday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Tuesday}
        If ($Schedule.Wednesday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Wednesday}
        If ($Schedule.Thursday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Thursday}
        If ($Schedule.Friday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Friday}
        If ($Schedule.Saturday){$DaysOfWeek += [MSFT_ScheduledTaskDaysOfWeek]::Saturday}
   
        If ($Schedule.First -and $Schedule.Second -and $Schedule.Third -and $Schedule.Fourth -and $Schedule.Last){
            $Schedule.First = $False
            $Schedule.Second = $False
            $Schedule.Third = $False
            $Schedule.Fourth = $False
            $Schedule.Last = $False

            $Schedule.LoadedWeeksOfMonth = $False
            Write-Verbose "-> switch to weekly mode."
        }
        ElseIf ($Schedule.First -or $Schedule.Second -or $Schedule.Third -or $Schedule.Fourth -or $Schedule.Last){
            # Monthly
            If ($Schedule.First){$WeeksOfMonth += [MSFT_ScheduledTaskWeeksOfMonth]::First}
            If ($Schedule.Second){$WeeksOfMonth += [MSFT_ScheduledTaskWeeksOfMonth]::Second}
            If ($Schedule.Third){$WeeksOfMonth += [MSFT_ScheduledTaskWeeksOfMonth]::Third}
            If ($Schedule.Fourth){$WeeksOfMonth += [MSFT_ScheduledTaskWeeksOfMonth]::Fourth}
            If ($Schedule.Last){$WeeksOfMonth += [MSFT_ScheduledTaskWeeksOfMonth]::Last}

            $Schedule.LoadedWeeksOfMonth = $True
            Write-Verbose ([String]::Format("-> switch to Montyhly mode. First:{0}, Second:{1}, Third:{2}, Fourth:{3}, Last:{4}", $Schedule.First, $Schedule.Second, $Schedule.Third, $Schedule.Fourth, $Schedule.Last))
        }
        Else {
            $Schedule.LoadedWeeksOfMonth = $False
            Write-Verbose "-> switch to weekly mode."
        }

        $ScheduleService = New-Object -ComObject Schedule.Service
        $ScheduleService.Connect()

        $ScheduleTask = $ScheduleService.NewTask(0)
        $ScheduleTask.RegistrationInfo.Description = "Optimize-WsusContents"
        $ScheduleTask.RegistrationInfo.Author = "Wsustainable"
        $ScheduleTask.Settings.Enabled = $True
        #$ScheduleTask.Settings.AllowDemandStart = $True
        $ScheduleTask.Settings.WakeToRun = $True

        $ScheduleTask.Principal.UserId = "System"
        $ScheduleTask.Principal.RunLevel = 1 #TASK_RUNLEVEL_HIGHEST

        $ScheduleTaskAction = $ScheduleTask.Actions.Create(0)
        $ScheduleTaskAction.Path = "%WinDir%\system32\WindowsPowerShell\v1.0\powershell.exe"
        $ScheduleTaskAction.Arguments = ("-ExecutionPolicy ByPass -Command ""Import-Module Wsustainable; Optimize-WsusContents -ConfigFileName " + "'" + "$(Join-Path (Get-ProgramDataDirectory) "Config.json")'""")

        If ($Schedule.LoadedWeeksOfMonth){
            $ScheduleTaskTrigger = $ScheduleTask.Triggers.Create([MSFT_ScheduledTaskTrigger]::MonthlyDayOfWeek)
            $ScheduleTaskTrigger.DaysOfWeek = $DaysOfWeek
            $ScheduleTaskTrigger.MonthsOfYear = 4095
            $ScheduleTaskTrigger.WeeksOfMonth = $WeeksOfMonth
        }
        ElseIf ($Schedule.Sunday -and $Schedule.Monday -and $Schedule.Tuesday -and $Schedule.Wednesday -and $Schedule.Thursday -and $Schedule.Friday -and $Schedule.Saturday){
            $ScheduleTaskTrigger = $ScheduleTask.Triggers.Create([MSFT_ScheduledTaskTrigger]::Daily)
        }
        ElseIf ($Schedule.Sunday -or $Schedule.Monday -or $Schedule.Tuesday -or $Schedule.Wednesday -or $Schedule.Thursday -or $Schedule.Friday -or $Schedule.Saturday){
            $ScheduleTaskTrigger = $ScheduleTask.Triggers.Create([MSFT_ScheduledTaskTrigger]::Weekly)
            $ScheduleTaskTrigger.DaysOfWeek = $DaysOfWeek
        }
        Else{
            $ScheduleTaskTrigger = $ScheduleTask.Triggers.Create([MSFT_ScheduledTaskTrigger]::Daily)
        }
        
        $ScheduleTaskTrigger.StartBoundary = (Get-Date $MainWindow.FindName("WeeklyScheduleDateTimePicker").Value -Format s)
        Write-Verbose "-> Time: $($ScheduleTaskTrigger.StartBoundary)"
        #$ScheduleTaskTrigger.Enabled = $True

        $ScheduleService.GetFolder("\").RegisterTaskDefinition("Optimize-WsusContents", $ScheduleTask, [MSFT_TaskCreation]::CreateOrUpdate,"","",[MSFT_TaskLogonType]::LogonServiceAccount)

        If ($StartTask){
            Start-ScheduledTask -TaskName $TaskName
        }
    }

    # IIS
    If (Test-IisWsusPoolPath){
        Write-Verbose "IIS Wsus pool:"
        Set-ValueWsusPool "queueLength" "(全般)\キューの長さ" $MainWindow.FindName("WsusQueueLengthTextBox").Value
        ##要修正 Set-ValueWsusPool "ApplicationPoolCpu.Limit" "CPU\制限 (%)" $MainWindow.FindName("WsusCpuLimitTextBox").Value
        
        Set-ValueWsusPool "Failure.RapidFailProtectionInterval" "ラピッド フェール保護\エラー間隔 (分)" $MainWindow.FindName("WsusRapidFailProtectionIntervalTextBox").Value
        Set-ValueWsusPool "Failure.RapidFailProtectionMaxCrashes" "ラピッド フェール保護\最大エラー数" $MainWindow.FindName("WsusRapidFailProtectionMaxCrashesTextBox").Value
        #Set-ValueWsusPool "processModel.idleTimeout" "プロセスモデル\アイドル状態のタイムアウト" $MainWindow.FindName("WsusIdleTimeoutTextBox").Value
        #Set-ValueWsusPool "processModel.pingingEnabled" "プロセスモデル\Pingの有効化" $MainWindow.FindName("WsusPingingEnabledCheckBox").IsChecked
        #Set-ValueWsusPool "recycling.periodicRestart.time" "リサイクル\定期的な期間" $MainWindow.FindName("WsusPeriodicRestartTimeTextBox").Value
        Set-ValueWsusPool "recycling.periodicRestart.privateMemory" "リサイクル\プライベートメモリ制限" $MainWindow.FindName("WsusPeriodicRestartPrivateMemoryTextBox").Value
        Set-ValueWsusPool "recycling.periodicRestart.Memory" "リサイクル\仮想メモリ制限 (KB)" $MainWindow.FindName("WsusPeriodicRestartMemoryTextBox").Value
    }

    # Componetns
    If ($MainWindow.FindName("ComponentsListView").IsEnabled){
        $MainWindow.FindName("ComponentsListView").DataContext | Where-Object {-not $_.Installed -and $_.IsSelected} | ForEach-Object{
            If ($_.Type -eq "WindowsFeature"){
                Try{
                    Install-WindowsFeature $_.WindowsFeatureName -IncludeManagementTools
                }
                Catch{
                    Write-Warning "[$($Component.DisplayName)] インストールできませんでした: $($_.Exception.Message)"
                }
            }
            Else{
                Invoke-SilentInstall $_
            }
        }
    }

}