From ad81ec37b5824046b29231da44f104f9e7fc3267 Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Fri, 30 May 2025 13:07:20 +0800 Subject: [PATCH] [PowerRename] Add ModificationTime and AccessTime support when renaming with $YY-$MM-$DD patterns (#39653) ## Summary of the Pull Request 1. Add new configuration to control this behaviour. By default, set to creation time to align with previous version 2. Add UI in PowerRename's MainWindow 3. Implement the logic ![image](https://github.com/user-attachments/assets/fde6731b-73f9-453f-8b68-6ce66589f44a) Original discussion here: https://github.com/microsoft/PowerToys/pull/38186 ## PR Checklist - [x] **Closes:** #36040 - [x] **Communication:** I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end user facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Co-authored-by: Yu Leng (from Dev Box) Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> --- .../PowerRenameXAML/MainWindow.xaml | 28 +++++++++++ .../PowerRenameXAML/MainWindow.xaml.cpp | 26 ++++++++++ .../Strings/en-us/Resources.resw | 12 +++++ .../powerrename/lib/PowerRenameInterfaces.h | 7 ++- .../powerrename/lib/PowerRenameItem.cpp | 48 +++++++++++++++++-- src/modules/powerrename/lib/PowerRenameItem.h | 3 +- src/modules/powerrename/lib/Renaming.cpp | 2 +- 7 files changed, 117 insertions(+), 9 deletions(-) diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml index d049a0d067..7126a63604 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml @@ -184,6 +184,7 @@ + + + + + + + + + + + + Random string features + + Time used for replacement + + + Creation Time + + + Modification Time + + + Access Time + \ No newline at end of file diff --git a/src/modules/powerrename/lib/PowerRenameInterfaces.h b/src/modules/powerrename/lib/PowerRenameInterfaces.h index c545e9dc00..ea761d156a 100644 --- a/src/modules/powerrename/lib/PowerRenameInterfaces.h +++ b/src/modules/powerrename/lib/PowerRenameInterfaces.h @@ -18,7 +18,10 @@ enum PowerRenameFlags Lowercase = 0x400, Titlecase = 0x800, Capitalized = 0x1000, - RandomizeItems = 0x2000 + RandomizeItems = 0x2000, + CreationTime = 0x4000, + ModificationTime = 0x8000, + AccessTime = 0x10000, }; enum PowerRenameFilters @@ -67,7 +70,7 @@ interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameI public: IFACEMETHOD(PutPath)(_In_opt_ PCWSTR newPath) = 0; IFACEMETHOD(GetPath)(_Outptr_ PWSTR * path) = 0; - IFACEMETHOD(GetTime)(_Outptr_ SYSTEMTIME* time) = 0; + IFACEMETHOD(GetTime)(_In_ DWORD flags, _Outptr_ SYSTEMTIME * time) = 0; IFACEMETHOD(GetShellItem)(_Outptr_ IShellItem** ppsi) = 0; IFACEMETHOD(GetOriginalName)(_Outptr_ PWSTR * originalName) = 0; IFACEMETHOD(PutOriginalName)(_In_opt_ PCWSTR originalName) = 0; diff --git a/src/modules/powerrename/lib/PowerRenameItem.cpp b/src/modules/powerrename/lib/PowerRenameItem.cpp index bd8fa48285..9a0652c451 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.cpp +++ b/src/modules/powerrename/lib/PowerRenameItem.cpp @@ -56,12 +56,28 @@ IFACEMETHODIMP CPowerRenameItem::GetPath(_Outptr_ PWSTR* path) return hr; } -IFACEMETHODIMP CPowerRenameItem::GetTime(_Outptr_ SYSTEMTIME* time) +IFACEMETHODIMP CPowerRenameItem::GetTime(_In_ DWORD flags, _Outptr_ SYSTEMTIME* time) { CSRWSharedAutoLock lock(&m_lock); HRESULT hr = E_FAIL; + PowerRenameFlags parsedTimeType; - if (m_isTimeParsed) + // Get Time by PowerRenameFlags + if (flags & PowerRenameFlags::ModificationTime) + { + parsedTimeType = PowerRenameFlags::ModificationTime; + } + else if (flags & PowerRenameFlags::AccessTime) + { + parsedTimeType = PowerRenameFlags::AccessTime; + } + else + { + // Default to modification time if no specific flag is set + parsedTimeType = PowerRenameFlags::CreationTime; + } + + if (m_isTimeParsed && parsedTimeType == m_parsedTimeType) { hr = S_OK; } @@ -70,21 +86,43 @@ IFACEMETHODIMP CPowerRenameItem::GetTime(_Outptr_ SYSTEMTIME* time) HANDLE hFile = CreateFileW(m_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile != INVALID_HANDLE_VALUE) { - FILETIME CreationTime; - if (GetFileTime(hFile, &CreationTime, NULL, NULL)) + FILETIME FileTime; + bool success = false; + + // Get Time by PowerRenameFlags + switch (parsedTimeType) + { + case PowerRenameFlags::CreationTime: + success = GetFileTime(hFile, &FileTime, NULL, NULL); + break; + case PowerRenameFlags::ModificationTime: + success = GetFileTime(hFile, NULL, NULL, &FileTime); + break; + case PowerRenameFlags::AccessTime: + success = GetFileTime(hFile, NULL, &FileTime, NULL); + break; + default: + // Default to modification time if no specific flag is set + success = GetFileTime(hFile, NULL, NULL, &FileTime); + break; + } + + if (success) { SYSTEMTIME SystemTime, LocalTime; - if (FileTimeToSystemTime(&CreationTime, &SystemTime)) + if (FileTimeToSystemTime(&FileTime, &SystemTime)) { if (SystemTimeToTzSpecificLocalTime(NULL, &SystemTime, &LocalTime)) { m_time = LocalTime; m_isTimeParsed = true; + m_parsedTimeType = parsedTimeType; hr = S_OK; } } } } + CloseHandle(hFile); } *time = m_time; diff --git a/src/modules/powerrename/lib/PowerRenameItem.h b/src/modules/powerrename/lib/PowerRenameItem.h index 83817b0699..6ced0a3ada 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.h +++ b/src/modules/powerrename/lib/PowerRenameItem.h @@ -16,7 +16,7 @@ public: // IPowerRenameItem IFACEMETHODIMP PutPath(_In_opt_ PCWSTR newPath); IFACEMETHODIMP GetPath(_Outptr_ PWSTR* path); - IFACEMETHODIMP GetTime(_Outptr_ SYSTEMTIME* time); + IFACEMETHODIMP GetTime(_In_ DWORD flags, _Outptr_ SYSTEMTIME* time); IFACEMETHODIMP GetShellItem(_Outptr_ IShellItem** ppsi); IFACEMETHODIMP PutOriginalName(_In_opt_ PCWSTR originalName); IFACEMETHODIMP GetOriginalName(_Outptr_ PWSTR* originalName); @@ -54,6 +54,7 @@ protected: bool m_selected = true; bool m_isFolder = false; bool m_isTimeParsed = false; + PowerRenameFlags m_parsedTimeType = PowerRenameFlags::CreationTime; bool m_canRename = true; int m_id = -1; int m_iconIndex = -1; diff --git a/src/modules/powerrename/lib/Renaming.cpp b/src/modules/powerrename/lib/Renaming.cpp index bf27500529..aa21666783 100644 --- a/src/modules/powerrename/lib/Renaming.cpp +++ b/src/modules/powerrename/lib/Renaming.cpp @@ -78,7 +78,7 @@ bool DoRename(CComPtr& spRenameRegEx, unsigned long& itemEnum if (useFileTime) { - winrt::check_hresult(spItem->GetTime(&fileTime)); + winrt::check_hresult(spItem->GetTime(flags, &fileTime)); winrt::check_hresult(spRenameRegEx->PutFileTime(fileTime)); }