Skip to content

Instantly share code, notes, and snippets.

@peterhirn
Last active November 29, 2021 19:04
Show Gist options
  • Save peterhirn/41efca5393a47d8aff5942ff698c19c3 to your computer and use it in GitHub Desktop.
Save peterhirn/41efca5393a47d8aff5942ff698c19c3 to your computer and use it in GitHub Desktop.
F# ProductCode from msi
/// F# impl. of https://stackoverflow.com/a/19765999/16368506
module private Msi =
open System
open System.Text
open System.Runtime.InteropServices
open Microsoft.Win32.SafeHandles
[<Literal>]
let private MsiDll = "msi.dll"
[<DllImport(MsiDll, ExactSpelling = true)>]
extern uint MsiCloseHandle(IntPtr hAny)
type MsiHandle() =
inherit SafeHandleMinusOneIsInvalid(true)
with
override x.ReleaseHandle() = MsiCloseHandle x.handle = 0u
[<DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)>]
extern uint MsiOpenPackageW(string szPackagePath, MsiHandle& product)
[<DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)>]
extern uint MsiGetProductPropertyW(MsiHandle hProduct, string szProperty, StringBuilder value, int& length)
[<DllImport(MsiDll, ExactSpelling = true)>]
extern int MsiSetInternalUI(int value, IntPtr hwnd)
let private disableUi () =
MsiSetInternalUI(2, IntPtr.Zero) |> ignore
let private openFile path =
// `MsiOpenPackageW` requires absolute path
let absolute = System.IO.Path.GetFullPath path
let mutable handle: MsiHandle = new MsiHandle()
let result = MsiOpenPackageW(absolute, &handle)
if result <> 0u then
failwithf "Failed to open msi %s" path
handle
let productProperty property path =
disableUi ()
use handle = openFile path
let builder = new StringBuilder(1024)
let mutable length: int = builder.Capacity
let result = MsiGetProductPropertyW(handle, property, builder, &length)
if result = 0u && length > 0 then
builder |> string |> Some
else
None
let productCode = productProperty "ProductCode"
let path = "./installer/my_app.msi"
let code = Msi.productCode path
printfn "%A" code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment