apple / swift-installer-scripts

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Thoughts regarding uninstall

wjk opened this issue · comments

// TODO(compnerd) it would be ideal to record the files deployed here to the
// `RemoveFile` table which would allow them to be cleaned up on removal.
// This is tricky as we cannot modify the on-disk database. The deferred
// action is already executed post-InstallExecute which means that we can now
// identify the cached MSI by:
//
// std::wstring product_code = msi::get_property(hInstall, L"ProductCode");
//
// DWORD size = 0;
// (void)MsiGetProductInfoW(product_code.c_str(),
// INSTALLPROPERTY_LOCALPACKAGE, L"", &size);
// std::vector<wchar_t> buffer;
// buffer.resize(++size);
// (void)MsiGetProductInfoW(product_code.c_str(),
// INSTALLPROPERTY_LOCALPACKAGE, buffer.data(),
// &size);
//
// We can then create a new property for the location of the entry and a new
// RemoveFile entry for cleaning up the file. Note that we may have to tweak
// things to get repairs to work properly with the tracking.
//
// PMSIHANDLE database;
// (void)MsiOpenDatabaseW(buffer.data(), MSIDBOPEN_TRANSACT, &database);
//
// static const wchar_t query[] =
// LR"SQL(
//INSERT INTO `Property` (`Property`, `Value`)
// VALUES(?, ?);
//INSERT INTO `RemoveFile` (`FileKey`, `Component_`, `FileName`, `DirProperty`, `InstallMode`
// VALUES (?, ?, ?, ?, ?);
// )SQL";
//
// PMSIHANDLE view;
// (void)MsiDatabaseOpenViewW(database, query, &view);
//
// std::hash<std::wstring> hasher;
//
// std::wostringstream component;
// component << "cmp" << hasher(path.wstring());
//
// std::wostringstream property;
// property << "prop" << hasher(path.wstring());
//
// PMSIHANDLE record = MsiRecordCreate(7);
// (void)MsiRecordSetStringW(record, 1, property.str().c_str());
// (void)MsiRecordSetStringW(record, 2, path.parent_path().wstring().c_str());
// (void)MsiRecordSetStringW(record, 3, component.str().c_str());
// (void)MsiRecordSetStringW(record, 4, component.str().c_str());
// (void)MsiRecordSetStringW(record, 5, path.filename().wstring().c_str());
// (void)MsiRecordSetStringW(record, 6, property.str().c_str());
// (void)MsiRecordSetInteger(record, 7, 2);
//
// (void)MsiViewExecute(view, record);
//
// (void)MsiDatabaseCommit(database);
//
// Currently, this seems to fail with the commiting of the database, which is
// still a mystery to me. This relies on the clever usage of the
// `EnsureTable` in the WiX definition to ensure that we do not need to create
// the table.

In the above code snippet, there is made mention of attempting to modify the MSI database in-situ during the install. I have never seen anyone try this before. I do not think what you are doing is a supported practice. The snippet mentions problems committing the changes to the database. I am pretty certain given the symptoms listed that Windows holds a lock on the MSI file being installed that prevents it from being modified during the installation.

There is another method, however. Custom actions can be run on uninstall as well. We could create a second MSI custom action function in the same DLL that does the same path lookup but deletes files instead of copying them. I could submit a PR for this myself, but since I would have to build Swift from source, it may take me a while to get into the state where I can work on this issue directly.

Yes, it is unsupported, and I don't think it can work given the lock. Interesting idea with the uninstall CA. How would we track the installed module maps though? I'm still holding out hope to support a multi-versioned installation so we can have more than one installed toolchain, so we could not remove the module maps until the last uninstall occurs.

How would we track the installed module maps though?

Unfortunately, on that one I have no clue.

I don't want to suggest this (because having more people building the toolchain helps clean up issues that I've become blind to), but you could grab the artifacts from https://github.com/compnerd/swift-build/actions/runs/3776707293 and only run the packaging stage.

Now that we no longer actually install the module maps into the VS installation, the next problem is the removal of the existing ones.

@wjk - I was wondering if you still have any thoughts about this. I feel like we should just cut our losses and say that we won't be able to clean up old installs 😞. There are so many improvements that we have made since the original installer that I am not sure if we can do much here.

@compnerd Yeah, I agree. 😔 My idea was to use the same logic that copied the maps in to delete them, but since that’s long gone I can’t think of anything good to do here either. Would having old versions on the filesystem cause problems?

Nope, nothing outside of the extreme amount of discomfort that the image is no longer "clean".