{"id":18021259,"url":"https://github.com/ho-cooh/regeditpp","last_synced_at":"2025-10-17T02:59:54.908Z","repository":{"id":112728009,"uuid":"445237906","full_name":"HO-COOH/RegeditPP","owner":"HO-COOH","description":null,"archived":false,"fork":false,"pushed_at":"2022-01-24T15:53:44.000Z","size":1146,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-10T02:45:31.884Z","etag":null,"topics":["cpp","regedit","registry","win32"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HO-COOH.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-06T16:32:36.000Z","updated_at":"2023-03-12T15:13:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"4077fd59-83e1-4b14-a463-1967aa58dbc7","html_url":"https://github.com/HO-COOH/RegeditPP","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HO-COOH%2FRegeditPP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HO-COOH%2FRegeditPP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HO-COOH%2FRegeditPP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HO-COOH%2FRegeditPP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HO-COOH","download_url":"https://codeload.github.com/HO-COOH/RegeditPP/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247217885,"owners_count":20903157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","regedit","registry","win32"],"created_at":"2024-10-30T06:09:14.486Z","updated_at":"2025-10-17T02:59:49.863Z","avatar_url":"https://github.com/HO-COOH.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RegeditPP\nA modern C++17 wrapper for Win32 Registry utilities.\n\n## Keys\n### Pre-opened keys\n[Microsoft docs](https://docs.microsoft.com/en-us/windows/win32/sysinfo/opening-creating-and-closing-keys).\n\n- LocalMachine\n- ClassesRoot\n- Users\n- CurrentUser\n\n### Opening, Creating, and Closing Keys\nYou start from a pre-opened key (listed above) to open a subkey or create a subkey.\nOpening a subkey is as simple as using the familiar array indexing operator`[L\"subkey\"]`.\nFor example, to open `HKEY_CURRENT_USER\\Control Panel`, you do\n```cpp\nauto controlPanel = CurrentUser[L\"Control Panel\"];\n```\nThe `[]` operator can be chanined to open subkeys at any level \n(up to 512, the maximum supported depth in registry) in a single line.\n```cpp\nauto currentVersion = CurrentUser[L\"Software\"][L\"Microsoft\"][L\"Windows\"][L\"CurrentVersion\"];\n```\nTo create a subkey, you call `.create(L\"subkey\")` on an opened key.\n```cpp\nauto newKey = key.create(L\"newKey\");\n```\nYou don't need to worry about closing the keys. \nIt is handled automatically in the destructor.\n\nIf you need to explicitly write registry data to the hard disk, you call `.flush()`\n```cpp\nkey.flush();\n```\n\n### Writing and Deleting Registry Data\nUse the operator `+=Value\u003cValueType\u003e(...)` to add a value and \noperator `-= L\"valueName\"` to delete a value. For example,\n```cpp\nauto run = CurrentUser[L\"Software\"][L\"Microsoft\"][L\"Windows\"][L\"CurrentVersion\"][L\"Run\"];\nrun -= L\"LGHUB\";    //Stop logitech g-hub auto launching when Windows start up\nrun += Value\u003cType::String\u003e(L\"My Application\", L\"...\");\n```\n\n\n### Retriving Data from the Registry\nThere are 2 ways to read a value.\n- If you are sure about the type, use `key.valueOf(L\"valueName\").as\u003ctype\u003e()`\n  The `.as\u003c\u003e()` call returns an instance of `Value\u003c\u003e` [type (see below)](###Types) \n  ```cpp\n  auto binaryValue = \n      CurrentUser[L\"Microsoft\"][L\"Windows\"][L\"CurrentVersion\"][L\"Explorer\"][L\"StartupApproved\"][L\"Run\"]\n      .valueOf(L\"OneDriveSetup\")\n      .as\u003cType::Binary\u003e();\n  ```\n- If you are **NOT** sure about the type, first get the type, then use a `switch` statement to handle it according to your need\n  ```cpp\n  auto unknownTypeValue = CurrentUser[L\"subKey\"].valueOf(L\"valueName\");\n  switch(unknownTypeValue.getType())\n  {\n      case Type::Binary:\n      {\n          auto binaryValue = unknownTypeValue.as\u003cType::Binary\u003e();\n          //process binary value...\n      }\n      //other cases...\n  }\n  ```\n### Enumerating Registry Subkeys\nTo enumerate a key, you can either use the iterator return from `.begin()` and `.end()`,\nor a range-based `for` loop, which uses the iterator underhood.\nWhen the iterator is dereferenced with operator`*`, it returns a `std::variant` of all the\nsupported value-types [(see below)](###Types) as well as the key type. \nThen you may use `std::visit()` to call different functions\nfor different value types.\n```cpp\ntemplate\u003ctypename... Functions\u003e \nstruct overloaded : Functions... \n{ \n    using Functions::operator()...;\n};\ntemplate\u003ctypename... Functions\u003e\noverloaded(Functions...) -\u003e overloaded\u003cFunctions...\u003e;\n\nfor(auto child : key) //child is a std::variant\n{\n    std::visit(\n        overloaded\n        {\n            [](Value\u003cType::Binary\u003e const\u0026 value)\n            {\n                //process binary value\n            },\n            [](Value\u003cType::String\u003e const\u0026 value)\n            {\n                //process string value\n            }\n        },\n        child\n    );\n}\n```\n### Deleting a Key with Subkeys\nSince `delete` is a keyword in C++, I chooose to use the word `.remove()` instead.\nIf you can be sure that there are no subkeys and values in the current key, you use\n`.remove(L\"key\")`. Why not use operator`-=` you ask? \nBecause there are no ways to distinguish whether to delete a key (fail if there are subkeys)\nor to delete a key recursively using operator`-=` with a name. \nAnd in fact, operator `-=` is for [deleting a value from a key](Deleting a value from a key).\n\n### Determining the Registry Size\n\n### Values Types\nSee [docs](https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types).\nValues types are strongly-typed classes, with `Type` as its non-type template parameters.\nYou usually get an instance of this class from `key.valueOf(L\"valueName\").as\u003ctype\u003e()`\nAll value types are listed as below\n- `Value\u003cType::Binary\u003e` -\u003e `REG_BINARY`\n- `Value\u003cType::Dword\u003e` -\u003e `REG_DWORD`\n- `Value\u003cType::UnexpandedString\u003e` -\u003e `REG_EXPAND_SZ`\n- `Value\u003cType::MultiString\u003e` -\u003e `REG_MULTI_SZ`\n- `Value\u003cType::Qword\u003e` -\u003e `REG_QWORD`\n- `Value\u003cType::String\u003e` -\u003e `REG_SZ`\n\nAll `Value\u003c\u003e` types support these methods:\n- `get` that returns the data that best expressed in C++\n  + Binary type returns `std::vector\u003cBYTE\u003e`\n  + Dword type returns `DWORD`\n  + Qword type returns `QWORD`\n  + String types (including unexpanded string and multi-string) returns `std::wstring`\n- `getData()` returns a pointer to the underlying storage, which you should not modify\n- `getName()` returns the name of the value\n\nThere are also additional methods that are supported in specific types, for example,\n`Value\u003cType::UnexpanedString\u003e` has `.expand()` that returns a string with the environment variables expanded. \nYou can find out those methods with the assistance of your IDE.\n\n### Constructing a value\nYou usually construct a value when editing a key.\nA value is constructed with a value name, and its corresponding data that is best expressed in C++ that already described above.\nFor example, a `Value\u003cType::String\u003e` can be constructed with a name and a string.\n```cpp\nValue\u003cType::String\u003e{L\"name\", L\"value\"};\n```\n\n## Inter-op\nThis small header-only library is written with inter-op with Win32 APIs in mind for greater flexibility.\nThere is a getter function called `.getXYZ()` on multiple wrapper classes. For example\n```cpp\nHKEY keyHandle = key.getHandle();\n```\n\n## Testing\nI am too lazy to bother setting up CI for testing. After all, this would be a small convenient utility for my company's software.\nYou can checkout the test code in `test.cpp`.\nHere are the screenshots of its running.\n![MSVC](screenshot/MSVC.png)\n![MingW](screenshot/MingW.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fho-cooh%2Fregeditpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fho-cooh%2Fregeditpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fho-cooh%2Fregeditpp/lists"}