TAP: Await anything (not only Tasks)

The async/await pattern is simple yet effective way to work with tasks. Its ingeniousity is that the programmer is focused on implementation of the function at the first place, leaving the technical details to the compiler which does some behind-the-scenes magic to make sure that async methods can:

  • run asynchronously,
  • capture or disregard the context (via ConfigureAwait(bool))
  • use all benefits of TAP (Task-based Asynchronous Pattern)

A nice touch of the async/await syntax is that it is easy to convert any synchronous method into its asynchronous counterpart, without sacrificing code clarity or increasing its complexity.

Interestingly enough, the await keyword is not really limited to Tasks, and as a matter of fact it can be used for any object for which it makes sense to wait for. This blog post is devoted to defining a class which can be awaited with await keyword, and yet is by no mean a Task at all!

So what is the compiler doing and how to make sure it understands our custom awaiting desire? In order to demonstrate, let’s try the following code which uses a plain AutoResetEvent. One thing to notice is that – instead of WaitOne() in line 21 – we try to await it by adding the await keyword before.
Continue reading “TAP: Await anything (not only Tasks)”

Enumerating installed MSI products with PowerShell and msi.dll

If you were ever wondering how to properly read the list of installed MSI software, then two popular choices are available:

  • Querying uninstall registry keys (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall), filtering out-non MSI entries and outputting the rest
  • Using Win32_Product from WMI

They both have their pros and cons. Querying registry is straightforward on its own, but requires awkward manipulations and accessing the data which is actually backing the Add/Remove Applet, not necessarily the Windows Installer API which uses its own complex registration. Additionally it may not work correctly with different installation context (user/machine) and you may have to query two places to get both x86 and x64 installations on a x64 system.

On the other hand, while WMI query is also pretty straightforward (seeĀ https://msdn.microsoft.com/en-us/library/aa394378(v=VS.85).aspx?f=255&MSPPError=-2147217396), it has a really big drawback. Running it is painfully slow, because Windows Installer checks integrity of each entry and triggers appropriate action (for example repair) if necessary.

So to have a solution which is both fast, reliable and without any side-effects, you may go for a third solution which is more complex, but once setup can be reused not only for querying but for a whole management of MSI-based installations. And so this blog today will be about P/invoking native msi.dll to get results returned by the true Windows Installer API.

This post may be too technical if you have never programmed in C/C++ or C#. If you just want the results without understanding how to implement them on your own, scroll to the bottom, the full content of the PowerShell script is there.
Continue reading “Enumerating installed MSI products with PowerShell and msi.dll”