mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-07-04 01:20:02 +02:00
Compare commits
3 Commits
copilot/fi
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9679b937d | ||
|
|
36300d3c75 | ||
|
|
1cde68ae04 |
@@ -14,7 +14,6 @@
|
||||
#include <shellapi.h>
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include <memory>
|
||||
|
||||
@@ -334,105 +334,6 @@ namespace newplus::utilities
|
||||
}
|
||||
}
|
||||
|
||||
// Watches for the user renaming a newly-created folder, then resolves $PARENT_FOLDER_NAME
|
||||
// in its child files using the final (user-given) name.
|
||||
// If no rename is detected within timeout_ms, resolves using the original folder name.
|
||||
// Must be called from a background thread; runs until the rename is detected or timeout expires.
|
||||
inline void watch_for_rename_then_resolve_variables(
|
||||
const std::filesystem::path& parent_dir,
|
||||
const std::wstring& original_folder_name,
|
||||
const DWORD timeout_ms = 30000)
|
||||
{
|
||||
std::filesystem::path final_target_path = parent_dir / original_folder_name;
|
||||
|
||||
HANDLE dir_handle = CreateFileW(
|
||||
parent_dir.c_str(),
|
||||
FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||
nullptr);
|
||||
|
||||
if (dir_handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HANDLE event_handle = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
if (event_handle)
|
||||
{
|
||||
OVERLAPPED overlapped = {};
|
||||
overlapped.hEvent = event_handle;
|
||||
|
||||
std::vector<BYTE> buffer(32768, 0);
|
||||
|
||||
if (ReadDirectoryChangesW(
|
||||
dir_handle,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size()),
|
||||
FALSE,
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
nullptr,
|
||||
&overlapped,
|
||||
nullptr))
|
||||
{
|
||||
const DWORD wait_result = WaitForSingleObject(event_handle, timeout_ms);
|
||||
|
||||
if (wait_result == WAIT_TIMEOUT)
|
||||
{
|
||||
CancelIo(dir_handle);
|
||||
}
|
||||
|
||||
// Wait for the I/O to fully complete (either normally or after cancellation)
|
||||
// before touching the OVERLAPPED or closing handles.
|
||||
DWORD bytes_returned = 0;
|
||||
const bool io_succeeded = GetOverlappedResult(dir_handle, &overlapped, &bytes_returned, TRUE) != FALSE;
|
||||
|
||||
if (wait_result == WAIT_OBJECT_0 && io_succeeded && bytes_returned > 0)
|
||||
{
|
||||
auto* notify_info = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer.data());
|
||||
bool found_old_name = false;
|
||||
|
||||
while (notify_info)
|
||||
{
|
||||
const std::wstring filename(
|
||||
notify_info->FileName,
|
||||
notify_info->FileNameLength / sizeof(wchar_t));
|
||||
|
||||
if (!found_old_name &&
|
||||
notify_info->Action == FILE_ACTION_RENAMED_OLD_NAME &&
|
||||
wstring_same_when_comparing_ignore_case(filename, original_folder_name))
|
||||
{
|
||||
found_old_name = true;
|
||||
}
|
||||
else if (found_old_name && notify_info->Action == FILE_ACTION_RENAMED_NEW_NAME)
|
||||
{
|
||||
final_target_path = parent_dir / filename;
|
||||
break;
|
||||
}
|
||||
|
||||
if (notify_info->NextEntryOffset == 0)
|
||||
break;
|
||||
notify_info = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
|
||||
reinterpret_cast<BYTE*>(notify_info) + notify_info->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(event_handle);
|
||||
CloseHandle(dir_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(dir_handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve $PARENT_FOLDER_NAME in child files using the final folder name
|
||||
if (std::filesystem::exists(final_target_path) && std::filesystem::is_directory(final_target_path))
|
||||
{
|
||||
helpers::variables::resolve_variables_in_filename_and_rename_files(final_target_path);
|
||||
}
|
||||
}
|
||||
|
||||
inline HRESULT copy_template(const template_item* template_entry, const ComPtr<IUnknown> site_of_folder)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
@@ -475,18 +376,10 @@ namespace newplus::utilities
|
||||
// Finally copy file/folder/subfolders
|
||||
std::filesystem::path target_final_fullpath = template_entry->copy_object_to(GetActiveWindow(), target_fullpath);
|
||||
|
||||
// Resolve variables and rename files in newly copied folders and subfolders.
|
||||
// For directory templates the top-level folder name is only known after the user
|
||||
// completes the rename-on-creation prompt, so defer resolution until then so that
|
||||
// $PARENT_FOLDER_NAME picks up the user-given name rather than the template name.
|
||||
// The watcher must be started before enter_rename_mode so the rename event is not missed.
|
||||
// Resolve variables and rename files in newly copied folders and subfolders and files
|
||||
if (utilities::get_newplus_setting_resolve_variables() && helpers::filesystem::is_directory(target_final_fullpath))
|
||||
{
|
||||
auto parent_dir = target_final_fullpath.parent_path();
|
||||
auto original_folder_name = target_final_fullpath.filename().wstring();
|
||||
std::thread([parent_dir = std::move(parent_dir), original_folder_name = std::move(original_folder_name)]() {
|
||||
watch_for_rename_then_resolve_variables(parent_dir, original_folder_name);
|
||||
}).detach();
|
||||
helpers::variables::resolve_variables_in_filename_and_rename_files(target_final_fullpath);
|
||||
}
|
||||
|
||||
// Touch all files and set last modified to "now"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include <memory>
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
@@ -135,7 +136,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
private void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e)
|
||||
{
|
||||
throw e.Exception;
|
||||
var sourcePage = e.SourcePageType?.FullName ?? "<unknown>";
|
||||
|
||||
if (e.Exception is null)
|
||||
{
|
||||
Logger.LogWarning($"Navigation to '{sourcePage}' failed without an exception.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError($"Navigation to '{sourcePage}' failed.", e.Exception);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void Frame_Navigated(object sender, NavigationEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user