Inject MSI Property at Compile-Time: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
m (→‎Macro: Removed the notpad call that was left in when I was testing.)
(Initial Release)
Line 1: Line 1:
{{PageAuthor|Zinthose}}
{{PageAuthor|Zinthose}}
== About ==
== About ==
This macro provides a compile-time ability to inject Microsoft Installer Database file properties at compile time. It uses a dynamically created VBScript to open the MSI file and read the property then creates the requested property value.
This snippet was developed to address an issue with Windows x64 incorrectly redirecting the shortcuts icon from $PROGRAMFILES32 to $PROGRAMFILES64.
[http://forums.winamp.com/newreply.php?do=postreply&t=327806 See forum post]


== Macro ==
== Macro ==
<highlight-nsis>/********************
<highlight-nsis>/******************************************************************************
     !MSIPropertyGet
     WORKAROUND - FixShortcut
         This macro provides a compile-time ability to inject Microsoft Installer Database file properties at compile time.
         This snippet was developed to address an issue with Windows
       
        x64 incorrectly redirecting the shortcuts icon from $PROGRAMFILES32
        to $PROGRAMFILES64.
   
    See Forum post: http://forums.winamp.com/newreply.php?do=postreply&t=327806
   
     Example:
     Example:
         ${!MSIPropertyGet} "SomePackage.ProductName"   "SomePackage.msi" "ProductName"
         CreateShortcut "$SMPROGRAMS\My App\My App.lnk" "$INSTDIR\My App.exe" "" "$INSTDIR\My App.exe"
         ${!MSIPropertyGet} "SomePackage.ProductVersion" "SomePackage.msi" "ProductVersion"
         ${lnkX64IconFix} "$SMPROGRAMS\My App\My App.lnk"
          
          
        !define DisplayName `${SomePackage.ProductName} v${SomePackage.ProductVersion}`
    Original Code by Anders [http://forums.winamp.com/member.php?u=70852]
        OutFile Test.exe
  ******************************************************************************/
        Name `${DisplayName} Special Build`
!ifndef ___lnkX64IconFix___
        Section
     !verbose push
        SectionEnd
  ********************/
!verbose push
!verbose 0
!define !MSIPropertyGet `!insertmacro _!MSIPropertyGet`
!macro _!MSIPropertyGet _DefineToCreate _MSIFilePath _PropertyToRead
     !verbose Push
     !verbose 0
     !verbose 0
     !if `${_DefineToCreate}` == ``
   
        !define __DefineToCreate `${_PropertyToRead}`
     !include "LogicLib.nsh"
     !else
    !include "x64.nsh"
        !define __DefineToCreate `${_DefineToCreate}`
   
     !endif
     !define ___lnkX64IconFix___
    !ifdef `${__DefineToCreate}`
    !define lnkX64IconFix `!insertmacro _lnkX64IconFix`
         !verbose 1
     !macro _lnkX64IconFix _lnkPath
         !error "!MSIPropertyGet: Value previously defined! [${__DefineToCreate}=${${__DefineToCreate}}]"
        !verbose push
     !else
         !verbose 0
         !tempfile MSIPropertyGet_VBScript
         ${If} ${RunningX64}
         !appendfile `${MSIPropertyGet_VBScript}` `Set A=WScript.Arguments:Set B=CreateObject("WindowsInstaller.Installer").OpenDatabase(A(2),0)`
            DetailPrint "WORKAROUND: 64bit OS Detected, Attempting to apply lnkX64IconFix"
         !appendfile `${MSIPropertyGet_VBScript}` `.OpenView("SELECT Value FROM Property WHERE Property='"&A(3)&"'"):B.Execute:Set C=CreateObjec`
            Push "${_lnkPath}"
        !appendfile `${MSIPropertyGet_VBScript}` `t("Scripting.Filesystemobject"):Set D=C.OpenTextFile(A(0),2,1):D.WriteLine "!define $\`"&A(1)`
            Call lnkX64IconFix
        !appendfile `${MSIPropertyGet_VBScript}` `&"$\` $\`"&B.Fetch.StringData(1)&"$\`":D.Close`
        ${EndIf}
        !tempfile MSIPropertyGet_Result
        !verbose pop
        !system `WScript.exe "${MSIPropertyGet_VBScript}" //B //E:VBSCRIPT //T:30 "${MSIPropertyGet_Result}" "${__DefineToCreate}" "${_MSIFilePath}" "${_PropertyToRead}"` = 0
     !macroend
        !include "${MSIPropertyGet_Result}"
   
        !delfile `${MSIPropertyGet_VBScript}`
    Function lnkX64IconFix ; _lnkPath
        !delfile `${MSIPropertyGet_Result}`
         Exch $5
        !undef MSIPropertyGet_VBScript
        Push $0
        !undef MSIPropertyGet_Result
        Push $1
        !ifndef `${__DefineToCreate}`
        Push $2
             !error "!MSIPropertyGet: Value was not defined! [${__DefineToCreate}] Ensure the MSI file exists and is not locked from reading"
        Push $3
         !else if `${${__DefineToCreate}}` == ``
         Push $4
            !warning "!MSIPropertyGet: Value is a zero length string! [${__DefineToCreate}=${${__DefineToCreate}}]"
        System::Call 'OLE32::CoCreateInstance(g "{00021401-0000-0000-c000-000000000046}",i 0,i 1,g "{000214ee-0000-0000-c000-000000000046}",*i.r1)i'
         !endif
         ${If} $1 <> 0
    !endif
            System::Call '$1->0(g "{0000010b-0000-0000-C000-000000000046}",*i.r2)'
     !undef __DefineToCreate
            ${If} $2 <> 0
                System::Call '$2->5(w r5,i 2)i.r0'
                ${If} $0 = 0
                    System::Call '$1->0(g "{45e2b4ae-b1c3-11d0-b92f-00a0c90312e1}",*i.r3)i.r0'
                    ${If} $3 <> 0
                        System::Call '$3->5(i 0xA0000007)i.r0'
                        System::Call '$3->6(*i.r4)i.r0'
                        ${If} $0 = 0
                            IntOp $4 $4 & 0xffffBFFF
                            System::Call '$3->7(ir4)i.r0'
                            ${If} $0 = 0
                                System::Call '$2->6(i0,i0)'
                                DetailPrint "WORKAROUND: lnkX64IconFix Applied successfully"
                            ${EndIf}
                        ${EndIf}
                        System::Call $3->2()
                    ${EndIf}
                ${EndIf}
                System::Call $2->2()
            ${EndIf}
             System::Call $1->2()
         ${EndIf}  
        Pop $4
        Pop $3
        Pop $2
         Pop $1
        Pop $0
     FunctionEnd
     !verbose pop
     !verbose pop
!macroend
!endif</highlight-nsis>
!verbose pop</highlight-nsis>
[[Category:Compile-Time Macros]]
[[Category:Compile-Time Macros]]

Revision as of 19:20, 25 February 2011

Author: Zinthose (talk, contrib)


About

This snippet was developed to address an issue with Windows x64 incorrectly redirecting the shortcuts icon from $PROGRAMFILES32 to $PROGRAMFILES64. See forum post

Macro

/******************************************************************************
    WORKAROUND - FixShortcut
        This snippet was developed to address an issue with Windows 
        x64 incorrectly redirecting the shortcuts icon from $PROGRAMFILES32 
        to $PROGRAMFILES64.
 
    See Forum post: http://forums.winamp.com/newreply.php?do=postreply&t=327806
 
    Example:
        CreateShortcut "$SMPROGRAMS\My App\My App.lnk" "$INSTDIR\My App.exe" "" "$INSTDIR\My App.exe"
        ${lnkX64IconFix} "$SMPROGRAMS\My App\My App.lnk"
 
    Original Code by Anders [http://forums.winamp.com/member.php?u=70852]
 ******************************************************************************/
!ifndef ___lnkX64IconFix___
    !verbose push
    !verbose 0
 
    !include "LogicLib.nsh"
    !include "x64.nsh"
 
    !define ___lnkX64IconFix___
    !define lnkX64IconFix `!insertmacro _lnkX64IconFix`
    !macro _lnkX64IconFix _lnkPath
        !verbose push
        !verbose 0
        ${If} ${RunningX64}
            DetailPrint "WORKAROUND: 64bit OS Detected, Attempting to apply lnkX64IconFix"
            Push "${_lnkPath}"
            Call lnkX64IconFix
        ${EndIf}
        !verbose pop
    !macroend
 
    Function lnkX64IconFix ; _lnkPath
        Exch $5
        Push $0
        Push $1
        Push $2
        Push $3
        Push $4
        System::Call 'OLE32::CoCreateInstance(g "{00021401-0000-0000-c000-000000000046}",i 0,i 1,g "{000214ee-0000-0000-c000-000000000046}",*i.r1)i'
        ${If} $1 <> 0
            System::Call '$1->0(g "{0000010b-0000-0000-C000-000000000046}",*i.r2)'
            ${If} $2 <> 0
                System::Call '$2->5(w r5,i 2)i.r0'
                ${If} $0 = 0
                    System::Call '$1->0(g "{45e2b4ae-b1c3-11d0-b92f-00a0c90312e1}",*i.r3)i.r0'
                    ${If} $3 <> 0
                        System::Call '$3->5(i 0xA0000007)i.r0'
                        System::Call '$3->6(*i.r4)i.r0'
                        ${If} $0 = 0 
                            IntOp $4 $4 & 0xffffBFFF
                            System::Call '$3->7(ir4)i.r0'
                            ${If} $0 = 0 
                                System::Call '$2->6(i0,i0)'
                                DetailPrint "WORKAROUND: lnkX64IconFix Applied successfully"
                            ${EndIf}
                        ${EndIf}
                        System::Call $3->2()
                    ${EndIf}
                ${EndIf}
                System::Call $2->2()
            ${EndIf}
            System::Call $1->2()
        ${EndIf} 
        Pop $4
        Pop $3
        Pop $2
        Pop $1
        Pop $0
    FunctionEnd
    !verbose pop
!endif