call for testing of latest setup.exe snapshot
Igor Peshansky
pechtcha@cs.nyu.edu
Wed Aug 16 04:39:00 GMT 2006
On Tue, 8 Aug 2006, Igor Peshansky wrote:
> On Sun, 6 Aug 2006, Brian Dessent wrote:
>
> [snip]
> > http://cygwin.com/ml/cygwin-apps/2006-02/msg00099.html
> > So, we have a couple of issues here. Firstly, the bug/unintended
> > feature of -r causing the infinite retries until the file can be
> > written (if I understand correctly.) Second the patch by Igor that
> > adds a dialog when trying to replace an in-use file.
>
> Right.
>
> > Here is my opinion on the matter: I like the dialog idea, but I don't
> > think having "Abort" as an option is appropriate, as it will
> > potentially cause a really screwed up install, plus it was left
> > unimplemented in the patch submitted. So let's just have two
> > options: "Retry" and "Replace on Reboot". I know that this means we
> > can't use the stock "Abort/Retry/Ignore" dialog but I think it's
> > worth it for clarity.
>
> Agreed on all points. However, there is a technical issue here. Stock
> MessageBoxes come in many flavors -- there actually is a Retry/Cancel box.
> There is no Retry/Continue stock box, unfortunately.
>
> We can use the Retry/Cancel one, and perhaps play some games with the
> WNDPROC of the MessageBox class to make "Cancel" look like "Replace on
> reboot" (or "Continue", which I like better -- we can explain in the
> MessageBox text that pressing "Continue" will require a reboot later), but
> I'm not sure it'll work, and it'll be ugly. Plus, I don't know that much
> about the WNDPROC, so it'll take me a bit of time to get something like
> this working.
>
> OTOH, I can change my patch to use the Retry/Cancel box today, and add the
> following to the text: "Pressing 'Cancel' will cause setup to use Windows
> mechanisms for replacing in-use files. It will be necessary for you to
> reboot after setup completes." I know, the label "Cancel" is evocative of
> aborting the whole installation, but this functionality is so useful, IMO,
> that I, for one, would put up with a little annoyance of a wrong label.
> Changing the label in a way I've described above could be a later
> enhancement.
Well, lo and behold, I overreacted. It turned out to be much easier than
I anticipated, so attached is the patch with the Retry/Continue message
box.
> > http://cygwin.com/ml/cygwin-apps/2006-01/msg00204.html
> [snip]
> However, there was another issue in that thread (the inline patch). It
> seems that applying that will cause the code to be simpler, but I'm afraid
> there's some little issue I'm missing.
I still have that one in my private sandbox, and had it in my running copy
of setup for a while with no observed problems. Any opinions?
> > If we can finish off the "Retry/Replace" file-in-use thing and assuming
> > there are no reports of new issues with this snapshot then I think we
> > can push out a release.
>
> Sounds good. If people are fine with the Retry/Cancel box, I can have a
> new patch by the end of this week.
So my weeks end on Wednesdays... :-) Since this change involved indenting
an 80-line chunk of code, I'm also attaching a whitespace-indifferent
patch for ease of reviewing. ChangeLog is below.
Igor
==============================================================================
2006-08-16 Igor Peshansky <pechtcha@cs.nyu.edu>
* install.cc (Installer::installOne): If file is in use, ask the user
to stop processes and retry.
(MB_RETRYCONTINUE, IDCONTINUE): New macros.
(hMsgBoxHook): New static field.
(CBTProc): New window hook function.
(_custom_MessageBox): New function.
* CHANGES: Update with the above.
--
http://cs.nyu.edu/~pechtcha/
|\ _,,,---,,_ pechtcha@cs.nyu.edu | igor@watson.ibm.com
ZZZzz /,`.-'`' -. ;-;;,_ Igor Peshansky, Ph.D. (name changed!)
|,4- ) )-,_. ,\ ( `'-' old name: Igor Pechtchanski
'---''(_/--' `-'\_) fL a.k.a JaguaR-R-R-r-r-r-.-.-. Meow!
"Las! je suis sot... -Mais non, tu ne l'es pas, puisque tu t'en rends compte."
"But no -- you are no fool; you call yourself a fool, there's proof enough in
that!" -- Rostand, "Cyrano de Bergerac"
-------------- next part --------------
Index: CHANGES
===================================================================
RCS file: /cvs/cygwin-apps/setup/CHANGES,v
retrieving revision 1.13
diff -u -p -r1.13 CHANGES
--- CHANGES 13 Jun 2006 14:00:23 -0000 1.13
+++ CHANGES 16 Aug 2006 03:56:05 -0000
@@ -3,6 +3,8 @@ Note: For easier maintenance try to keep
Version 2.548 (HEAD)
+ - Allow interactively retrying to replace open files.
+
- Fix unreadable chooser page due to bad background colour problem.
- Make categories named with an initial "." default to expanded display.
Index: install.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/install.cc,v
retrieving revision 2.78
diff -u -p -r2.78 install.cc
--- install.cc 16 Apr 2006 15:37:49 -0000 2.78
+++ install.cc 16 Aug 2006 03:56:06 -0000
@@ -178,6 +178,44 @@ Installer::replaceOnRebootSucceeded (con
rebootneeded = true;
}
+#define MB_RETRYCONTINUE 7
+#if !defined(IDCONTINUE)
+#define IDCONTINUE IDCANCEL
+#endif
+
+static HHOOK hMsgBoxHook;
+LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) {
+ HWND hWnd;
+ switch (nCode) {
+ case HCBT_ACTIVATE:
+ hWnd = (HWND)wParam;
+ if (GetDlgItem(hWnd, IDCANCEL) != NULL)
+ SetDlgItemText(hWnd, IDCANCEL, "Continue");
+ UnhookWindowsHookEx(hMsgBoxHook);
+ }
+ return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam);
+}
+
+int _custom_MessageBox(HWND hWnd, LPCTSTR szText, LPCTSTR szCaption, UINT uType) {
+ int retval;
+ bool retry_continue = (uType & MB_TYPEMASK) == MB_RETRYCONTINUE;
+ if (retry_continue) {
+ uType &= ~MB_TYPEMASK; uType |= MB_RETRYCANCEL;
+ // Install a window hook, so we can intercept the message-box
+ // creation, and customize it
+ // Only install for THIS thread!!!
+ hMsgBoxHook = SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId());
+ }
+ retval = MessageBox(hWnd, szText, szCaption, uType);
+ // Intercept the return value for less confusing results
+ if (retry_continue && retval == IDCANCEL)
+ return IDCONTINUE;
+ return retval;
+}
+
+#undef MessageBox
+#define MessageBox _custom_MessageBox
+
/* install one source at a given prefix. */
void
Installer::installOne (packagemeta &pkgm, const packageversion &ver,
@@ -205,6 +243,7 @@ Installer::installOne (packagemeta &pkgm
io_stream *tmp = io_stream::open (source.Cached (), "rb");
io_stream *tmp2 = 0;
archive *thefile = 0;
+ bool ignoreExtractErrors = unattended_mode;
if (tmp)
{
tmp2 = compress::decompress (tmp);
@@ -253,74 +292,101 @@ Installer::installOne (packagemeta &pkgm
Progress.SetText3 (canonicalfn.c_str());
log (LOG_BABBLE) << "Installing file " << prefixURL << prefixPath
<< fn << endLog;
- if (archive::extract_file (thefile, prefixURL, prefixPath) != 0)
+ bool firstIteration = true;
+ while (archive::extract_file (thefile, prefixURL, prefixPath) != 0)
{
- if (NoReplaceOnReboot)
+ if (!ignoreExtractErrors)
{
- ++errors;
- error_in_this_package = true;
- log (LOG_PLAIN) << "Not replacing in-use file "
- << prefixURL << prefixPath << fn << endLog;
+ char msg[fn.size() + 300];
+ sprintf (msg,
+ "%snable to extract /%s -- the file is in use.\r\n"
+ "Please stop %s Cygwin processes and select \"Retry\", or\r\n"
+ "select \"Continue\" to go on anyway (you will need to reboot).\r\n",
+ firstIteration?"U":"Still u", fn.c_str(), firstIteration?"all":"ALL");
+ switch (MessageBox
+ (NULL, msg, "In-use files detected",
+ MB_RETRYCONTINUE | MB_ICONWARNING | MB_TASKMODAL))
+ {
+ case IDRETRY:
+ // retry
+ firstIteration = false;
+ continue;
+ case IDCONTINUE:
+ ignoreExtractErrors = true;
+ break;
+ default:
+ break;
+ }
+ // fall through to previous functionality
}
- else
- //extract to temp location
- if (archive::extract_file (thefile, prefixURL, prefixPath, ".new") != 0)
+ if (NoReplaceOnReboot)
{
- log (LOG_PLAIN) << "Unable to install file "
- << prefixURL << prefixPath << fn << endLog;
++errors;
- error_in_this_package = true;
+ error_in_this_package = true;
+ log (LOG_PLAIN) << "Not replacing in-use file "
+ << prefixURL << prefixPath << fn << endLog;
}
else
- {
- if (!IsWindowsNT())
- {
- /* Get the short file names */
- char source[MAX_PATH];
- unsigned int len =
- GetShortPathName(cygpath("/" + fn + ".new").c_str(),
- source, MAX_PATH);
- if (!len || len > MAX_PATH)
- {
- replaceOnRebootFailed(fn);
- }
- else
- {
- char dest[MAX_PATH];
- len =
- GetShortPathName(cygpath("/" + fn).c_str(),
- dest, MAX_PATH);
- if (!len || len > MAX_PATH)
- replaceOnRebootFailed (fn);
- else
- /* trigger a replacement on reboot */
- if (!WritePrivateProfileString
- ("rename", dest, source, "WININIT.INI"))
- replaceOnRebootFailed (fn);
- else
- replaceOnRebootSucceeded (fn, rebootneeded);
- }
- }
- else
- {
- /* XXX FIXME: prefix may not be / for in use files -
- * although it most likely is
- * - we need a io method to get win32 paths
- * or to wrap this system call
- */
- if (!MoveFileEx(cygpath("/" + fn + ".new").c_str(),
- cygpath("/" + fn).c_str(),
- MOVEFILE_DELAY_UNTIL_REBOOT |
- MOVEFILE_REPLACE_EXISTING))
- {
- replaceOnRebootFailed (fn);
- }
- else
- {
- replaceOnRebootSucceeded (fn, rebootneeded);
- }
- }
- }
+ //extract to temp location
+ if (archive::extract_file (thefile, prefixURL, prefixPath, ".new") != 0)
+ {
+ log (LOG_PLAIN) << "Unable to install file "
+ << prefixURL << prefixPath << fn << endLog;
+ ++errors;
+ error_in_this_package = true;
+ }
+ else
+ {
+ if (!IsWindowsNT())
+ {
+ /* Get the short file names */
+ char source[MAX_PATH];
+ unsigned int len =
+ GetShortPathName(cygpath("/" + fn + ".new").c_str(),
+ source, MAX_PATH);
+ if (!len || len > MAX_PATH)
+ {
+ replaceOnRebootFailed(fn);
+ }
+ else
+ {
+ char dest[MAX_PATH];
+ len =
+ GetShortPathName(cygpath("/" + fn).c_str(),
+ dest, MAX_PATH);
+ if (!len || len > MAX_PATH)
+ replaceOnRebootFailed (fn);
+ else
+ /* trigger a replacement on reboot */
+ if (!WritePrivateProfileString
+ ("rename", dest, source, "WININIT.INI"))
+ replaceOnRebootFailed (fn);
+ else
+ replaceOnRebootSucceeded (fn, rebootneeded);
+ }
+ }
+ else
+ {
+ /* XXX FIXME: prefix may not be / for in use files -
+ * although it most likely is
+ * - we need a io method to get win32 paths
+ * or to wrap this system call
+ */
+ if (!MoveFileEx(cygpath("/" + fn + ".new").c_str(),
+ cygpath("/" + fn).c_str(),
+ MOVEFILE_DELAY_UNTIL_REBOOT |
+ MOVEFILE_REPLACE_EXISTING))
+ {
+ replaceOnRebootFailed (fn);
+ }
+ else
+ {
+ replaceOnRebootSucceeded (fn, rebootneeded);
+ }
+ }
+ }
+ // We're done with this file
+ break;
}
progress (tmp->tell ());
num_installs++;
-------------- next part --------------
Index: CHANGES
===================================================================
RCS file: /cvs/cygwin-apps/setup/CHANGES,v
retrieving revision 1.13
diff -u -p -b -B -r1.13 CHANGES
--- CHANGES 13 Jun 2006 14:00:23 -0000 1.13
+++ CHANGES 16 Aug 2006 04:21:08 -0000
@@ -3,6 +3,8 @@ Note: For easier maintenance try to keep
Version 2.548 (HEAD)
+ - Allow interactively retrying to replace open files.
+
- Fix unreadable chooser page due to bad background colour problem.
- Make categories named with an initial "." default to expanded display.
Index: install.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/install.cc,v
retrieving revision 2.78
diff -u -p -b -B -r2.78 install.cc
--- install.cc 16 Apr 2006 15:37:49 -0000 2.78
+++ install.cc 16 Aug 2006 04:21:09 -0000
@@ -178,6 +178,44 @@ Installer::replaceOnRebootSucceeded (con
rebootneeded = true;
}
+#define MB_RETRYCONTINUE 7
+#if !defined(IDCONTINUE)
+#define IDCONTINUE IDCANCEL
+#endif
+
+static HHOOK hMsgBoxHook;
+LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) {
+ HWND hWnd;
+ switch (nCode) {
+ case HCBT_ACTIVATE:
+ hWnd = (HWND)wParam;
+ if (GetDlgItem(hWnd, IDCANCEL) != NULL)
+ SetDlgItemText(hWnd, IDCANCEL, "Continue");
+ UnhookWindowsHookEx(hMsgBoxHook);
+ }
+ return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam);
+}
+
+int _custom_MessageBox(HWND hWnd, LPCTSTR szText, LPCTSTR szCaption, UINT uType) {
+ int retval;
+ bool retry_continue = (uType & MB_TYPEMASK) == MB_RETRYCONTINUE;
+ if (retry_continue) {
+ uType &= ~MB_TYPEMASK; uType |= MB_RETRYCANCEL;
+ // Install a window hook, so we can intercept the message-box
+ // creation, and customize it
+ // Only install for THIS thread!!!
+ hMsgBoxHook = SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId());
+ }
+ retval = MessageBox(hWnd, szText, szCaption, uType);
+ // Intercept the return value for less confusing results
+ if (retry_continue && retval == IDCANCEL)
+ return IDCONTINUE;
+ return retval;
+}
+
+#undef MessageBox
+#define MessageBox _custom_MessageBox
+
/* install one source at a given prefix. */
void
Installer::installOne (packagemeta &pkgm, const packageversion &ver,
@@ -205,6 +243,7 @@ Installer::installOne (packagemeta &pkgm
io_stream *tmp = io_stream::open (source.Cached (), "rb");
io_stream *tmp2 = 0;
archive *thefile = 0;
+ bool ignoreExtractErrors = unattended_mode;
if (tmp)
{
tmp2 = compress::decompress (tmp);
@@ -253,8 +292,33 @@ Installer::installOne (packagemeta &pkgm
Progress.SetText3 (canonicalfn.c_str());
log (LOG_BABBLE) << "Installing file " << prefixURL << prefixPath
<< fn << endLog;
- if (archive::extract_file (thefile, prefixURL, prefixPath) != 0)
+ bool firstIteration = true;
+ while (archive::extract_file (thefile, prefixURL, prefixPath) != 0)
+ {
+ if (!ignoreExtractErrors)
+ {
+ char msg[fn.size() + 300];
+ sprintf (msg,
+ "%snable to extract /%s -- the file is in use.\r\n"
+ "Please stop %s Cygwin processes and select \"Retry\", or\r\n"
+ "select \"Continue\" to go on anyway (you will need to reboot).\r\n",
+ firstIteration?"U":"Still u", fn.c_str(), firstIteration?"all":"ALL");
+ switch (MessageBox
+ (NULL, msg, "In-use files detected",
+ MB_RETRYCONTINUE | MB_ICONWARNING | MB_TASKMODAL))
{
+ case IDRETRY:
+ // retry
+ firstIteration = false;
+ continue;
+ case IDCONTINUE:
+ ignoreExtractErrors = true;
+ break;
+ default:
+ break;
+ }
+ // fall through to previous functionality
+ }
if (NoReplaceOnReboot)
{
++errors;
@@ -321,6 +385,8 @@ Installer::installOne (packagemeta &pkgm
}
}
}
+ // We're done with this file
+ break;
}
progress (tmp->tell ());
num_installs++;
More information about the Cygwin-apps
mailing list