Windowsアップデートの停止方法について

# やりたいこと（余談）
![image (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/a2957f67-34fa-14a7-323d-844289e46be0.png)


従来のツールやネット記事の方法通りにやっても
再起動後やシャットダウン後、数日後にはまた勝手に元に戻ってしまう
Windowsアップデートを**完全に停止**させてみたいと思います。

Windowsアップデートを停止したい理由は様々です。
重たくなったり、余計なプログラムのインストールでバグを引き起こしたりする
ということで自分でインストールする時まで止めたい人は多いと思います。

レジストリや
グループポリシー
タスクスケジューラや
サービス管理ウインドウ
フリーのツールや
ファイヤーウォール
CMDやパワーシェルコマンドなど

様々な方法を試したけど全然だめだった、て人は多いと思いますが

今回はそのWindowsアップデートを
今のところ再帰せず完全に止められたお話をさせて頂きます。

---
:::note warn
従来の方法で止められなかった主な理由としては「アクセス拒否をする」という手順がほとんどの記事で触れられていない点が主な原因です。

（少なくても自分の場合はそれでした）
:::
# 作業をする前に ！！

今回実行に使うのは

・パワーシェル
・スクリプト

＜確認用に＞
・サービス管理ウインドウ
・レジストリ

計４つのみ
スクリプトは私からご用意させていただきます。

なので皆さんにやってもらう作業は
以下の三つの単純作業だけで済みます。

・コピペ
・実行
・確認

:::note alert
ここからは自己責任で進めてください ⚠

レジストリはWindowsの本体と言っても過言ではありません。
値の戻し方やバックアップの取り方が分からない人は触らないでください！！

また、なにかあった時のためにバックアップを取ることを強くお勧めします。
:::

PowerShellからREGで
Windowsアップデートを停止させる
---

**※ここではレジストリのことをREGと略しています。**

スクリプトの実行内容は以下の通りです。

・`サービス管理ウインドウ上で動いているWindowsアップデートの値をREGで無効にすること`
（Windowsアップデートの値の無効化）
・`REG上にあるWinUpの親とサブキーの所有者をSYSTEMからAdministartorsに変更`
（アクセス許可の操作）
・`親とサブキーにアクセスするオブジェクトのアクセスを拒否に登録`
（アクセス許可の操作）

大きくこの３つです。
細かく砕くと長くなるので割愛します。
詳しく知りたい方はコードを分析してください。

それでは、スクリプトをコピーしてPowerShellで実行しましょう。
```Powershell. or ps1ファイルの内容

# WindowsUpdateキーが存在しない場合は作成
if (-not (Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate")) {
    New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\" -Name "WindowsUpdate" -Force
}

# AUキーを作成
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\" -Name "AU" -Force

# NoAutoUpdate DWORD値を作成して値を設定
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Value 1 -PropertyType DWORD -Force


# ーーーーーーー

# Windows Update サービスを無効にする
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv" -Name "Start" -Value 4

# Windows Update Medic Service を無効にする
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc" -Name "Start" -Value 4




@"
ーーーーー
上記のスクリプトは値の変更を行い
下記のスクリプトは、アクセス許可の変更を行います。
ーー
下記について、

指定された親レジストリキーの所有者をAdministratorsに変更し
サブキーにも同様に変更される処理を加えてます。

次に、親キーにアクセスできる２つのオブジェクトを拒否します。

拒否するオブジェクトは以下の２つです。
＞SYSTEM
＞ALL APPCLICATION PACKAGES
これをサブキーにも割り当てるようにします。

ーーーーー
"@



# レジストリキーのパスとサブキーの名前
$keyPaths = @{
    "HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv" = "wuauserv"
    "HKLM:\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc" = "WaaSMedicSvc"
}

# 指定されたレジストリキーの所有者とアクセス許可を一覧表示
foreach ($keyPath in $keyPaths.GetEnumerator()) {
    Write-Host ""
    Write-Host $keyPath.Key
    Write-Host "＞所有者：" (Get-Acl -Path $keyPath.Key).Owner
    Write-Host ""
    Write-Host "拒否："
    $acl = Get-Acl -Path $keyPath.Key
    $acl.Access | Where-Object { $_.AccessControlType -eq 'Deny' } | ForEach-Object {
        Write-Host "  $($_.IdentityReference)"
    }
    Write-Host ""
    Write-Host "許可："
    $acl.Access | Where-Object { $_.AccessControlType -eq 'Allow' } | ForEach-Object {
        Write-Host "  $($_.IdentityReference)"
    }
    Write-Host "ー　ー　ー　ー　ー"
    Write-Host ""

    Write-Host "$($keyPath.Value)のサブキを一覧で表示"
    Write-Host ""
    Get-ChildItem -Path $keyPath.Key | ForEach-Object {
        Write-Host "\$($keyPath.Value)\$($_.Name)"
    }
    Write-Host "ーーーーーーーーーーーーーーーーーーーーーーーーーーー"
}

# ユーザー確認
$confirmation = Read-Host "親とサブキーの所有者を Administrators に変更しますか？ (Y/N)"

if ($confirmation -eq "Y" -or $confirmation -eq "y") {
    # 変更したいレジストリキーのパス
    $keyPaths = @(
        "HKLM:\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc",
        "HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv"
    )

    # 指定されたレジストリキーの所有者を Administrators に変更する
    foreach ($keyPath in $keyPaths) {
        $acl = Get-Acl -Path $keyPath
        $administrators = New-Object System.Security.Principal.NTAccount("Administrators")
        $acl.SetOwner($administrators)
        Set-Acl -Path $keyPath -AclObject $acl

        # 親キーに対しても拒否設定を追加
        $acl = Get-Acl -Path $keyPath
        $deniedUsers = @("SYSTEM", "ALL APPLICATION PACKAGES")
        $deniedUsers | ForEach-Object {
            $identity = New-Object System.Security.Principal.NTAccount($_)
            $accessRule = New-Object System.Security.AccessControl.RegistryAccessRule($identity, "FullControl", "Deny")
            $acl.AddAccessRule($accessRule)
        }
        Set-Acl -Path $keyPath -AclObject $acl

        # 親キーの所有者をサブキーに割り当てる
        # 親キーの所有者を取得
        $parentOwner = New-Object System.Security.Principal.NTAccount("Administrators")

        # サブキーの一覧を取得
        $subKeys = Get-ChildItem -Path $keyPath

        # サブキーの所有者を親キーの所有者に設定
        foreach ($subKey in $subKeys) {
            $acl = Get-Acl -Path $subKey.PSPath
            $acl.SetOwner($parentOwner)
            Set-Acl -Path $subKey.PSPath -AclObject $acl
        }
    }

Write-Host "
親とサブキーの所有者を Administrators に変更しました。"

    # 親キーのオブジェクトを拒否にします。
    Write-Host "
次に、親キーの以下のオブジェクトを拒否にし"
    Write-Host "＞SYSTEM"
    Write-Host "＞ALL APPLICATION PACKAGES"

    # ユーザーに確認を求める
    $confirmation = Read-Host "サブキーにも同じ変更を適用しますか？(Y/N)"

    if ($confirmation -eq "Y" -or $confirmation -eq "y") {
        # サブキーにも同じ変更を適用
        foreach ($keyPath in $keyPaths) {
            # サブキーの一覧を取得
            $subKeys = Get-ChildItem -Path $keyPath

            # サブキーの所有者を親キーの所有者に設定
            foreach ($subKey in $subKeys) {
                $acl = Get-Acl -Path $subKey.PSPath
                
                # 拒否設定を追加
                foreach ($user in $deniedUsers) {
                    $identity = New-Object System.Security.Principal.NTAccount($user)
                    $accessRule = New-Object System.Security.AccessControl.RegistryAccessRule($identity, "FullControl", "Deny")
                    $acl.AddAccessRule($accessRule)
                }

                # 所有者を設定
                $acl.SetOwner($parentOwner)
                
                # ACLを設定
                Set-Acl -Path $subKey.PSPath -AclObject $acl
            }
        }
    }
}

# レジストリキーのパスとサブキーの名前
$keyPaths = @{
    "HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv" = "wuauserv"
    "HKLM:\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc" = "WaaSMedicSvc"
}

# 指定されたレジストリキーの所有者とアクセス許可を一覧表示
foreach ($keyPath in $keyPaths.GetEnumerator()) {
    Write-Host ""
    Write-Host $keyPath.Key
    Write-Host "＞所有者：" (Get-Acl -Path $keyPath.Key).Owner
    Write-Host ""
    Write-Host "拒否："
    $acl = Get-Acl -Path $keyPath.Key
    $acl.Access | Where-Object { $_.AccessControlType -eq 'Deny' } | ForEach-Object {
        Write-Host "  $($_.IdentityReference)"
    }
    Write-Host ""
    Write-Host "許可："
    $acl.Access | Where-Object { $_.AccessControlType -eq 'Allow' } | ForEach-Object {
        Write-Host "  $($_.IdentityReference)"
    }
    Write-Host "ー　ー　ー　ー　ー"
    Write-Host ""

    Write-Host "$($keyPath.Value)のサブキを一覧で表示"
    Write-Host ""
    Get-ChildItem -Path $keyPath.Key | ForEach-Object {
        Write-Host "\$($keyPath.Value)\$($_.Name)"
    }
    Write-Host "ーーーーーーーーーーーーーーーーーーーーーーーーーーー"
}

```
ここから実行に移ります。まずは

Powershellを管理者権限で開き
スクリプトをコピペしてエンターキーを押してください。

:::note info
PowerShellの開き方がわからない人へ。

Winキー　＋　Sキー　で検索欄が開きます。
「PowerShell」と入力して


Ctrlキー　＋　Shiftキー　を押しながら　Enterキー　を押してください。
※　右クリック「管理者権限で開く」でも大丈夫です。

開いたら、先ほどのスクリプトをコピーして
PowerShellの画面に戻ってペーストしてエンターキーを押してください。
:::

すると、以下のものが表示されます。

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/03a68b15-7f3e-563b-c749-a5d7c73c44cb.png)

