Use JSON data file for storing PowerRename settings instead of registry (#1909)

* Use JSON data file for storing PowerRename settings instead of registry

* Address PR comments and made several improvements

* Remove WindowsApp.lib dependencies in test app and unit tests

* Revert changes in vcxproj for unit test

* Solve linker warnings generated while linking WindowsApp.lib

* Don't migrate enabled flag. Always read / write from registry.
This commit is contained in:
vldmr11080 2020-04-08 19:12:46 +02:00 committed by GitHub
parent 17022d50d4
commit c355a2b61e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 314 additions and 224 deletions

View File

@ -48,7 +48,7 @@ HRESULT CPowerRenameMenu::s_CreateInstance(_In_opt_ IUnknown*, _In_ REFIID riid,
HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject* pdtobj, HKEY) HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject* pdtobj, HKEY)
{ {
// Check if we have disabled ourselves // Check if we have disabled ourselves
if (!CSettings::GetEnabled()) if (!CSettingsInstance().GetEnabled())
return E_FAIL; return E_FAIL;
// Cache the data object to be used later // Cache the data object to be used later
@ -60,11 +60,11 @@ HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObjec
HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirst, UINT, UINT uFlags) HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirst, UINT, UINT uFlags)
{ {
// Check if we have disabled ourselves // Check if we have disabled ourselves
if (!CSettings::GetEnabled()) if (!CSettingsInstance().GetEnabled())
return E_FAIL; return E_FAIL;
// Check if we should only be on the extended context menu // Check if we should only be on the extended context menu
if (CSettings::GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS))) if (CSettingsInstance().GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
return E_FAIL; return E_FAIL;
HRESULT hr = E_UNEXPECTED; HRESULT hr = E_UNEXPECTED;
@ -81,7 +81,7 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs
mii.dwTypeData = (PWSTR)menuName; mii.dwTypeData = (PWSTR)menuName;
mii.fState = MFS_ENABLED; mii.fState = MFS_ENABLED;
if (CSettings::GetShowIconOnMenu()) if (CSettingsInstance().GetShowIconOnMenu())
{ {
HICON hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_RENAME), IMAGE_ICON, 16, 16, 0); HICON hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_RENAME), IMAGE_ICON, 16, 16, 0);
if (hIcon) if (hIcon)
@ -113,7 +113,7 @@ HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (CSettings::GetEnabled() && if (CSettingsInstance().GetEnabled() &&
(IS_INTRESOURCE(pici->lpVerb)) && (IS_INTRESOURCE(pici->lpVerb)) &&
(LOWORD(pici->lpVerb) == 0)) (LOWORD(pici->lpVerb) == 0))
{ {
@ -203,7 +203,7 @@ HRESULT __stdcall CPowerRenameMenu::GetTitle(IShellItemArray* /*psiItemArray*/,
HRESULT __stdcall CPowerRenameMenu::GetIcon(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszIcon) HRESULT __stdcall CPowerRenameMenu::GetIcon(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszIcon)
{ {
if (!CSettings::GetShowIconOnMenu()) if (!CSettingsInstance().GetShowIconOnMenu())
{ {
*ppszIcon = nullptr; *ppszIcon = nullptr;
return E_NOTIMPL; return E_NOTIMPL;
@ -229,7 +229,7 @@ HRESULT __stdcall CPowerRenameMenu::GetCanonicalName(GUID* pguidCommandName)
HRESULT __stdcall CPowerRenameMenu::GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState) HRESULT __stdcall CPowerRenameMenu::GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState)
{ {
*pCmdState = CSettings::GetEnabled() ? ECS_ENABLED : ECS_HIDDEN; *pCmdState = CSettingsInstance().GetEnabled() ? ECS_ENABLED : ECS_HIDDEN;
return S_OK; return S_OK;
} }

View File

@ -207,17 +207,17 @@ public:
settings.add_bool_toogle( settings.add_bool_toogle(
L"bool_persist_input", L"bool_persist_input",
GET_RESOURCE_STRING(IDS_RESTORE_SEARCH), GET_RESOURCE_STRING(IDS_RESTORE_SEARCH),
CSettings::GetPersistState()); CSettingsInstance().GetPersistState());
settings.add_bool_toogle( settings.add_bool_toogle(
L"bool_mru_enabled", L"bool_mru_enabled",
GET_RESOURCE_STRING(IDS_ENABLE_AUTO), GET_RESOURCE_STRING(IDS_ENABLE_AUTO),
CSettings::GetMRUEnabled()); CSettingsInstance().GetMRUEnabled());
settings.add_int_spinner( settings.add_int_spinner(
L"int_max_mru_size", L"int_max_mru_size",
GET_RESOURCE_STRING(IDS_MAX_ITEMS), GET_RESOURCE_STRING(IDS_MAX_ITEMS),
CSettings::GetMaxMRUSize(), CSettingsInstance().GetMaxMRUSize(),
0, 0,
20, 20,
1); 1);
@ -225,12 +225,12 @@ public:
settings.add_bool_toogle( settings.add_bool_toogle(
L"bool_show_icon_on_menu", L"bool_show_icon_on_menu",
GET_RESOURCE_STRING(IDS_ICON_CONTEXT_MENU), GET_RESOURCE_STRING(IDS_ICON_CONTEXT_MENU),
CSettings::GetShowIconOnMenu()); CSettingsInstance().GetShowIconOnMenu());
settings.add_bool_toogle( settings.add_bool_toogle(
L"bool_show_extended_menu", L"bool_show_extended_menu",
GET_RESOURCE_STRING(IDS_EXTENDED_MENU_INFO), GET_RESOURCE_STRING(IDS_EXTENDED_MENU_INFO),
CSettings::GetExtendedContextMenuOnly()); CSettingsInstance().GetExtendedContextMenuOnly());
return settings.serialize_to_buffer(buffer, buffer_size); return settings.serialize_to_buffer(buffer, buffer_size);
} }
@ -245,11 +245,12 @@ public:
PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues values =
PowerToysSettings::PowerToyValues::from_json_string(config); PowerToysSettings::PowerToyValues::from_json_string(config);
CSettings::SetPersistState(values.get_bool_value(L"bool_persist_input").value()); CSettingsInstance().SetPersistState(values.get_bool_value(L"bool_persist_input").value());
CSettings::SetMRUEnabled(values.get_bool_value(L"bool_mru_enabled").value()); CSettingsInstance().SetMRUEnabled(values.get_bool_value(L"bool_mru_enabled").value());
CSettings::SetMaxMRUSize(values.get_int_value(L"int_max_mru_size").value()); CSettingsInstance().SetMaxMRUSize(values.get_int_value(L"int_max_mru_size").value());
CSettings::SetShowIconOnMenu(values.get_bool_value(L"bool_show_icon_on_menu").value()); CSettingsInstance().SetShowIconOnMenu(values.get_bool_value(L"bool_show_icon_on_menu").value());
CSettings::SetExtendedContextMenuOnly(values.get_bool_value(L"bool_show_extended_menu").value()); CSettingsInstance().SetExtendedContextMenuOnly(values.get_bool_value(L"bool_show_extended_menu").value());
CSettingsInstance().SavePowerRenameData();
Trace::SettingsChanged(); Trace::SettingsChanged();
} }
@ -282,13 +283,15 @@ public:
void init_settings() void init_settings()
{ {
m_enabled = CSettings::GetEnabled(); CSettingsInstance().LoadPowerRenameData();
m_enabled = CSettingsInstance().GetEnabled();
Trace::EnablePowerRename(m_enabled); Trace::EnablePowerRename(m_enabled);
} }
void save_settings() void save_settings()
{ {
CSettings::SetEnabled(m_enabled); CSettingsInstance().SetEnabled(m_enabled);
CSettingsInstance().SavePowerRenameData();
Trace::EnablePowerRename(m_enabled); Trace::EnablePowerRename(m_enabled);
} }

View File

@ -85,13 +85,14 @@
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -99,7 +100,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -107,6 +108,7 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -116,7 +118,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
@ -124,6 +126,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -134,7 +137,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
@ -143,6 +146,7 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>

View File

@ -1,7 +1,14 @@
#include "stdafx.h" #include "stdafx.h"
#include <commctrl.h>
#include "Settings.h" #include "Settings.h"
#include "PowerRenameInterfaces.h" #include "PowerRenameInterfaces.h"
#include "settings_helpers.h"
#include <filesystem>
#include <commctrl.h>
namespace
{
const wchar_t c_powerRenameDataFilePath[] = L"power-rename-settings.json";
const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename"; const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename";
const wchar_t c_mruSearchRegPath[] = L"SearchMRU"; const wchar_t c_mruSearchRegPath[] = L"SearchMRU";
@ -17,154 +24,46 @@ const wchar_t c_searchText[] = L"SearchText";
const wchar_t c_replaceText[] = L"ReplaceText"; const wchar_t c_replaceText[] = L"ReplaceText";
const wchar_t c_mruEnabled[] = L"MRUEnabled"; const wchar_t c_mruEnabled[] = L"MRUEnabled";
const bool c_enabledDefault = true; long GetRegNumber(const std::wstring& valueName, long defaultValue)
const bool c_showIconOnMenuDefault = true;
const bool c_extendedContextMenuOnlyDefaut = false;
const bool c_persistStateDefault = true;
const bool c_mruEnabledDefault = true;
const DWORD c_maxMRUSizeDefault = 10;
const DWORD c_flagsDefault = 0;
bool CSettings::GetEnabled()
{ {
return GetRegBoolValue(c_enabled, c_enabledDefault); DWORD type = REG_DWORD;
DWORD data = 0;
DWORD size = sizeof(DWORD);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS)
{
return data;
}
return defaultValue;
} }
bool CSettings::SetEnabled(_In_ bool enabled) void SetRegNumber(const std::wstring& valueName, long value)
{ {
return SetRegBoolValue(c_enabled, enabled); SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), REG_DWORD, &value, sizeof(value));
} }
bool CSettings::GetShowIconOnMenu() bool GetRegBoolean(const std::wstring& valueName, bool defaultValue)
{ {
return GetRegBoolValue(c_showIconOnMenu, c_showIconOnMenuDefault); DWORD value = GetRegNumber(valueName.c_str(), defaultValue ? 1 : 0);
}
bool CSettings::SetShowIconOnMenu(_In_ bool show)
{
return SetRegBoolValue(c_showIconOnMenu, show);
}
bool CSettings::GetExtendedContextMenuOnly()
{
return GetRegBoolValue(c_extendedContextMenuOnly, c_extendedContextMenuOnlyDefaut);
}
bool CSettings::SetExtendedContextMenuOnly(_In_ bool extendedOnly)
{
return SetRegBoolValue(c_extendedContextMenuOnly, extendedOnly);
}
bool CSettings::GetPersistState()
{
return GetRegBoolValue(c_persistState, c_persistStateDefault);
}
bool CSettings::SetPersistState(_In_ bool persistState)
{
return SetRegBoolValue(c_persistState, persistState);
}
bool CSettings::GetMRUEnabled()
{
return GetRegBoolValue(c_mruEnabled, c_mruEnabledDefault);
}
bool CSettings::SetMRUEnabled(_In_ bool enabled)
{
return SetRegBoolValue(c_mruEnabled, enabled);
}
DWORD CSettings::GetMaxMRUSize()
{
return GetRegDWORDValue(c_maxMRUSize, c_maxMRUSizeDefault);
}
bool CSettings::SetMaxMRUSize(_In_ DWORD maxMRUSize)
{
return SetRegDWORDValue(c_maxMRUSize, maxMRUSize);
}
DWORD CSettings::GetFlags()
{
return GetRegDWORDValue(c_flags, c_flagsDefault);
}
bool CSettings::SetFlags(_In_ DWORD flags)
{
return SetRegDWORDValue(c_flags, flags);
}
bool CSettings::GetSearchText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf)
{
return GetRegStringValue(c_searchText, text, cchBuf);
}
bool CSettings::SetSearchText(_In_ PCWSTR text)
{
return SetRegStringValue(c_searchText, text);
}
bool CSettings::GetReplaceText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf)
{
return GetRegStringValue(c_replaceText, text, cchBuf);
}
bool CSettings::SetReplaceText(_In_ PCWSTR text)
{
return SetRegStringValue(c_replaceText, text);
}
bool CSettings::SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value)
{
DWORD dwValue = value ? 1 : 0;
return SetRegDWORDValue(valueName, dwValue);
}
bool CSettings::GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue)
{
DWORD value = GetRegDWORDValue(valueName, (defaultValue == 0) ? false : true);
return (value == 0) ? false : true; return (value == 0) ? false : true;
} }
bool CSettings::SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value) void SetRegBoolean(const std::wstring& valueName, bool value)
{ {
return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_DWORD, &value, sizeof(value))))); SetRegNumber(valueName, value ? 1 : 0);
} }
DWORD CSettings::GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue) std::wstring GetRegString(const std::wstring& valueName) {
{ wchar_t value[CSettings::MAX_INPUT_STRING_LEN];
DWORD retVal = defaultValue;
DWORD type = REG_DWORD;
DWORD dwEnabled = 0;
DWORD cb = sizeof(dwEnabled);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, &dwEnabled, &cb) == ERROR_SUCCESS)
{
retVal = dwEnabled;
}
return retVal;
}
bool CSettings::SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value)
{
ULONG cb = (DWORD)((wcslen(value) + 1) * sizeof(*value));
return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_SZ, (const BYTE*)value, cb))));
}
bool CSettings::GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf)
{
if (cchBuf > 0)
{
value[0] = L'\0'; value[0] = L'\0';
}
DWORD type = REG_SZ; DWORD type = REG_SZ;
ULONG cb = cchBuf * sizeof(*value); DWORD size = CSettings::MAX_INPUT_STRING_LEN * sizeof(wchar_t);
return (SUCCEEDED(HRESULT_FROM_WIN32(SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, value, &cb) == ERROR_SUCCESS))); if (SUCCEEDED(HRESULT_FROM_WIN32(SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, value, &size) == ERROR_SUCCESS)))
{
return std::wstring(value);
}
return std::wstring{};
}
} }
typedef int (CALLBACK* MRUCMPPROC)(LPCWSTR, LPCWSTR); typedef int (CALLBACK* MRUCMPPROC)(LPCWSTR, LPCWSTR);
@ -470,12 +369,121 @@ void CRenameMRU::_FreeMRUList()
} }
} }
CSettings::CSettings()
{
std::wstring result = PTSettingsHelper::get_module_save_folder_location(L"PowerRename");
jsonFilePath = result + L"\\" + std::wstring(c_powerRenameDataFilePath);
}
bool CSettings::GetEnabled()
{
return GetRegBoolean(c_enabled, true);
}
void CSettings::SetEnabled(bool enabled)
{
SetRegBoolean(c_enabled, enabled);
}
void CSettings::LoadPowerRenameData()
{
if (!std::filesystem::exists(jsonFilePath))
{
MigrateSettingsFromRegistry();
SavePowerRenameData();
}
else
{
ParseJsonSettings();
}
}
void CSettings::SavePowerRenameData() const
{
json::JsonObject jsonData;
jsonData.SetNamedValue(c_showIconOnMenu, json::value(settings.showIconOnMenu));
jsonData.SetNamedValue(c_extendedContextMenuOnly, json::value(settings.extendedContextMenuOnly));
jsonData.SetNamedValue(c_persistState, json::value(settings.persistState));
jsonData.SetNamedValue(c_mruEnabled, json::value(settings.MRUEnabled));
jsonData.SetNamedValue(c_maxMRUSize, json::value(settings.maxMRUSize));
jsonData.SetNamedValue(c_flags, json::value(settings.flags));
jsonData.SetNamedValue(c_searchText, json::value(settings.searchText));
jsonData.SetNamedValue(c_replaceText, json::value(settings.replaceText));
json::to_file(jsonFilePath, jsonData);
}
void CSettings::MigrateSettingsFromRegistry()
{
settings.showIconOnMenu = GetRegBoolean(c_showIconOnMenu, true);
settings.extendedContextMenuOnly = GetRegBoolean(c_extendedContextMenuOnly, false); // Disabled by default.
settings.persistState = GetRegBoolean(c_persistState, true);
settings.MRUEnabled = GetRegBoolean(c_mruEnabled, true);
settings.maxMRUSize = GetRegNumber(c_maxMRUSize, 10);
settings.flags = GetRegNumber(c_flags, 0);
settings.searchText = GetRegString(c_searchText);
settings.replaceText = GetRegString(c_replaceText);
}
void CSettings::ParseJsonSettings()
{
auto json = json::from_file(jsonFilePath);
if (json)
{
const json::JsonObject& jsonSettings = json.value();
try
{
if (json::has(jsonSettings, c_showIconOnMenu, json::JsonValueType::Boolean))
{
settings.showIconOnMenu = jsonSettings.GetNamedBoolean(c_showIconOnMenu);
}
if (json::has(jsonSettings, c_extendedContextMenuOnly, json::JsonValueType::Boolean))
{
settings.extendedContextMenuOnly = jsonSettings.GetNamedBoolean(c_extendedContextMenuOnly);
}
if (json::has(jsonSettings, c_persistState, json::JsonValueType::Boolean))
{
settings.persistState = jsonSettings.GetNamedBoolean(c_persistState);
}
if (json::has(jsonSettings, c_mruEnabled, json::JsonValueType::Boolean))
{
settings.MRUEnabled = jsonSettings.GetNamedBoolean(c_mruEnabled);
}
if (json::has(jsonSettings, c_maxMRUSize, json::JsonValueType::Number))
{
settings.maxMRUSize = (long)jsonSettings.GetNamedNumber(c_maxMRUSize);
}
if (json::has(jsonSettings, c_flags, json::JsonValueType::Number))
{
settings.flags = (long)jsonSettings.GetNamedNumber(c_flags);
}
if (json::has(jsonSettings, c_searchText, json::JsonValueType::String))
{
settings.searchText = jsonSettings.GetNamedString(c_searchText);
}
if (json::has(jsonSettings, c_replaceText, json::JsonValueType::String))
{
settings.replaceText = jsonSettings.GetNamedString(c_replaceText);
}
}
catch (const winrt::hresult_error&) { }
}
}
CSettings& CSettingsInstance()
{
static CSettings instance;
return instance;
}
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk) HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk)
{ {
return CRenameMRU::CreateInstance(c_mruSearchRegPath, CSettings::GetMaxMRUSize(), ppUnk); return CRenameMRU::CreateInstance(c_mruSearchRegPath, CSettingsInstance().GetMaxMRUSize(), ppUnk);
} }
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk) HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk)
{ {
return CRenameMRU::CreateInstance(c_mruReplaceRegPath, CSettings::GetMaxMRUSize(), ppUnk); return CRenameMRU::CreateInstance(c_mruReplaceRegPath, CSettingsInstance().GetMaxMRUSize(), ppUnk);
} }

