feat: 支持选择RPA安装目录

This commit is contained in:
yu 2026-10-27 18:23:25 +08:00
parent 12de8fbf58
commit f675cc0086

View File

@ -248,6 +248,70 @@ void validateApplication(const fs::path& directory) {
if (!fs::exists(asar) || fs::file_size(asar) < 1024 * 1024) fail(L"resources\\app.asar 缺失或不完整。");
}
bool chooseInstallDirectory(const fs::path& currentTarget, fs::path& selectedTarget) {
HRESULT initialized = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
IFileOpenDialog* dialog = nullptr;
HRESULT result = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_IFileOpenDialog,
reinterpret_cast<void**>(&dialog));
if (FAILED(result) || !dialog) {
if (SUCCEEDED(initialized)) CoUninitialize();
fail(L"无法打开安装目录选择窗口。");
}
FILEOPENDIALOGOPTIONS options = 0;
dialog->GetOptions(&options);
dialog->SetOptions(options | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_DONTADDTORECENT);
dialog->SetTitle(L"选择 RPA Studio 的安装位置");
dialog->SetOkButtonLabel(L"选择此文件夹");
dialog->SetFileName(L"RPA Studio");
fs::path initial = currentTarget.parent_path();
while (!initial.empty() && !fs::exists(initial)) initial = initial.parent_path();
if (!initial.empty()) {
IShellItem* initialItem = nullptr;
if (SUCCEEDED(SHCreateItemFromParsingName(initial.c_str(), nullptr, IID_IShellItem,
reinterpret_cast<void**>(&initialItem))) && initialItem) {
dialog->SetFolder(initialItem);
initialItem->Release();
}
}
result = dialog->Show(nullptr);
if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
dialog->Release();
if (SUCCEEDED(initialized)) CoUninitialize();
return false;
}
if (FAILED(result)) {
dialog->Release();
if (SUCCEEDED(initialized)) CoUninitialize();
fail(L"安装目录选择失败。");
}
IShellItem* selectedItem = nullptr;
result = dialog->GetResult(&selectedItem);
dialog->Release();
if (FAILED(result) || !selectedItem) {
if (SUCCEEDED(initialized)) CoUninitialize();
fail(L"无法读取所选安装目录。");
}
PWSTR selectedPath = nullptr;
result = selectedItem->GetDisplayName(SIGDN_FILESYSPATH, &selectedPath);
selectedItem->Release();
if (FAILED(result) || !selectedPath) {
if (SUCCEEDED(initialized)) CoUninitialize();
fail(L"所选位置不是有效的本地文件夹。");
}
fs::path parent(selectedPath);
CoTaskMemFree(selectedPath);
if (SUCCEEDED(initialized)) CoUninitialize();
selectedTarget = lower(parent.filename().wstring()) == L"rpa studio" ? parent : parent / L"RPA Studio";
selectedTarget = fs::absolute(selectedTarget).lexically_normal();
return true;
}
void createShortcut(const fs::path& targetExecutable, const fs::path& workingDirectory) {
HRESULT initialized = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
IShellLinkW* shellLink = nullptr;
@ -350,6 +414,9 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) {
silent = options.silent;
logLine(L"installer started");
if (!options.silent) {
fs::path selectedTarget;
if (!chooseInstallDirectory(options.target, selectedTarget)) return 0;
options.target = selectedTarget;
std::wstring prompt = L"将 RPA Studio __PRODUCT_VERSION__ 安装到当前 Windows 用户?\r\n\r\n安装位置:" +
options.target.wstring();
if (MessageBoxW(nullptr, prompt.c_str(), L"RPA Studio 安装", MB_YESNO | MB_ICONQUESTION | MB_SETFOREGROUND) != IDYES)