Supprimer définitivement et de force OneDrive pour tous les utilisateurs sous Windows 11 via PowerShell

Tout d’abord, un peu de contexte :

Je prépare environ 20 ordinateurs portables pour un programme éducatif en prison. Cet environnement présente des défis… particuliers. L’un d’eux est que les étudiants (détenus) ne sont en aucun cas autorisés à avoir quoi que ce soit ressemblant de près ou de loin à un accès de messagerie électronique.

Cela signifie qu’ils ne peuvent pas avoir de comptes Microsoft du tout et n’auront pas accès à un domaine AD ou à Entra Identity ; seuls les comptes locaux conviennent (et la suppression des notifications de compte MS fera l’objet d’une question séparée), et la gestion par stratégie de groupe/System Center/Intune/autre MDM est exclue.

Cela signifie également qu’ils ne peuvent pas avoir OneDrive sur l’ordinateur. Si un étudiant parvenait à ouvrir OneDrive et à le connecter, il pourrait l’utiliser pour créer un dossier partagé avec quelqu’un à l’extérieur de la prison et échanger des messages en déposant des fichiers texte.

Oui, nous devons vraiment être aussi prudents, et découvrir après coup que nous n’avons pas réussi implique le genre de sanctions auxquelles je préfère ne pas penser.

De plus, peu importe que le service OneDrive soit bloqué sur le réseau de la prison. Les machines seront inspectées avant la livraison, et d’après ce que j’ai compris en discutant avec d’autres organisations, la présence d’OneDrive leur ferait échouer l’inspection.

Un autre aspect de la situation est qu’il n’y a pas de véritable support technique sur place. D’après ce que je comprends actuellement (ce qui pourrait encore être faux), le coordinateur éducatif de la prison reçoit un compte administrateur local et des instructions détaillées sur la façon d’ouvrir Gestion de l’ordinateur et de créer un nouvel utilisateur local avec un mot de passe distinct pour chaque étudiant (également connu du coordinateur). J’ai donc besoin que cela fonctionne comme l’expérience par défaut pour les nouveaux utilisateurs.

Encore une fois, j’ai un lot de ces machines, avec la possibilité d’en ajouter d’autres à l’avenir. Je sais que je pars toujours d’une installation Windows propre/neuve, et pour l’instant elles sont toutes de la même marque/modèle. Mais je sais aussi qu’il est peu probable que le prochain lot soit de la même marque, donc je ne peux pas compter sur des systèmes identiques. Ce n’est pas la seule chose particulière que je dois faire pour ces machines, donc j’aimerais vraiment que ce soit scriptable, afin que le processus soit reproductible.

En résumé (trop tard), je suis très motivé pour m’assurer que OneDrive est vraiment totalement supprimé de ces systèmes de manière reproductible ; il est probable que je fasse même exécuter le script final chaque nuit comme tâche planifiée, pour protéger contre une réinstallation accidentelle. Cela doit vraiment fonctionner pour tous les utilisateurs, y compris ceux qui ne sont pas encore créés, et c’est bien plus que le classique « Je n’aime pas OneDrive, pourquoi dois-je le supporter ? ».

Voici ce que j’ai jusqu’ici :

# Make sure OneDrive isn't later changed to be a Windows Store app
Get-AppxPackage -AllUsers "*OneDrive*" | Remove-AppxPackage -AllUsers