View File

@ -1,45 +1,124 @@
#pragma once #pragma once
#include "json.h"
#include <string>
class CSettings class CSettings
{ {
public: public:
static const int MAX_INPUT_STRING_LEN = 1024; static const int MAX_INPUT_STRING_LEN = 1024;
static bool GetEnabled(); CSettings();
static bool SetEnabled(_In_ bool enabled);
static bool GetShowIconOnMenu(); bool GetEnabled();
static bool SetShowIconOnMenu(_In_ bool show);
static bool GetExtendedContextMenuOnly(); void SetEnabled(bool enabled);
static bool SetExtendedContextMenuOnly(_In_ bool extendedOnly);
static bool GetPersistState(); inline bool GetShowIconOnMenu() const
static bool SetPersistState(_In_ bool extendedOnly); {
return settings.showIconOnMenu;
}
static bool GetMRUEnabled(); inline void SetShowIconOnMenu(bool show)
static bool SetMRUEnabled(_In_ bool enabled); {
settings.showIconOnMenu = show;
}
static DWORD GetMaxMRUSize(); inline bool GetExtendedContextMenuOnly() const
static bool SetMaxMRUSize(_In_ DWORD maxMRUSize); {
return settings.extendedContextMenuOnly;
}
static DWORD GetFlags(); inline void SetExtendedContextMenuOnly(bool extendedOnly)
static bool SetFlags(_In_ DWORD flags); {
settings.extendedContextMenuOnly = extendedOnly;
}
static bool GetSearchText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf); inline bool GetPersistState() const
static bool SetSearchText(_In_ PCWSTR text); {
return settings.persistState;
}
static bool GetReplaceText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf); inline void SetPersistState(bool persistState)
static bool SetReplaceText(_In_ PCWSTR text); {
settings.persistState = persistState;
}
inline bool GetMRUEnabled() const
{
return settings.MRUEnabled;
}
inline void SetMRUEnabled(bool MRUEnabled)
{
settings.MRUEnabled = MRUEnabled;
}
inline long GetMaxMRUSize() const
{
return settings.maxMRUSize;
}
inline void SetMaxMRUSize(long maxMRUSize)
{
settings.maxMRUSize = maxMRUSize;
}
inline long GetFlags() const
{
return settings.flags;
}
inline void SetFlags(long flags)
{
settings.flags = flags;
}
inline const std::wstring& GetSearchText() const
{
return settings.searchText;
}
inline void SetSearchText(const std::wstring& text)
{
settings.searchText = text;
}
inline const std::wstring& GetReplaceText() const
{
return settings.replaceText;
}
inline void SetReplaceText(const std::wstring& text)
{
settings.replaceText = text;
}
void LoadPowerRenameData();
void SavePowerRenameData() const;
private: private:
static bool GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue); struct Settings
static bool SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value); {
static bool SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value); bool showIconOnMenu{ true };
static DWORD GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue); bool extendedContextMenuOnly{ false }; // Disabled by default.
static bool SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value); bool persistState{ true };
static bool GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf); bool MRUEnabled{ true };
long maxMRUSize{ 10 };
long flags{ 0 };
std::wstring searchText{};
std::wstring replaceText{};
}; };
void MigrateSettingsFromRegistry();
void ParseJsonSettings();
Settings settings;
std::wstring jsonFilePath;
};
CSettings& CSettingsInstance();
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk); HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk);
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk); HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk);

