Skip to content

Instantly share code, notes, and snippets.

@ruxo
Last active February 9, 2023 23:18
Show Gist options
  • Select an option

  • Save ruxo/32972039eb659dd5c103 to your computer and use it in GitHub Desktop.

Select an option

Save ruxo/32972039eb659dd5c103 to your computer and use it in GitHub Desktop.
Remove garbage from registry
open System
open Microsoft.Win32
let inline constant x = fun _ -> x
type RegistryEntry =
| Key of RegistryKey * string list
| Value of RegistryKey * string list * obj
let inline tryCast<'a> (x:obj) =
match x with
| :? 'a as s -> Some s
| _ -> None
module Option =
let inline cata fnone fsome = function
| None -> fnone()
| Some x -> fsome x
let inline getOrElse def = function
| Some x -> x
| None -> def()
let registries = [ Registry.ClassesRoot; Registry.CurrentConfig; Registry.CurrentUser; Registry.LocalMachine; Registry.Users]
let target = "Visual Studio 2015"
let openReg path (reg: RegistryKey) =
try
Option.ofObj <| reg.OpenSubKey path
with
| _ as ex -> printfn "%s: %s" (ex.GetType().ToString()) ex.Message
None
let getRegPath path = String.Join(@"\", path |> List.rev |> List.tail)
let rec flatten (reg: RegistryKey, path) =
seq {
let regPath = getRegPath path
let regOpt = openReg regPath reg
if Option.isSome regOpt then
use subReg = Option.get regOpt
let values = subReg.GetValueNames()
let subKeys = subReg.GetSubKeyNames()
for valKey in values do
yield Value (reg, valKey::path, subReg.GetValue valKey)
for subKey in subKeys do
let subKeyPath = subKey::path
yield Key (reg, subKeyPath)
yield! flatten(reg, subKeyPath)
else
printfn "Skip... open %s\\%s failed" reg.Name regPath
}
let root (reg: RegistryKey) = reg, [reg.Name]
let allKeys = registries |> Seq.map root |> Seq.collect flatten
let findInKey text = function
| Value (_, [], _)
| Key (_, []) -> invalidOp "Invalid registry path"
| Key (_, key::path) -> key.Contains text
| Value (_, key::path, v) -> key.Contains text || (v |> tryCast<string> |> Option.map (fun s -> s.Contains text) |> Option.getOrElse (constant false))
let findTargetKeys target = allKeys |> Seq.filter (findInKey target)
let showRegEntries: RegistryEntry -> unit = function
| Key (_, paths) -> printfn "[Key] %A" paths
| Value (_, paths, v) -> printfn "[Val] %A\n\r\t%A" paths v
let getParentChildRegPaths = function
| [] -> invalidOp "Path is invalid"
| (subkey::path) -> (getRegPath path), subkey
let removeRegEntry = function
| Key (reg, path) ->
let parentKey, subKey = getParentChildRegPaths path
printfn "[%s] Remove key %s from %s" reg.Name subKey parentKey
use targetReg = reg.OpenSubKey( parentKey, true)
targetReg.DeleteSubKeyTree subKey
| Value (reg, path, _) ->
let parentKey, valueKey = getParentChildRegPaths path
printfn "[%s] Remove value %s from %s" reg.Name valueKey parentKey
use targetReg = reg.OpenSubKey( parentKey, true)
targetReg.DeleteValue(valueKey)
target |> findTargetKeys
|> Seq.iter removeRegEntry
// |> Seq.iter showRegEntries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment