Zdaj zakasnjena akcija vedno pripravi razveljavitvena in uveljavitvena skripta. Razveljavitev opravi sama le, če ji to ne uspe. Sicer pa delo razveljavljanja prepusti razveljavitveni akiciji, ki mora biti zato zdaj v tabeli InstallExecuteSequence uvrščena pred zakasnjeno.

Če datoteke z zaporedjem ukazov za čiščenje ni, ne javimo več napake.

Verzijo sem nastavil na 2.0.1.
This commit is contained in:
Simon Rozman 2014-01-14 10:13:06 +00:00
parent 9ffeaca907
commit 56dfdb9ec7
3 changed files with 65 additions and 47 deletions

View File

@ -233,12 +233,12 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall)
uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename); uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
AMSICA::COpList lstOperations; AMSICA::COpList lstOperations;
BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK);
// Load operation sequence. // Load operation sequence.
hr = lstOperations.LoadFromFile(sSequenceFilename); hr = lstOperations.LoadFromFile(sSequenceFilename);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
AMSICA::CSession session; AMSICA::CSession session;
BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK);
session.m_hInstall = hInstall; session.m_hInstall = hInstall;
@ -247,16 +247,17 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall)
// Execute the operations. // Execute the operations.
hr = lstOperations.Execute(&session); hr = lstOperations.Execute(&session);
if (SUCCEEDED(hr)) { if (!bIsCleanup) {
if (!bIsCleanup && session.m_bRollbackEnabled) { // Save cleanup scripts of delayed action regardless of action's execution status.
// Save cleanup scripts. // Rollback action MUST be scheduled in InstallExecuteSequence before this action! Otherwise cleanup won't be performed in case this action execution failed.
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename);
ATL::CAtlString sSequenceFilenameCM, sSequenceFilenameRB; ATL::CAtlString sSequenceFilenameCM, sSequenceFilenameRB;
HRESULT hr;
sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
// After end of commit, delete rollback file too. After end of rollback, delete commit file too. // After commit, delete rollback file. After rollback, delete commit file.
session.m_olCommit.AddTail(new AMSICA::COpFileDelete( session.m_olCommit.AddTail(new AMSICA::COpFileDelete(
#ifdef _UNICODE #ifdef _UNICODE
sSequenceFilenameRB sSequenceFilenameRB
@ -281,28 +282,46 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall)
uiResult = ERROR_SUCCESS; uiResult = ERROR_SUCCESS;
} else { } else {
// Saving rollback file failed. // Saving rollback file failed.
uiResult = HRESULT_CODE(hr); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
uiResult = ERROR_INSTALL_SCRIPT_WRITE;
::MsiRecordSetInteger(hRecordProg, 1, uiResult );
::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameRB);
::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
} else { } else {
// Saving commit file failed. // Saving commit file failed.
uiResult = HRESULT_CODE(hr); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
} uiResult = ERROR_INSTALL_SCRIPT_WRITE;
} else { ::MsiRecordSetInteger(hRecordProg, 1, uiResult );
// No cleanup support required. ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameCM);
uiResult = ERROR_SUCCESS; ::MsiRecordSetInteger(hRecordProg, 3, hr );
} ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} else {
// Execution failed.
uiResult = HRESULT_CODE(hr);
} }
if (uiResult != ERROR_SUCCESS) { if (uiResult != ERROR_SUCCESS) {
// Perform the cleanup now. The rollback script might not have been written to file yet. // The commit and/or rollback scripts were not written to file successfully. Perform the cleanup immediately.
// And even if it was, the rollback action might not get invoked at all (if scheduled in InstallExecuteSequence later than this action).
session.m_bContinueOnError = TRUE; session.m_bContinueOnError = TRUE;
session.m_bRollbackEnabled = FALSE; session.m_bRollbackEnabled = FALSE;
session.m_olRollback.Execute(&session); session.m_olRollback.Execute(&session);
::DeleteFile(sSequenceFilenameRB);
} }
} else {
// No cleanup after cleanup support.
uiResult = ERROR_SUCCESS;
}
if (FAILED(hr)) {
// Execution of the action failed.
uiResult = HRESULT_CODE(hr);
}
::DeleteFile(sSequenceFilename);
} else if (hr == ERROR_FILE_NOT_FOUND && bIsCleanup) {
// Sequence file not found and this is rollback/commit action. Either of the following scenarios are possible:
// - The delayed action failed to save the rollback/commit file. The delayed action performed cleanup itself. No further action is required.
// - Somebody removed the rollback/commit file between delayed action and rollback/commit action. No further action is possible.
uiResult = ERROR_SUCCESS;
} else { } else {
// Sequence loading failed. Probably, LOCAL SYSTEM doesn't have read access to user's temp directory. // Sequence loading failed. Probably, LOCAL SYSTEM doesn't have read access to user's temp directory.
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
@ -314,9 +333,8 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall)
} }
lstOperations.Free(); lstOperations.Free();
::DeleteFile(sSequenceFilename);
} else { } else {
// Couldn't get CustomActionData property. // Couldn't get CustomActionData property. uiResult has the error code.
} }
if (bIsCoInitialized) ::CoUninitialize(); if (bIsCoInitialized) ::CoUninitialize();

View File

@ -6,14 +6,14 @@
// Constants // Constants
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
#define MSITSCA_VERSION 0x02000000 #define MSITSCA_VERSION 0x02000100
#define MSITSCA_VERSION_MAJ 2 #define MSITSCA_VERSION_MAJ 2
#define MSITSCA_VERSION_MIN 0 #define MSITSCA_VERSION_MIN 0
#define MSITSCA_VERSION_REV 0 #define MSITSCA_VERSION_REV 1
#define MSITSCA_VERSION_STR "2.0" #define MSITSCA_VERSION_STR "2.0.1"
#define MSITSCA_VERSION_INST "2.0" #define MSITSCA_VERSION_INST "2.0.1"
#if !defined(RC_INVOKED) && !defined(MIDL_PASS) #if !defined(RC_INVOKED) && !defined(MIDL_PASS)

View File

@ -153,8 +153,8 @@ Action Condition Sequence
s$(MSI_TIP_ID) S255 I2 s$(MSI_TIP_ID) S255 I2
InstallExecuteSequence Action InstallExecuteSequence Action
EvaluateScheduledTasks 6580 EvaluateScheduledTasks 6580
InstallScheduledTasks 6581 RollbackScheduledTasks 6581
RollbackScheduledTasks 6582 InstallScheduledTasks 6582
CommitScheduledTasks 6583 CommitScheduledTasks 6583
<<NOKEEP <<NOKEEP