user1263089
user1263089

Reputation: 11

Getting Error result in System::call for MsiEnumProducts and GetLastError in NSIS script

I have written the following script to Enumerate Installed Products from MSI.

!include LogicLib.nsh

!define MsiGetProductCodeFromName "!insertmacro MsiGetProductCodeFromName"

!macro MsiGetProductCodeFromName MSINSISPRODUCTNAME
        Push ${MSINSISPRODUCTNAME}
        Call MsiGetProductCodeFromName
!macroend

Function MsiGetProductCodeFromName
    ;================
    ; Stack : <ProductName>, ...
    ;================

    Exch $0         ; ProductName
    Push $1         ; For internal use as buffer for ProductCode
    Push $2         ; For internal use as counter to MsiEnumProducts
    Push $3         ; For internal use as result of MsiEnumProducts

    ; loop through all productcodes
    Strcpy $2 0

    System::Call "advapi32::GetUserName(t .r0, *i ${NSIS_MAX_STRLEN} r1) i.r2"
    DetailPrint "User name - $0"
    DetailPrint "String length - $1"
    DetailPrint "Return value - $2"

    loop:
    DetailPrint "Calling MsiEnumProducts ( $2, $1 )"
    System::call "msi::MsiEnumProducts (i r2, t .r1) i.r3"
    DetailPrint "Result = $3"
    System::call "kernel32::GetLastError () i.r3"
    DetailPrint "LastError = $3"
    ${If} $R1 == 0
            DetailPrint $1
            Intop $R0 $R0 + 1
            goto loop
    ${Endif}

    end:

    Pop $3
    Pop $2
    Exch
    Pop $0

    ;=========================
    ; Stack : <ProductCode>, ...
    ; ========================
FunctionEnd

When I use the above script in the following manner:

${MsiGetProductCodeFromName} ${PRODUCT_NAME}

I am getting the following output:

Calling MsiEnumProducts(0, )
Result = error
LastError = error
Completed

Please note that this is excluding the output of System call to GetUserName, which is working fine.

Any help would be appreciated.

Upvotes: 1

Views: 1108

Answers (1)

Anders
Anders

Reputation: 101756

The first call to MsiEnumProducts has to start at index 0 so add Strcpy $2 0 before the loop label.

I'm not sure if you can have a space between dll::function and (), when you just get "error" from the system plugin it usually means there is something wrong with the syntax.

You cannot call kernel32::GetLastError and get a valid result, it has to be part of the original call: System::Call 'dll::function() ?e' and then pop the error code off the stack...

Upvotes: 2

Related Questions