View File

@ -19,3 +19,5 @@
#include <shlwapi.h> #include <shlwapi.h>
#include <ProjectTelemetry.h> #include <ProjectTelemetry.h>
#pragma comment(lib, "windowsapp")

View File

@ -79,11 +79,11 @@ void Trace::SettingsChanged() noexcept
"PowerRename_SettingsChanged", "PowerRename_SettingsChanged",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE), TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(CSettings::GetEnabled(), "IsEnabled"), TraceLoggingBoolean(CSettingsInstance().GetEnabled(), "IsEnabled"),
TraceLoggingBoolean(CSettings::GetShowIconOnMenu(), "ShowIconOnMenu"), TraceLoggingBoolean(CSettingsInstance().GetShowIconOnMenu(), "ShowIconOnMenu"),
TraceLoggingBoolean(CSettings::GetExtendedContextMenuOnly(), "ExtendedContextMenuOnly"), TraceLoggingBoolean(CSettingsInstance().GetExtendedContextMenuOnly(), "ExtendedContextMenuOnly"),
TraceLoggingBoolean(CSettings::GetPersistState(), "PersistState"), TraceLoggingBoolean(CSettingsInstance().GetPersistState(), "PersistState"),
TraceLoggingBoolean(CSettings::GetMRUEnabled(), "IsMRUEnabled"), TraceLoggingBoolean(CSettingsInstance().GetMRUEnabled(), "IsMRUEnabled"),
TraceLoggingUInt64(CSettings::GetMaxMRUSize(), "MaxMRUSize"), TraceLoggingUInt64(CSettingsInstance().GetMaxMRUSize(), "MaxMRUSize"),
TraceLoggingUInt64(CSettings::GetFlags(), "Flags")); TraceLoggingUInt64(CSettingsInstance().GetFlags(), "Flags"));
} }

