From 40575f7676e51183a40e3a9cb4c7e8052f17a946 Mon Sep 17 00:00:00 2001 From: lopple <5253526+lopple@users.noreply.github.com> Date: Thu, 25 Jun 2026 19:04:42 +0900 Subject: [PATCH] Add option to open destination folder after extraction --- CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 4 ++++ CPP/7zip/UI/Common/CompressCall.cpp | 12 +++++++++++- CPP/7zip/UI/Common/CompressCall.h | 5 ++++- CPP/7zip/UI/Common/CompressCall2.cpp | 9 ++++++++- CPP/7zip/UI/Common/Extract.h | 2 ++ CPP/7zip/UI/Common/ZipRegistry.cpp | 14 ++++++++++++++ CPP/7zip/UI/Common/ZipRegistry.h | 2 ++ CPP/7zip/UI/Explorer/ContextMenu.cpp | 4 +++- CPP/7zip/UI/GUI/ExtractDialog.cpp | 12 ++++++++++++ CPP/7zip/UI/GUI/ExtractDialog.h | 4 +++- CPP/7zip/UI/GUI/ExtractDialog.rc | 2 ++ CPP/7zip/UI/GUI/ExtractDialogRes.h | 1 + CPP/7zip/UI/GUI/ExtractGUI.cpp | 17 +++++++++++++++++ 13 files changed, 83 insertions(+), 5 deletions(-) diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index f2738706..3825c7df 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -188,6 +188,7 @@ enum Enum kUseSlashMark, kDisableWildcardParsing, kElimDup, + kOpenDestFolder, kFullPathMode, kOutDirMode, @@ -340,6 +341,7 @@ static const CSwitchForm kSwitchForms[] = { "spm", SWFRM_STRING_SINGL(0) }, { "spd", SWFRM_SIMPLE }, { "spe", SWFRM_MINUS }, + { "sod", SWFRM_SIMPLE }, { "spf", SWFRM_STRING_SINGL(0) }, { "spo", NSwitchType::kChar, false, 1, "dcr" }, // kOutDirMode @@ -1464,6 +1466,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) options.ExtractOptions.ElimDup.Def = true; options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; } + if (parser[NKey::kOpenDestFolder].ThereIs) + options.ExtractOptions.OpenDestFolderAfterExtract = true; NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index 1ded1b39..bb95dbb2 100644 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -38,6 +38,7 @@ using namespace NWindows; #define ISWITCH_NO_WILDCARD_POSTFIX #define kShowDialogSwitch " -ad" +#define kOpenDestFolderSwitch " -sod" #define kEmailSwitch " -seml." #define kArchiveTypeSwitch " -t" #define kIncludeSwitch " -i" ISWITCH_NO_WILDCARD_POSTFIX @@ -252,7 +253,8 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, ErrorMessageHRESULT(result); } -void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone) +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, + bool showDialog, bool elimDup, UInt32 writeZone, bool openDestFolder) { MY_TRY_BEGIN UString params ('x'); @@ -270,10 +272,18 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo } if (showDialog) params += kShowDialogSwitch; + if (openDestFolder) + params += kOpenDestFolderSwitch; ExtractGroupCommand(arcPaths, params, false); MY_TRY_FINISH_VOID } +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, + bool showDialog, bool elimDup, UInt32 writeZone) +{ + ExtractArchives(arcPaths, outFolder, showDialog, elimDup, writeZone, false); +} + void TestArchives(const UStringVector &arcPaths, bool hashMode) { diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h index f2da1631..c1c6174d 100644 --- a/CPP/7zip/UI/Common/CompressCall.h +++ b/CPP/7zip/UI/Common/CompressCall.h @@ -15,7 +15,10 @@ HRESULT CompressFiles( const UStringVector &names, bool email, bool showDialog, bool waitFinish); -void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone); +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, + bool showDialog, bool elimDup, UInt32 writeZone); +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, + bool showDialog, bool elimDup, UInt32 writeZone, bool openDestFolder); void TestArchives(const UStringVector &arcPaths, bool hashMode = false); void CalcChecksum(const UStringVector &paths, diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp index fef0877a..228c671c 100644 --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -224,11 +224,12 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, } void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, - bool showDialog, bool elimDup, UInt32 writeZone) + bool showDialog, bool elimDup, UInt32 writeZone, bool openDestFolder) { CExtractOptions eo; eo.OutputDir = us2fs(outFolder); eo.TestMode = false; + eo.OpenDestFolderAfterExtract = openDestFolder; eo.ElimDup.Val = elimDup; eo.ElimDup.Def = elimDup; if (writeZone != (UInt32)(Int32)-1) @@ -236,6 +237,12 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, ExtractGroupCommand(arcPaths, showDialog, eo); } +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, + bool showDialog, bool elimDup, UInt32 writeZone) +{ + ExtractArchives(arcPaths, outFolder, showDialog, elimDup, writeZone, false); +} + void TestArchives(const UStringVector &arcPaths, bool hashMode) { CExtractOptions eo; diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index 130f55a9..6aa54c56 100644 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -32,6 +32,7 @@ struct CExtractOptionsBase bool PathMode_Force; bool OverwriteMode_Force; + bool OpenDestFolderAfterExtract; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; NExtract::NZoneIdMode::EEnum ZoneMode; @@ -47,6 +48,7 @@ struct CExtractOptionsBase ExcludeFileItems(false), PathMode_Force(false), OverwriteMode_Force(false), + OpenDestFolderAfterExtract(false), PathMode(NExtract::NPathMode::kFullPaths), OverwriteMode(NExtract::NOverwriteMode::kAsk), ZoneMode(NExtract::NZoneIdMode::kNone), diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 936b8881..096f071e 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -96,6 +96,7 @@ static LPCTSTR const kShowPassword = TEXT("ShowPassword"); static LPCTSTR const kPathHistory = TEXT("PathHistory"); static LPCTSTR const kSplitDest = TEXT("SplitDest"); static LPCTSTR const kElimDup = TEXT("ElimDup"); +static LPCTSTR const kOpenDestFolder = TEXT("OpenDestFolder"); // static LPCTSTR const kAltStreams = TEXT("AltStreams"); static LPCTSTR const kNtSecur = TEXT("Security"); static LPCTSTR const kMemLimit = TEXT("MemLimit"); @@ -113,6 +114,7 @@ void CInfo::Save() const Key_Set_BoolPair(key, kSplitDest, SplitDest); Key_Set_BoolPair(key, kElimDup, ElimDup); + Key_Set_BoolPair(key, kOpenDestFolder, OpenDestFolder); // Key_Set_BoolPair(key, kAltStreams, AltStreams); Key_Set_BoolPair(key, kNtSecur, NtSecurity); Key_Set_BoolPair(key, kShowPassword, ShowPassword); @@ -169,6 +171,7 @@ void CInfo::Load() Key_Get_BoolPair_true(key, kSplitDest, SplitDest); Key_Get_BoolPair(key, kElimDup, ElimDup); + Key_Get_BoolPair(key, kOpenDestFolder, OpenDestFolder); // Key_Get_BoolPair(key, kAltStreams, AltStreams); Key_Get_BoolPair(key, kNtSecur, NtSecurity); Key_Get_BoolPair(key, kShowPassword, ShowPassword); @@ -185,6 +188,17 @@ bool Read_ShowPassword() return showPassword; } +bool Read_OpenDestFolder() +{ + CS_LOCK + CKey key; + bool openDestFolder = false; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return openDestFolder; + key.GetValue_bool_IfOk(kOpenDestFolder, openDestFolder); + return openDestFolder; +} + UInt32 Read_LimitGB() { CS_LOCK diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index ce084f4e..e4aab87e 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -31,6 +31,7 @@ namespace NExtract CBoolPair SplitDest; CBoolPair ElimDup; + CBoolPair OpenDestFolder; // CBoolPair AltStreams; CBoolPair NtSecurity; CBoolPair ShowPassword; @@ -43,6 +44,7 @@ namespace NExtract void Save_ShowPassword(bool showPassword); bool Read_ShowPassword(); + bool Read_OpenDestFolder(); void Save_LimitGB(UInt32 limit_GB); UInt32 Read_LimitGB(); diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 0630d78e..3149c218 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -1282,10 +1282,12 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi) ShowErrorMessageRes(IDS_SELECT_FILES); break; } + const bool openDestFolder = (cmdID == kExtractTo) && NExtract::Read_OpenDestFolder(); ExtractArchives(_fileNames, cmi.Folder, (cmdID == kExtract), // showDialog (cmdID == kExtractTo) && _elimDup.Val, // elimDup - _writeZone + _writeZone, + openDestFolder ); break; } diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index 467cf18f..5d27dcef 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -80,6 +80,7 @@ static const UInt32 kLangIDs[] = // IDX_EXTRACT_ALT_STREAMS, IDX_EXTRACT_NT_SECUR, IDX_EXTRACT_ELIM_DUP, + IDX_EXTRACT_OPEN_DEST_FOLDER, IDG_PASSWORD, IDX_PASSWORD_SHOW }; @@ -180,12 +181,15 @@ bool CExtractDialog::OnInit() // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + OpenDestFolder = _info.OpenDestFolder.Val; CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val); UpdatePasswordControl(); #endif + CheckButton(IDX_EXTRACT_OPEN_DEST_FOLDER, OpenDestFolder); + _path.Attach(GetItem(IDC_EXTRACT_PATH)); UString pathPrefix = DirPath; @@ -318,6 +322,13 @@ void CExtractDialog::OnOK() GetButton_Bools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); GetButton_Bools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + OpenDestFolder = IsButtonCheckedBool(IDX_EXTRACT_OPEN_DEST_FOLDER); + if (OpenDestFolder != _info.OpenDestFolder.Val) + { + _info.OpenDestFolder.Def = true; + _info.OpenDestFolder.Val = OpenDestFolder; + } + bool showPassword = IsShowPasswordChecked(); if (showPassword != _info.ShowPassword.Val) { @@ -344,6 +355,7 @@ void CExtractDialog::OnOK() #else ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); + OpenDestFolder = IsButtonCheckedBool(IDX_EXTRACT_OPEN_DEST_FOLDER); #endif diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h index 1565fb8a..36335e5a 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.h +++ b/CPP/7zip/UI/GUI/ExtractDialog.h @@ -90,6 +90,7 @@ class CExtractDialog: public NWindows::NControl::CModalDialog #endif CBoolPair ElimDup; + bool OpenDestFolder; INT_PTR Create(HWND aWndParent = NULL) { @@ -103,7 +104,8 @@ class CExtractDialog: public NWindows::NControl::CModalDialog CExtractDialog(): PathMode_Force(false), - OverwriteMode_Force(false) + OverwriteMode_Force(false), + OpenDestFolder(false) { ElimDup.Val = true; } diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc index 3728b96d..19670276 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.rc +++ b/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -53,6 +53,8 @@ BEGIN // g2x, m + 104, g2xs, 10 CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX, g2x, m + 104, g2xs, 10 + CONTROL "Open destination folder after extraction", IDX_EXTRACT_OPEN_DEST_FOLDER, MY_CHECKBOX, + m, m + 140, xc, 10 DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h index ed12bfb3..fa25afd7 100644 --- a/CPP/7zip/UI/GUI/ExtractDialogRes.h +++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h @@ -19,6 +19,7 @@ #define IDX_EXTRACT_ELIM_DUP 3430 #define IDX_EXTRACT_NT_SECUR 3431 // #define IDX_EXTRACT_ALT_STREAMS 3432 +#define IDX_EXTRACT_OPEN_DEST_FOLDER 3433 #define IDX_PASSWORD_SHOW 3803 #define IDG_PASSWORD 3807 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index bafff2ba..64ff5f8f 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -36,6 +36,19 @@ using namespace NDir; static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path"; +static void OpenFolderInExplorer(CFSTR path) +{ + #ifdef UNDER_CE + SHELLEXECUTEINFO s; + memset(&s, 0, sizeof(s)); + s.cbSize = sizeof(s); + s.lpFile = path; + ::ShellExecuteEx(&s); + #else + ::ShellExecute(NULL, NULL, path, NULL, NULL, SW_SHOWNORMAL); + #endif +} + #ifndef Z7_SFX static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true) @@ -182,6 +195,7 @@ HRESULT ExtractGUI( HWND hwndParent) { messageWasDisplayed = false; + bool openDestFolder = options.OpenDestFolderAfterExtract; CThreadExtracting extracter; /* @@ -234,6 +248,7 @@ HRESULT ExtractGUI( return E_ABORT; outputDir = us2fs(dialog.DirPath); + openDestFolder = dialog.OpenDestFolder; options.OverwriteMode = dialog.OverwriteMode; options.PathMode = dialog.PathMode; @@ -293,5 +308,7 @@ HRESULT ExtractGUI( RINOK(extracter.Create(title, hwndParent)) messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed; + if (openDestFolder && extracter.Result == S_OK && extractCallback->IsOK()) + OpenFolderInExplorer(options.OutputDir); return extracter.Result; }