# But really OneDrive uses any of five possible locations:
# Windows\System, Windows\System32, Windows\SysWOW64, Program Files, and Program Files (x86)
# Need to check all five
if (Test-Path "C:\Windows\System\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\System\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}
if (Test-Path "C:\Windows\System32\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\System32\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}
if (Test-Path "C:\Windows\SysWOW64\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\SysWOW64\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}

# Program Files locations also have a version number subfolder that may change over time
if (Test-path "C:\Program Files\Microsoft OneDrive") {
    $folder = (get-childitem "C:\Program Files\Microsoft OneDrive").Name | ?{ $_ -match "^\d{2}.*" }
    # can be several folders. Only one will have the uninstaller
    $folder | % {
        if (Test-Path "C:\Program Files\Microsoft OneDrive\$_\OneDriveSetup.exe") {
           $path = "C:\Program Files\Microsoft OneDrive\$_\OneDriveSetup.exe"
            start -wait -filepath $path -argumentlist "/uninstall","/qn"
        }
    }
}
if (Test-path "C:\Program Files (x86)\Microsoft OneDrive") {
    $folder = (get-childitem "C:\Program Files (x86)\Microsoft OneDrive").Name | ?{ $_ -match "^\d{2}.*" }
    # can be several folders. Only one will have the uninstaller
    $folder | % {
        if (Test-Path "C:\Program Files (x86)\Microsoft OneDrive\$_\OneDriveSetup.exe") {
           $path = "C:\Program Files (x86)\Microsoft OneDrive\$_\OneDriveSetup.exe"
            start -wait -filepath $path -argumentlist "/uninstall","/qn"
        }
    }
}

# Also look in WinSXS
$ods = get-childitem "C:\Windows\WinSxS\amd64_microsoft-windows-onedrive-setup*"
if ($ods) {
    $path = "C:\Windows\WinSxS\$($ods.Name)\*.*"
    # Don't need to uninstall; just remove files. But also need to take ownership first
    takeown /F $path /A | Out-Null
    icacls $path /grant Administrators:M | Out-Null
    remove-item -path $path -force
}

J’inclus ce script pour montrer ce qui est déjà fait, et non parce que j’ai besoin d’aide avec le code (et c’est pourquoi je suis ici sur Super User plutôt que sur Stack Overflow).

J’ai également la possibilité, ailleurs dans mon script, d’ajouter facilement des modifications à la ruche de registre du profil utilisateur par défaut et à la machine locale :

reg load HKU\default c:\users\default\ntuser.dat
reg import .\DefaultRegistryFixes.reg
reg unload HKU\default

Le résultat est que tout ce qui se trouve dans le fichier DefaultRegistryFixes.reg peut référencer HKEY_USERS\default et sera écrit dans les paramètres de registre attribués aux nouveaux utilisateurs. Le fichier contient actuellement environ 40 modifications de registre. Rien n’y concerne encore OneDrive, car j’ai vraiment besoin qu’OneDrive soit entièrement supprimé, et pas seulement désactivé. Cependant, tout ce que je peux faire ici pour également désactiver OneDrive est bon, car je veux en plus me protéger contre une mise à jour système qui remettrait OneDrive sur l’ordinateur, et si une modification de registre est le seul moyen d’empêcher son exécution pour un nouvel utilisateur, je suis prêt.

Et maintenant, finalement, mon problème :

Après tout cela, je vois qu’OneDrive a disparu du compte administrateur initial que j’utilise pour exécuter le script. Mais si je crée ensuite un nouvel utilisateur local et que je me connecte, je vois OneDrive en cours d’exécution dans la zone de notification. Le Gestionnaire des tâches montre que le fichier .exe se trouve dans le dossier App Data de cet utilisateur (tout neuf).

Que me manque-t-il pour qu’OneDrive soit encore en cours d’exécution sur le système lorsque j’ajoute un nouvel utilisateur, même après l’avoir supprimé de tous ces emplacements ? Et comment puis-je le supprimer définitivement une bonne fois pour toutes ?

J’ai maintenant les choses en place pour que je pense qu’OneDrive est entièrement supprimé à l’aide d’un script et d’un fichier reg. Le script :

Write-Host "Removing OneDrive"

# First make our registry tweaks. To do this, we need the default user's hive loaded
reg load HKU\default c:\users\default\ntuser.dat

# Now, before importing changes, look for the OneDrive Personal installer location (we'll need it later) 
#  Also, KHU isn't available by default, so check that, too
if ((Get-PSDrive -PSProvider Registry).Name -notcontains 'HKU') {
    New-PSDrive HKU Registry HKEY_USERS | Out-Null
    $removeHKU = $true
}
$odp = (Get-ItemProperty -path 'HKU:\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Run').OneDriveSetup
if ($removeHKU) {
    Remove-PSDrive -Name "HKU"
}

# Import our registry changes
# This removes the command to install OneDrive again from the default user template
reg import .\DefaultRegistryFixes.reg
reg unload HKU\default
# Done with registry

# Make sure OneDrive isn't later changed to be a Windows Store app
Get-AppxPackage -AllUsers "*OneDrive*" | Remove-AppxPackage -AllUsers

# OneDrive is installed in one or more of five possible locations:
# Windows\System, Windows\System32, Windows\SysWOW64, Program Files, and Program Files (x86)
# Need to check all five

# First, the Windows locations
if (Test-Path "C:\Windows\System\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\System\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}
if (Test-Path "C:\Windows\System32\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\System32\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}
if (Test-Path "C:\Windows\SysWOW64\OneDriveSetup.exe") {
    start -wait -filepath "C:\Windows\SysWOW64\OneDriveSetup.exe" -argumentlist "/uninstall","/qn"
}

# Then Program Files. 
# These locations also have a version number subfolder that may change over time
# So we need extra steps to find that folder
if (Test-path "C:\Program Files\Microsoft OneDrive") {
    $folder = (get-childitem "C:\Program Files\Microsoft OneDrive").Name | ?{ $_ -match "^\d{2}.*" }
    # can be several folders. Only one will have the uninstaller
    $folder | % {
        if (Test-Path "C:\Program Files\Microsoft OneDrive\$_\OneDriveSetup.exe") {
            $path = "C:\Program Files\Microsoft OneDrive\$_\OneDriveSetup.exe"
            start -wait -filepath $path -argumentlist "/uninstall","/qn"
        }
    }
}
if (Test-path "C:\Program Files (x86)\Microsoft OneDrive") {
    $folder = (get-childitem "C:\Program Files (x86)\Microsoft OneDrive").Name | ?{ $_ -match "^\d{2}.*" }
    # can be several folders. Only one will have the uninstaller
    $folder | % {
        if (Test-Path "C:\Program Files (x86)\Microsoft OneDrive\$_\OneDriveSetup.exe") {
            $path = "C:\Program Files (x86)\Microsoft OneDrive\$_\OneDriveSetup.exe"
            start -wait -filepath $path -argumentlist "/uninstall","/qn"
        }
    }
}

# Now look in WinSXS for the setup file backup
$ods = get-childitem "C:\Windows\WinSxS\amd64_microsoft-windows-onedrive-setup*"
if ($ods) {
    $path = "C:\Windows\WinSxS\$($ods.Name)\*.*"
    # Don't need to uninstall. Just remove the files. But also need to take ownership first
    takeown /F $path /A | Out-Null
    icacls $path /grant Administrators:M | Out-Null
    remove-item -path $path -force | out-null
}

#   And finally clean up installer program found earlier in the registry
if ($odp)
{
    $odp = $odp.Replace(" /thfirstsetup", "") # remove command line argument
    takeown /F $odp /A | Out-Null
    icacls $odp /grant Administrators:M | Out-Null
    remove-item $odp | out-null
}

Le fichier de registre :

Windows Registry Editor Version 5.00

[HKEY_USERS\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"OneDriveSetup"=-

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"OneDriveSetup"=-
"OneDrive"=-

N’oubliez pas que le script a chargé la ruche de l’utilisateur par défaut spécialement pour que ce fichier .reg soit efficace.

Cela supprime avec succès OneDrive d’un système neuf, et je ne le vois plus en cours d’exécution après la création d’un nouvel utilisateur. S’il y a d’autres utilisateurs déjà créés sur le système, un travail supplémentaire sera nécessaire. Mais ce n’est pas ma situation actuelle.

Mais je n’ai pas terminé.

Je m’attends à ce que le script ci-dessus soit efficace pendant un à trois mois, mais ensuite une mise à jour Windows finira par corriger l’installateur et le registre par défaut. Ce n’est même pas Microsoft qui essaie trop de pousser ses propres produits. C’est simplement le résultat naturel de la plateforme de maintenance qui fait son travail, soit après la correction d’un CVE, soit lorsqu’une nouvelle version est disponible dans le cadre d’une mise à jour annuelle de fonctionnalités.

Donc, pour empêcher OneDrive de revenir, ce code (et d’autres choses) sera également inclus comme tâche planifiée récurrente. Ainsi, quand OneDrive reviendra, il sera simplement supprimé à nouveau. Cela devrait empêcher son apparition pour les nouveaux utilisateurs, ce qui est un événement plus rare. J’examine également des modifications de registre supplémentaires que je peux utiliser pour le rendre moins agressif pendant la période potentielle pouvant aller jusqu’à environ un jour où il pourrait exister sur un système, afin qu’il ne finisse pas installé dans le dossier AppData d’un utilisateur.

Comme autre mesure, j’envisage de modifier le code du script pour écrire des fichiers de remplacement par-dessus les fichiers OneDriveSetup.exe existants, avec des listes de contrôle d’accès personnalisées qui ne permettent pas l’accès en écriture aux principaux SYSTEM ou TRUSTED INSTALLER. Mais je crains que cela ne casse et force des restaurations pour les mises à jour plus importantes, laissant les systèmes dans un état non sécurisé, donc ce n’est pas dans le plan actuel.

Enfin, nous pourrions également apporter des modifications manuelles de politique de sécurité sur chaque système, pour bloquer l’exécution des installateurs. Mais comme je n’ai pas trouvé de moyen de rendre cela scriptable/reproductible, je le garde en dernier recours.