:::note warn
赤い部分に注目してください。
:::
所有者はデフォルトでは、SYSTEM（システム）であり
オブジェクトがまだ拒否されていないことが分かります。

**※上記の写真で表示されているのは、親キーの詳細のみです。
サブキーの詳細及び、サブキーの所有者と
オブジェクトの拒否・許可の有無については
直接REGの画面（レジストリ）から確認してください。**

:::note info
確認が終わりましたら

`親とサブキーの所有者を Administrators に変更しますか？ (Y/N)`

という案内が出てるので案内通りにYキーを押して行き
その後に続く案内にも同様にYキーを選択してください。
:::


実行後以下のように書き換わっているか確認してください。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/a08fb23e-35e4-40fb-dc80-8632d581e54b.png)

SYSTEM　が　**Administartors**　に書き変わり、
**拒否の部分に　SYSTEM　と　APPLICATION　が入っていれば成功です。**

---
念のためREGやサービス管理ウインドウで
値や項目が無効もしくは消えているか確認します。

:::note info
レジストリとサービス管理画面の表示の仕方

先ほどと同じようにWindowsの検索欄に
「レジストリ」もしくは「REG」
「サービス」もしくは「Services.msc」

と入力して開いてください(´・ω・｀)
:::

### サービス管理画面
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/29dd2b4d-fc2e-85fa-8bc2-76cd2eea08cb.png)

