Last active
February 9, 2023 23:18
-
-
Save ruxo/32972039eb659dd5c103 to your computer and use it in GitHub Desktop.
Remove garbage from registry
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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