aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-03-18 20:16:07 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-03-19 12:07:32 -0500
commitfbc1a73743368211d5d8c7fc0625adf6eb9ca50c (patch)
treec314d72b4b25afab7a27be664a1bffa5bdd80b3a /src
parentfb54576f1d05e82ba47cd718c4c4f8b3bad624c9 (diff)
downloadwix-fbc1a73743368211d5d8c7fc0625adf6eb9ca50c.tar.gz
wix-fbc1a73743368211d5d8c7fc0625adf6eb9ca50c.tar.bz2
wix-fbc1a73743368211d5d8c7fc0625adf6eb9ca50c.zip
Add checkpoint so Exe and Msu packages rollback after being cancelled.
Fixes 5950
Diffstat (limited to 'src')
-rw-r--r--src/burn/engine/apply.cpp93
-rw-r--r--src/burn/engine/apply.h2
-rw-r--r--src/burn/engine/elevation.cpp18
-rw-r--r--src/burn/engine/engine.mc7
-rw-r--r--src/burn/engine/exeengine.cpp37
-rw-r--r--src/burn/engine/msuengine.cpp27
-rw-r--r--src/burn/engine/package.h1
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp4
-rw-r--r--src/test/burn/TestBA/TestBA.cs25
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs14
10 files changed, 171 insertions, 57 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 73b5b396..6af5c040 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -63,6 +63,7 @@ typedef struct _BURN_EXECUTE_CONTEXT
63 LPCWSTR wzExecutingPackageId; 63 LPCWSTR wzExecutingPackageId;
64 DWORD cExecutedPackages; 64 DWORD cExecutedPackages;
65 DWORD cExecutePackagesTotal; 65 DWORD cExecutePackagesTotal;
66 BOOL fAbandonedProcess;
66} BURN_EXECUTE_CONTEXT; 67} BURN_EXECUTE_CONTEXT;
67 68
68 69
@@ -322,6 +323,7 @@ static HRESULT ExecutePackageComplete(
322 __in BURN_VARIABLES* pVariables, 323 __in BURN_VARIABLES* pVariables,
323 __in LPCWSTR wzPackageId, 324 __in LPCWSTR wzPackageId,
324 __in BOOL fPackageVital, 325 __in BOOL fPackageVital,
326 __in BOOL fAbandonedProcess,
325 __in HRESULT hrOverall, 327 __in HRESULT hrOverall,
326 __in HRESULT hrExecute, 328 __in HRESULT hrExecute,
327 __in BOOL fRollback, 329 __in BOOL fRollback,
@@ -369,6 +371,7 @@ extern "C" void ApplyReset(
369 BURN_PACKAGE* pPackage = pPackages->rgPackages + i; 371 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
370 pPackage->hrCacheResult = S_OK; 372 pPackage->hrCacheResult = S_OK;
371 pPackage->fReachedExecution = FALSE; 373 pPackage->fReachedExecution = FALSE;
374 pPackage->fAbandonedProcess = FALSE;
372 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 375 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
373 } 376 }
374} 377}
@@ -715,6 +718,9 @@ extern "C" HRESULT ApplyExecute(
715 continue; 718 continue;
716 } 719 }
717 720
721 context.wzExecutingPackageId = NULL;
722 context.fAbandonedProcess = FALSE;
723
718 // If we are seeking the end of the rollback boundary, skip if this action wasn't it. 724 // If we are seeking the end of the rollback boundary, skip if this action wasn't it.
719 if (fSeekRollbackBoundaryEnd) 725 if (fSeekRollbackBoundaryEnd)
720 { 726 {
@@ -2437,6 +2443,9 @@ static HRESULT DoRollbackActions(
2437 continue; 2443 continue;
2438 } 2444 }
2439 2445
2446 pContext->wzExecutingPackageId = NULL;
2447 pContext->fAbandonedProcess = FALSE;
2448
2440 if (BURN_EXECUTE_ACTION_TYPE_CHECKPOINT == pRollbackAction->type) 2449 if (BURN_EXECUTE_ACTION_TYPE_CHECKPOINT == pRollbackAction->type)
2441 { 2450 {
2442 if (pRollbackAction->checkpoint.dwId == dwCheckpoint) 2451 if (pRollbackAction->checkpoint.dwId == dwCheckpoint)
@@ -2533,6 +2542,28 @@ LExit:
2533 return hr; 2542 return hr;
2534} 2543}
2535 2544
2545static BOOL ShouldSkipPackage(
2546 __in BURN_PACKAGE* pPackage,
2547 __in BOOL fRollback
2548 )
2549{
2550 BOOL fSkip = FALSE;
2551
2552 if (FAILED(pPackage->hrCacheResult))
2553 {
2554 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2555 ExitFunction1(fSkip = TRUE);
2556 }
2557 else if (fRollback && pPackage->fAbandonedProcess)
2558 {
2559 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_PACKAGE_WITH_ABANDONED_PROCESS, pPackage->sczId);
2560 ExitFunction1(fSkip = TRUE);
2561 }
2562
2563LExit:
2564 return fSkip;
2565}
2566
2536static HRESULT ExecuteRelatedBundle( 2567static HRESULT ExecuteRelatedBundle(
2537 __in BURN_ENGINE_STATE* pEngineState, 2568 __in BURN_ENGINE_STATE* pEngineState,
2538 __in BURN_EXECUTE_ACTION* pExecuteAction, 2569 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -2551,13 +2582,13 @@ static HRESULT ExecuteRelatedBundle(
2551 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle; 2582 BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
2552 BURN_PACKAGE* pPackage = &pRelatedBundle->package; 2583 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
2553 2584
2554 if (FAILED(pPackage->hrCacheResult)) 2585 Assert(pContext->fRollback == fRollback);
2586
2587 if (ShouldSkipPackage(pPackage, fRollback))
2555 { 2588 {
2556 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2557 ExitFunction1(hr = S_OK); 2589 ExitFunction1(hr = S_OK);
2558 } 2590 }
2559 2591
2560 Assert(pContext->fRollback == fRollback);
2561 pContext->wzExecutingPackageId = pPackage->sczId; 2592 pContext->wzExecutingPackageId = pPackage->sczId;
2562 fBeginCalled = TRUE; 2593 fBeginCalled = TRUE;
2563 2594
@@ -2599,7 +2630,8 @@ static HRESULT ExecuteRelatedBundle(
2599LExit: 2630LExit:
2600 if (fBeginCalled) 2631 if (fBeginCalled)
2601 { 2632 {
2602 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 2633 pPackage->fAbandonedProcess = pContext->fAbandonedProcess;
2634 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, pPackage->fAbandonedProcess, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2603 } 2635 }
2604 2636
2605 return hr; 2637 return hr;
@@ -2624,6 +2656,9 @@ static HRESULT DoRestoreRelatedBundleActions(
2624 continue; 2656 continue;
2625 } 2657 }
2626 2658
2659 pContext->wzExecutingPackageId = NULL;
2660 pContext->fAbandonedProcess = FALSE;
2661
2627 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2662 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2628 switch (pRestoreRelatedBundleAction->type) 2663 switch (pRestoreRelatedBundleAction->type)
2629 { 2664 {
@@ -2665,13 +2700,13 @@ static HRESULT ExecuteExePackage(
2665 BOOL fExecuted = FALSE; 2700 BOOL fExecuted = FALSE;
2666 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; 2701 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
2667 2702
2668 if (FAILED(pPackage->hrCacheResult)) 2703 Assert(pContext->fRollback == fRollback);
2704
2705 if (ShouldSkipPackage(pPackage, fRollback))
2669 { 2706 {
2670 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2671 ExitFunction1(hr = S_OK); 2707 ExitFunction1(hr = S_OK);
2672 } 2708 }
2673 2709
2674 Assert(pContext->fRollback == fRollback);
2675 pContext->wzExecutingPackageId = pPackage->sczId; 2710 pContext->wzExecutingPackageId = pPackage->sczId;
2676 fBeginCalled = TRUE; 2711 fBeginCalled = TRUE;
2677 2712
@@ -2720,7 +2755,8 @@ LExit:
2720 2755
2721 if (fBeginCalled) 2756 if (fBeginCalled)
2722 { 2757 {
2723 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 2758 pPackage->fAbandonedProcess = pContext->fAbandonedProcess;
2759 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, pPackage->fAbandonedProcess, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2724 } 2760 }
2725 2761
2726 return hr; 2762 return hr;
@@ -2743,13 +2779,13 @@ static HRESULT ExecuteMsiPackage(
2743 BOOL fExecuted = FALSE; 2779 BOOL fExecuted = FALSE;
2744 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage; 2780 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage;
2745 2781
2746 if (FAILED(pPackage->hrCacheResult)) 2782 Assert(pContext->fRollback == fRollback);
2783
2784 if (ShouldSkipPackage(pPackage, fRollback))
2747 { 2785 {
2748 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2749 ExitFunction1(hr = S_OK); 2786 ExitFunction1(hr = S_OK);
2750 } 2787 }
2751 2788
2752 Assert(pContext->fRollback == fRollback);
2753 pContext->wzExecutingPackageId = pPackage->sczId; 2789 pContext->wzExecutingPackageId = pPackage->sczId;
2754 fBeginCalled = TRUE; 2790 fBeginCalled = TRUE;
2755 2791
@@ -2784,7 +2820,8 @@ LExit:
2784 2820
2785 if (fBeginCalled) 2821 if (fBeginCalled)
2786 { 2822 {
2787 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 2823 Assert(!pContext->fAbandonedProcess);
2824 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, FALSE, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2788 } 2825 }
2789 2826
2790 return hr; 2827 return hr;
@@ -2807,13 +2844,13 @@ static HRESULT ExecuteMspPackage(
2807 BOOL fExecuted = FALSE; 2844 BOOL fExecuted = FALSE;
2808 BURN_PACKAGE* pPackage = pExecuteAction->mspTarget.pPackage; 2845 BURN_PACKAGE* pPackage = pExecuteAction->mspTarget.pPackage;
2809 2846
2810 if (FAILED(pPackage->hrCacheResult)) 2847 Assert(pContext->fRollback == fRollback);
2848
2849 if (ShouldSkipPackage(pPackage, fRollback))
2811 { 2850 {
2812 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2813 ExitFunction1(hr = S_OK); 2851 ExitFunction1(hr = S_OK);
2814 } 2852 }
2815 2853
2816 Assert(pContext->fRollback == fRollback);
2817 pContext->wzExecutingPackageId = pPackage->sczId; 2854 pContext->wzExecutingPackageId = pPackage->sczId;
2818 fBeginCalled = TRUE; 2855 fBeginCalled = TRUE;
2819 2856
@@ -2857,7 +2894,8 @@ LExit:
2857 2894
2858 if (fBeginCalled) 2895 if (fBeginCalled)
2859 { 2896 {
2860 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 2897 Assert(!pContext->fAbandonedProcess);
2898 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, FALSE, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2861 } 2899 }
2862 2900
2863 return hr; 2901 return hr;
@@ -2882,13 +2920,13 @@ static HRESULT ExecuteMsuPackage(
2882 BOOL fExecuted = FALSE; 2920 BOOL fExecuted = FALSE;
2883 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage; 2921 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage;
2884 2922
2885 if (FAILED(pPackage->hrCacheResult)) 2923 Assert(pContext->fRollback == fRollback);
2924
2925 if (ShouldSkipPackage(pPackage, fRollback))
2886 { 2926 {
2887 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2888 ExitFunction1(hr = S_OK); 2927 ExitFunction1(hr = S_OK);
2889 } 2928 }
2890 2929
2891 Assert(pContext->fRollback == fRollback);
2892 pContext->wzExecutingPackageId = pPackage->sczId; 2930 pContext->wzExecutingPackageId = pPackage->sczId;
2893 fBeginCalled = TRUE; 2931 fBeginCalled = TRUE;
2894 2932
@@ -2937,7 +2975,8 @@ LExit:
2937 2975
2938 if (fBeginCalled) 2976 if (fBeginCalled)
2939 { 2977 {
2940 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 2978 pPackage->fAbandonedProcess = pContext->fAbandonedProcess;
2979 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage->sczId, pPackage->fVital, pPackage->fAbandonedProcess, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2941 } 2980 }
2942 2981
2943 return hr; 2982 return hr;
@@ -3256,7 +3295,8 @@ LExit:
3256 3295
3257 if (fBeginCalled) 3296 if (fBeginCalled)
3258 { 3297 {
3259 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pContext->wzExecutingPackageId, FALSE, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); 3298 Assert(!pContext->fAbandonedProcess);
3299 hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pContext->wzExecutingPackageId, FALSE, FALSE, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
3260 } 3300 }
3261 3301
3262 return hr; 3302 return hr;
@@ -3334,6 +3374,14 @@ static int GenericExecuteMessageHandler(
3334 } 3374 }
3335 break; 3375 break;
3336 3376
3377 case GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED:
3378 pContext->fAbandonedProcess = TRUE;
3379 break;
3380
3381 case GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED:
3382 pContext->fAbandonedProcess = FALSE;
3383 break;
3384
3337 case GENERIC_EXECUTE_MESSAGE_ERROR: 3385 case GENERIC_EXECUTE_MESSAGE_ERROR:
3338 UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->wzExecutingPackageId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, 0, NULL, &nResult); // ignore return value. 3386 UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->wzExecutingPackageId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, 0, NULL, &nResult); // ignore return value.
3339 break; 3387 break;
@@ -3428,6 +3476,7 @@ static HRESULT ExecutePackageComplete(
3428 __in BURN_VARIABLES* pVariables, 3476 __in BURN_VARIABLES* pVariables,
3429 __in LPCWSTR wzPackageId, 3477 __in LPCWSTR wzPackageId,
3430 __in BOOL fPackageVital, 3478 __in BOOL fPackageVital,
3479 __in BOOL fAbandonedProcess,
3431 __in HRESULT hrOverall, 3480 __in HRESULT hrOverall,
3432 __in HRESULT hrExecute, 3481 __in HRESULT hrExecute,
3433 __in BOOL fRollback, 3482 __in BOOL fRollback,
@@ -3445,7 +3494,7 @@ static HRESULT ExecutePackageComplete(
3445 { 3494 {
3446 *pRestart = BOOTSTRAPPER_APPLY_RESTART_INITIATED; 3495 *pRestart = BOOTSTRAPPER_APPLY_RESTART_INITIATED;
3447 } 3496 }
3448 *pfRetry = (FAILED(hrExecute) && BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_RETRY == executePackageCompleteAction); // allow retry only on failures. 3497 *pfRetry = (FAILED(hrExecute) && BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_RETRY == executePackageCompleteAction && !fAbandonedProcess); // allow retry only on failures.
3449 *pfSuspend = (BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_SUSPEND == executePackageCompleteAction); 3498 *pfSuspend = (BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_SUSPEND == executePackageCompleteAction);
3450 3499
3451 // Remember this package as the package that initiated the forced restart. 3500 // Remember this package as the package that initiated the forced restart.
diff --git a/src/burn/engine/apply.h b/src/burn/engine/apply.h
index 47f0ece6..7c786cc6 100644
--- a/src/burn/engine/apply.h
+++ b/src/burn/engine/apply.h
@@ -14,6 +14,8 @@ enum GENERIC_EXECUTE_MESSAGE_TYPE
14 GENERIC_EXECUTE_MESSAGE_PROGRESS, 14 GENERIC_EXECUTE_MESSAGE_PROGRESS,
15 GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE, 15 GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE,
16 GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL, 16 GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL,
17 GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED,
18 GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED,
17}; 19};
18 20
19typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA 21typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 3c2872f1..ea56e242 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -44,6 +44,8 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
44 BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS, 44 BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS,
45 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, 45 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS,
46 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL, 46 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL,
47 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED,
48 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED,
47 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, 49 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR,
48 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, 50 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE,
49 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE, 51 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE,
@@ -1823,6 +1825,14 @@ static HRESULT ProcessGenericExecuteMessages(
1823 ExitOnFailure(hr, "Failed to read processId."); 1825 ExitOnFailure(hr, "Failed to read processId.");
1824 break; 1826 break;
1825 1827
1828 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED:
1829 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED;
1830 break;
1831
1832 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED:
1833 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED;
1834 break;
1835
1826 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: 1836 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR:
1827 message.type = GENERIC_EXECUTE_MESSAGE_ERROR; 1837 message.type = GENERIC_EXECUTE_MESSAGE_ERROR;
1828 1838
@@ -3465,6 +3475,14 @@ static int GenericExecuteMessageHandler(
3465 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL; 3475 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL;
3466 break; 3476 break;
3467 3477
3478 case GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED:
3479 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED;
3480 break;
3481
3482 case GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED:
3483 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED;
3484 break;
3485
3468 case GENERIC_EXECUTE_MESSAGE_ERROR: 3486 case GENERIC_EXECUTE_MESSAGE_ERROR:
3469 // serialize message data 3487 // serialize message data
3470 hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); 3488 hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode);
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 9e139661..32473252 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -940,6 +940,13 @@ Language=English
940Bootstrapper application requested delayed cancel during package process progress, id: %1!ls!. Waiting... 940Bootstrapper application requested delayed cancel during package process progress, id: %1!ls!. Waiting...
941. 941.
942 942
943MessageId=365
944Severity=Success
945SymbolicName=MSG_APPLY_SKIPPED_PACKAGE_WITH_ABANDONED_PROCESS
946Language=English
947Skipping rollback of package: %1!ls! due to abandoning its process. Continuing...
948.
949
943MessageId=370 950MessageId=370
944Severity=Success 951Severity=Success
945SymbolicName=MSG_SESSION_BEGIN 952SymbolicName=MSG_SESSION_BEGIN
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index 4c3c6fb0..a1049006 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -276,30 +276,33 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
276 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 276 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
277 ExitOnFailure(hr, "Failed to plan package dependency actions."); 277 ExitOnFailure(hr, "Failed to plan package dependency actions.");
278 278
279 // add execute action 279 // add rollback action
280 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) 280 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
281 { 281 {
282 hr = PlanAppendExecuteAction(pPlan, &pAction); 282 hr = PlanAppendRollbackAction(pPlan, &pAction);
283 ExitOnFailure(hr, "Failed to append execute action."); 283 ExitOnFailure(hr, "Failed to append rollback action.");
284 284
285 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 285 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
286 pAction->exePackage.pPackage = pPackage; 286 pAction->exePackage.pPackage = pPackage;
287 pAction->exePackage.action = pPackage->execute; 287 pAction->exePackage.action = pPackage->rollback;
288 288
289 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. 289 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
290
291 hr = PlanExecuteCheckpoint(pPlan);
292 ExitOnFailure(hr, "Failed to append execute checkpoint.");
290 } 293 }
291 294
292 // add rollback action 295 // add execute action
293 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback) 296 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
294 { 297 {
295 hr = PlanAppendRollbackAction(pPlan, &pAction); 298 hr = PlanAppendExecuteAction(pPlan, &pAction);
296 ExitOnFailure(hr, "Failed to append rollback action."); 299 ExitOnFailure(hr, "Failed to append execute action.");
297 300
298 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 301 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
299 pAction->exePackage.pPackage = pPackage; 302 pAction->exePackage.pPackage = pPackage;
300 pAction->exePackage.action = pPackage->rollback; 303 pAction->exePackage.action = pPackage->execute;
301 304
302 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. 305 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
303 } 306 }
304 307
305LExit: 308LExit:
@@ -493,6 +496,10 @@ extern "C" HRESULT ExeEngineRunProcess(
493 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); 496 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
494 } 497 }
495 498
499 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED;
500 message.dwUIHint = MB_OK;
501 pfnGenericMessageHandler(&message, pvContext);
502
496 if (fFireAndForget) 503 if (fFireAndForget)
497 { 504 {
498 ::WaitForInputIdle(pi.hProcess, 5000); 505 ::WaitForInputIdle(pi.hProcess, 5000);
@@ -504,6 +511,7 @@ extern "C" HRESULT ExeEngineRunProcess(
504 // Wait for the executable process while sending fake progress to allow cancel. 511 // Wait for the executable process while sending fake progress to allow cancel.
505 do 512 do
506 { 513 {
514 memset(&message, 0, sizeof(message));
507 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; 515 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
508 message.dwUIHint = MB_OKCANCEL; 516 message.dwUIHint = MB_OKCANCEL;
509 message.progress.dwPercentage = 50; 517 message.progress.dwPercentage = 50;
@@ -546,6 +554,11 @@ extern "C" HRESULT ExeEngineRunProcess(
546 } 554 }
547 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); 555 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
548 556
557 memset(&message, 0, sizeof(message));
558 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED;
559 message.dwUIHint = MB_OK;
560 pfnGenericMessageHandler(&message, pvContext);
561
549 if (fDelayedCancel) 562 if (fDelayedCancel)
550 { 563 {
551 ExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT), "Bootstrapper application cancelled during package process progress, exit code: 0x%x", *pdwExitCode); 564 ExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT), "Bootstrapper application cancelled during package process progress, exit code: 0x%x", *pdwExitCode);
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index 2f1fb61c..2591973f 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -222,30 +222,33 @@ extern "C" HRESULT MsuEnginePlanAddPackage(
222 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 222 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
223 ExitOnFailure(hr, "Failed to plan package dependency actions."); 223 ExitOnFailure(hr, "Failed to plan package dependency actions.");
224 224
225 // add execute action 225 // add rollback action
226 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) 226 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
227 { 227 {
228 hr = PlanAppendExecuteAction(pPlan, &pAction); 228 hr = PlanAppendRollbackAction(pPlan, &pAction);
229 ExitOnFailure(hr, "Failed to append execute action."); 229 ExitOnFailure(hr, "Failed to append rollback action.");
230 230
231 pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; 231 pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE;
232 pAction->msuPackage.pPackage = pPackage; 232 pAction->msuPackage.pPackage = pPackage;
233 pAction->msuPackage.action = pPackage->execute; 233 pAction->msuPackage.action = pPackage->rollback;
234 234
235 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors. 235 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors.
236
237 hr = PlanExecuteCheckpoint(pPlan);
238 ExitOnFailure(hr, "Failed to append execute checkpoint.");
236 } 239 }
237 240
238 // add rollback action 241 // add execute action
239 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback) 242 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
240 { 243 {
241 hr = PlanAppendRollbackAction(pPlan, &pAction); 244 hr = PlanAppendExecuteAction(pPlan, &pAction);
242 ExitOnFailure(hr, "Failed to append rollback action."); 245 ExitOnFailure(hr, "Failed to append execute action.");
243 246
244 pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; 247 pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE;
245 pAction->msuPackage.pPackage = pPackage; 248 pAction->msuPackage.pPackage = pPackage;
246 pAction->msuPackage.action = pPackage->rollback; 249 pAction->msuPackage.action = pPackage->execute;
247 250
248 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors. 251 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors.
249 } 252 }
250 253
251LExit: 254LExit:
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index eb40443d..e3e39c51 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -282,6 +282,7 @@ typedef struct _BURN_PACKAGE
282 LPWSTR sczCacheFolder; // only valid during Apply. 282 LPWSTR sczCacheFolder; // only valid during Apply.
283 HRESULT hrCacheResult; // only valid during Apply. 283 HRESULT hrCacheResult; // only valid during Apply.
284 BOOL fReachedExecution; // only valid during Apply. 284 BOOL fReachedExecution; // only valid during Apply.
285 BOOL fAbandonedProcess; // only valid during Apply.
285 286
286 BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply. 287 BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply.
287 BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply. 288 BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply.
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 770922b4..2febe277 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -715,6 +715,7 @@ namespace Bootstrapper
715 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 715 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA"); 717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA");
718 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
718 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL); 719 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL);
719 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 721 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -729,6 +730,7 @@ namespace Bootstrapper
729 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL); 730 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
730 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 732 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
733 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
732 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 734 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
733 Assert::Equal(dwIndex, pPlan->cRollbackActions); 735 Assert::Equal(dwIndex, pPlan->cRollbackActions);
734 736
@@ -1682,6 +1684,7 @@ namespace Bootstrapper
1682 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 1684 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
1683 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1685 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1684 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"test.msu"); 1686 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"test.msu");
1687 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1685 ValidateExecuteMsuPackage(pPlan, fRollback, dwIndex++, L"test.msu", BOOTSTRAPPER_ACTION_STATE_INSTALL); 1688 ValidateExecuteMsuPackage(pPlan, fRollback, dwIndex++, L"test.msu", BOOTSTRAPPER_ACTION_STATE_INSTALL);
1686 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1689 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1687 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1690 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -1697,6 +1700,7 @@ namespace Bootstrapper
1697 ValidateExecuteMsuPackage(pPlan, fRollback, dwIndex++, L"test.msu", BOOTSTRAPPER_ACTION_STATE_UNINSTALL); 1700 ValidateExecuteMsuPackage(pPlan, fRollback, dwIndex++, L"test.msu", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
1698 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1701 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1699 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1702 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1703 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1700 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 1704 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
1701 Assert::Equal(dwIndex, pPlan->cRollbackActions); 1705 Assert::Equal(dwIndex, pPlan->cRollbackActions);
1702 1706
diff --git a/src/test/burn/TestBA/TestBA.cs b/src/test/burn/TestBA/TestBA.cs
index c219ce9c..fdbcc6d4 100644
--- a/src/test/burn/TestBA/TestBA.cs
+++ b/src/test/burn/TestBA/TestBA.cs
@@ -4,6 +4,7 @@ namespace WixToolset.Test.BA
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics;
7 using System.IO; 8 using System.IO;
8 using System.Linq; 9 using System.Linq;
9 using System.Threading; 10 using System.Threading;
@@ -37,6 +38,7 @@ namespace WixToolset.Test.BA
37 private string cancelExecuteActionName; 38 private string cancelExecuteActionName;
38 private int cancelOnProgressAtProgress; 39 private int cancelOnProgressAtProgress;
39 private int retryExecuteFilesInUse; 40 private int retryExecuteFilesInUse;
41 private bool rollingBack;
40 42
41 private IBootstrapperCommand Command { get; } 43 private IBootstrapperCommand Command { get; }
42 44
@@ -350,6 +352,8 @@ namespace WixToolset.Test.BA
350 { 352 {
351 this.Log("OnExecutePackageBegin() - package: {0}, rollback: {1}", args.PackageId, !args.ShouldExecute); 353 this.Log("OnExecutePackageBegin() - package: {0}, rollback: {1}", args.PackageId, !args.ShouldExecute);
352 354
355 this.rollingBack = !args.ShouldExecute;
356
353 string slowProgress = this.ReadPackageAction(args.PackageId, "SlowExecute"); 357 string slowProgress = this.ReadPackageAction(args.PackageId, "SlowExecute");
354 if (String.IsNullOrEmpty(slowProgress) || !Int32.TryParse(slowProgress, out this.sleepDuringExecute)) 358 if (String.IsNullOrEmpty(slowProgress) || !Int32.TryParse(slowProgress, out this.sleepDuringExecute))
355 { 359 {
@@ -404,7 +408,7 @@ namespace WixToolset.Test.BA
404 if (!String.IsNullOrEmpty(recordTestRegistryValue) && Boolean.TryParse(recordTestRegistryValue, out logTestRegistryValue) && logTestRegistryValue) 408 if (!String.IsNullOrEmpty(recordTestRegistryValue) && Boolean.TryParse(recordTestRegistryValue, out logTestRegistryValue) && logTestRegistryValue)
405 { 409 {
406 var value = this.ReadTestRegistryValue(args.PackageId); 410 var value = this.ReadTestRegistryValue(args.PackageId);
407 this.Log("TestRegistryValue: {0}, Version, '{1}'", args.PackageId, value); 411 this.Log("TestRegistryValue: {0}, {1}, Version, '{2}'", this.rollingBack ? "Rollback" : "Execute", args.PackageId, value);
408 } 412 }
409 } 413 }
410 414
@@ -419,8 +423,22 @@ namespace WixToolset.Test.BA
419 423
420 if (args.Action == BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION.Abandon) 424 if (args.Action == BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION.Abandon)
421 { 425 {
422 // Give time to the process to start before its files are deleted. 426 // Kill process to make sure it doesn't affect other tests.
423 Thread.Sleep(2000); 427 try
428 {
429 using (Process process = Process.GetProcessById(args.ProcessId))
430 {
431 if (process != null)
432 {
433 process.Kill();
434 }
435 }
436 }
437 catch (Exception e)
438 {
439 this.Log("Failed to kill process {0}: {1}", args.ProcessId, e);
440 Thread.Sleep(5000);
441 }
424 } 442 }
425 443
426 this.Log("OnExecuteProcessCancel({0})", args.Action); 444 this.Log("OnExecuteProcessCancel({0})", args.Action);
@@ -494,6 +512,7 @@ namespace WixToolset.Test.BA
494 this.cancelOnProgressAtProgress = -1; 512 this.cancelOnProgressAtProgress = -1;
495 this.cancelExecuteAtProgress = -1; 513 this.cancelExecuteAtProgress = -1;
496 this.cancelCacheAtProgress = -1; 514 this.cancelCacheAtProgress = -1;
515 this.rollingBack = false;
497 } 516 }
498 517
499 protected override void OnApplyComplete(ApplyCompleteEventArgs args) 518 protected override void OnApplyComplete(ApplyCompleteEventArgs args)
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
index bbc0b387..b50be49a 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/FailureTests.cs
@@ -25,12 +25,8 @@ namespace WixToolsetTest.BurnE2E
25 var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); 25 var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT);
26 bundleD.VerifyUnregisteredAndRemovedFromPackageCache(); 26 bundleD.VerifyUnregisteredAndRemovedFromPackageCache();
27 27
28 Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: ExeA, Version, ''")); 28 Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Execute, ExeA, Version, ''"));
29 29 Assert.False(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Rollback, ExeA, Version"));
30 // Make sure ExeA finishes running.
31 Thread.Sleep(3000);
32
33 bundleD.VerifyExeTestRegistryValue("ExeA", "1.0.0.0");
34 } 30 }
35 31
36 [Fact] 32 [Fact]
@@ -47,9 +43,11 @@ namespace WixToolsetTest.BurnE2E
47 var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); 43 var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT);
48 bundleD.VerifyUnregisteredAndRemovedFromPackageCache(); 44 bundleD.VerifyUnregisteredAndRemovedFromPackageCache();
49 45
50 Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: ExeA, Version, '1.0.0.0'")); 46 Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Execute, ExeA, Version, '1.0.0.0'"));
47 Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Rollback, ExeA, Version, ''"));
51 48
52 bundleD.VerifyExeTestRegistryValue("ExeA", "1.0.0.0"); 49 // The package should have rolled back.
50 bundleD.VerifyExeTestRegistryRootDeleted("ExeA");
53 } 51 }
54 52
55 [Fact] 53 [Fact]