![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/ceef5f09-2ef1-e2a0-1fc9-2182e4ece57d.png)

ちゃんとアプリからのアクセスも拒否されていますね。

---
### レジストリの画面
それぞれのキーのパス
＞HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv
＞HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc

**Startに割り当てられている値を確認する**

![image (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/e7fe1be1-1e05-81ad-8a76-03878887bacc.png)

![image (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/cf26d794-75bf-aa4b-e924-406b6f0e1d8c.png)


REGの場合、デフォルトは３（有効）であり
値が４（無効）になっていれば成功です。

再起動して、項目が消えていることを確認
-----
![image (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752525/b362e0c0-4493-e260-9f54-e2578e1a5ade.png)

ネットに接続している状態で5分以上経過しても
REGやサービス管理ウインドウで値や項目が
元に戻っていなければ今後勝手に戻ることは、まずないと思います。

:::note warn
元に戻したい場合は、手動でREGの操作を行うか
自己で戻すスクリプトを書いて戻してください。
:::

お疲れ様です。
-----
再起動してWindowsアップデートがもとに戻っていなければ、
今後しばらくは大丈夫だと思ます。

念の為言っておきますが
なにかがきっかけで戻される可能性があります。
１００％セント保証するものではないのでご自愛ください。

また、繰り返しますが
本記事によって行った作業で不具合が生じた場合
責任は一切負いかねますので自己責任でお願い致します。