View File

@ -308,7 +308,7 @@ HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IUn
HRESULT CPowerRenameUI::_InitAutoComplete() HRESULT CPowerRenameUI::_InitAutoComplete()
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (CSettings::GetMRUEnabled()) if (CSettingsInstance().GetMRUEnabled())
{ {
hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spSearchAC)); hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spSearchAC));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -387,19 +387,13 @@ HRESULT CPowerRenameUI::_ReadSettings()
// Check if we should read flags from settings // Check if we should read flags from settings
// or the defaults from the manager. // or the defaults from the manager.
DWORD flags = 0; DWORD flags = 0;
if (CSettings::GetPersistState()) if (CSettingsInstance().GetPersistState())
{ {
flags = CSettings::GetFlags(); flags = CSettingsInstance().GetFlags();
m_spsrm->put_flags(flags); m_spsrm->put_flags(flags);
wchar_t buffer[CSettings::MAX_INPUT_STRING_LEN]; SetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, CSettingsInstance().GetSearchText().c_str());
buffer[0] = L'\0'; SetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, CSettingsInstance().GetReplaceText().c_str());
CSettings::GetSearchText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer);
buffer[0] = L'\0';
CSettings::GetReplaceText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer);
} }
else else
{ {
@ -414,18 +408,18 @@ HRESULT CPowerRenameUI::_ReadSettings()
HRESULT CPowerRenameUI::_WriteSettings() HRESULT CPowerRenameUI::_WriteSettings()
{ {
// Check if we should store our settings // Check if we should store our settings
if (CSettings::GetPersistState()) if (CSettingsInstance().GetPersistState())
{ {
DWORD flags = 0; DWORD flags = 0;
m_spsrm->get_flags(&flags); m_spsrm->get_flags(&flags);
CSettings::SetFlags(flags); CSettingsInstance().SetFlags(flags);
wchar_t buffer[CSettings::MAX_INPUT_STRING_LEN]; wchar_t buffer[CSettings::MAX_INPUT_STRING_LEN];
buffer[0] = L'\0'; buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer)); GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer));
CSettings::SetSearchText(buffer); CSettingsInstance().SetSearchText(buffer);
if (CSettings::GetMRUEnabled() && m_spSearchACL) if (CSettingsInstance().GetMRUEnabled() && m_spSearchACL)
{ {
CComPtr<IPowerRenameMRU> spSearchMRU; CComPtr<IPowerRenameMRU> spSearchMRU;
if (SUCCEEDED(m_spSearchACL->QueryInterface(IID_PPV_ARGS(&spSearchMRU)))) if (SUCCEEDED(m_spSearchACL->QueryInterface(IID_PPV_ARGS(&spSearchMRU))))
@ -436,9 +430,9 @@ HRESULT CPowerRenameUI::_WriteSettings()
buffer[0] = L'\0'; buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer, ARRAYSIZE(buffer)); GetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer, ARRAYSIZE(buffer));
CSettings::SetReplaceText(buffer); CSettingsInstance().SetReplaceText(buffer);
if (CSettings::GetMRUEnabled() && m_spReplaceACL) if (CSettingsInstance().GetMRUEnabled() && m_spReplaceACL)
{ {
CComPtr<IPowerRenameMRU> spReplaceMRU; CComPtr<IPowerRenameMRU> spReplaceMRU;
if (SUCCEEDED(m_spReplaceACL->QueryInterface(IID_PPV_ARGS(&spReplaceMRU)))) if (SUCCEEDED(m_spReplaceACL->QueryInterface(IID_PPV_ARGS(&spReplaceMRU))))