Run a VBScript from NSIS

From NSIS Wiki
Jump to navigationJump to search

Synopsis

Sometimes, it's just easier to run a VBScript. This is particularly useful when repackaging software for corporate deployments, At least until someone make accessing COM+ easier in NSIS.

  • Verified working with the Unicode build of NSIS.

Known Issues

Please keep in mind that the target system may have VBScript disabled or even blocked by anti-virus software.

NOT WORKING YET

Simple Example

VBScript

SimpleVBScript.vbs

'## When executing VBScripts in batch mode, Any output we want to capture must be sent to the console using StdOut.
	WScript.StdOut.WriteLine "First Line output by VBScript."
 
'## When executing VBScripts in batch mode, these two lines of vbscript will not execute
	WScript.Echo "This line will not be displayed when executing in batch mode."
 
'## Just anouther line of data to be captured.	
	WScript.StdOut.WriteLine "Anouther Line output by VBScript."
 
'## Set ErrorLevel to 512, Why? Sometimes a script will fail and still return 0 as the ErrorLevel.
'## If we explicitly set a Success code then we can avoid this.
	WScript.Quit 512

NSIS Example

SimpleVBScript.nsi

OutFile SimpleVBScript.exe
 
Section Example
 
    GetTempFileName $0
 
    File /oname=$0 `SimpleVBScript.vbs`
 
    nsExec::ExecToStack `"$SYSDIR\CScript.exe" $0 //e:vbscript //B //NOLOGO`
 
    ## Get & Test Return Code
        Pop $0
        DetailPrint `Return Code = $0`
 
    ## Get the Captured Data
        Pop $1
        DetailPrint `VB: $1`
 
        Pop $2
        DetailPrint `VB: $2`
 
SectionEnd

Advanced Example

This example shows how to use a vbscript to identify the number of active logon sessions. This is useful for corporate deployments when it is beneficial to detect if the target system does not have any active users logged on. (And this includes terminal sessions!)

VBScript

InteractiveLogonSessionsCount.vbs

On Error Resume Next
Dim Count
 
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
If Err Then
	WScript.StdOut.WriteLine "Unable to access WMI Service."
	MsgBox "Unable to access WMI Service.", vbCritical, "Get Count of Interactive Logon Sessions"
	WScript.Quit 32
End If
 
Set colItems = objWMIService.ExecQuery("Select * from Win32_LogonSession WHERE LogonType=2 Or LogonType=10")
If Err Then
	WScript.StdOut.WriteLine "WMI ExecQuery Failed."
	MsgBox "WMI ExecQuery Failed.", vbCritical, "Get Count of Interactive Logon Sessions"
	WScript.Quit 64
End If
 
Count = CLng(colItems.Count)
 
If Err Then
	WScript.StdOut.WriteLine "Unable to get the LogonSession count due to an error."
	MsgBox "Unable to get the LogonSession count due to an error.", vbCritical, "Get Count of Interactive Logon Sessions"
	WScript.Quit 128
End If
 
WScript.StdOut.WriteLine Count
MsgBox "There are " & Count & " interactive logon sessions.", vbInformation, "Get Count of Interactive Logon Sessions"
WScript.Quit 512

NSIS Example

Advanced VBScript Example.nsi

OutFile Example.exe
Name `Interactive Logon Session Count \ VBScript Example`
 
!define InteractiveLogonSessionsCount "!insertmacro InteractiveLogonSessionsCount"
!macro InteractiveLogonSessionsCount _Count
    Call InteractiveLogonSessionsCount
    Pop ${_Count}
!macroend
 
Section Example
 
    ${InteractiveLogonSessionsCount} $0
    DetailPrint `Returned=$0`
 
SectionEnd
 
Function InteractiveLogonSessionsCount
    Push $0 ;Stack: $0
    Push $1 ;Stack: $1 $0
 
    InitPluginsDir
 
    GetTempFileName $0 $PLUGINSDIR
 
    SetDetailsPrint none
    File /oname=$0 `InteractiveLogonSessionsCount.vbs`
 
    Push `<ENDOFSCRIPT>` ;Stack: eos $1 $0
    nsExec::ExecToStack `"$SYSDIR\CScript.exe" "$0" //e:vbscript //B //NOLOGO`
    SetDetailsPrint both
 
    ## Get the return Code
        Pop $0
        StrCmp $0 512 0 ScriptError
 
    ## Get the count
        Pop $0
        DetailPrint `Detected Interactive Logon Sessions: $0`
 
    ## Remove the ENDOFSTACK key from stack
        Pop $1 ;Stack: $1 $0
 
    Goto End
    ScriptError:
 
    ## Display Error
        Loop:
            Pop $1
            StrCmp $1 `<ENDOFSCRIPT>` EndLoop
            DetailPrint `VBS: $1`
            Goto Loop
        EndLoop: ;Stack: $1 $0
        StrCpy $0 -1
    End:
 
    Pop $1  ;Stack: $0
    Exch $0 ;Stack: Count
 
FunctionEnd

Sample Details Output

Extract: C:\DOCUME~1\ra053132\LOCALS~1\Temp\nsp23C.tmp\nsp23D.tmp... 100%
Detected Interactive Logon Sessions: 1

Returned=1

Completed