StdUtils plug-in: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
Line 407: Line 407:


== GetParameter ==
== GetParameter ==
With ''${StdUtils.GetParameter}'' you can check for the presence of a specific command-line parameter.
If the parameter was specified with a value, then the parameter's value is return. If the parameter was specified ''without'' a value, then an empty string is return. If the parameter is has '''not''' been specified, then the ''default'' value is returned.
Parameters can be passed to the installer like this:
* <tt>Installer.exe /Foobar</tt>
* <tt>Installer.exe /Foobar=SomeValue</tt>
* <tt>Installer.exe "/Foobar=Some Value With Whitespaces"</tt>


<highlight-nsis>!include 'StdUtils.nsh'
<highlight-nsis>!include 'StdUtils.nsh'

Revision as of 23:57, 8 October 2011

Author: Instructor (talk, contrib)


This plug-in provides access to a number of "standard" functions from C Standard Library, which programmers are used to from their C/C++ compilers (and other languages), but which are not available in NSIS by default. In order to keep the plug-in size as small as possible (~9 KB) and for maximum compatibility, the Visual C++ Run-Time v6.0 (MSVCRT.DLL), which is included with all versions of Windows (since Windows 2000), is used - instead of linking the Visual C++ Run-Time library into the plug-in DLL.

Additionally this plug-in provides wrappers for the SHFileOperation function. Moreover it provides a method for launching programs in a non-elevated way (user context) from an elevated installer (admin mode) on UAC-enabled systems - see this thread for details! Last but not least, a version of ExecShell with "wait for process termination" feature, based on ShellExecuteEx, is provided.

ANSI and Unicode builds available!

Available Functions

!define StdUtils.Time            '!insertmacro _StdUtils_Time'         #time()
!define StdUtils.Rand            '!insertmacro _StdUtils_Rand'         #rand()
!define StdUtils.RandMax         '!insertmacro _StdUtils_RandMax'      #rand() with maximum
!define StdUtils.RandMinMax      '!insertmacro _StdUtils_RandMinMax'   #rand() with minimum/maximum
!define StdUtils.RandList        '!insertmacro _StdUtils_RandList'     #rand() with list support
!define StdUtils.FormatStr       '!insertmacro _StdUtils_FormatStr'    #sprintf() with one format tag (only %d supported!)
!define StdUtils.FormatStr2      '!insertmacro _StdUtils_FormatStr2'   #sprintf() with two format tags (only %d supported!)
!define StdUtils.FormatStr3      '!insertmacro _StdUtils_FormatStr3'   #sprintf() with three format tags (only %d supported!)
!define StdUtils.ScanStr         '!insertmacro _StdUtils_ScanStr'      #sscanf() with one format tag (only %d supported!)
!define StdUtils.ScanStr2        '!insertmacro _StdUtils_ScanStr2'     #sscanf() with two format tags (only %d supported!)
!define StdUtils.ScanStr3        '!insertmacro _StdUtils_ScanStr3'     #sscanf() with three format tags (only %d supported!)
!define StdUtils.TrimStr         '!insertmacro _StdUtils_TrimStr'      #Remove whitspaces from string (left and right)
!define StdUtils.TrimStrLeft     '!insertmacro _StdUtils_TrimStrLeft'  #Remove whitspaces from string (left side only)
!define StdUtils.TrimStrRight    '!insertmacro _StdUtils_TrimStrRight' #Remove whitspaces from string (right side only)
!define StdUtils.SHFileMove      '!insertmacro _StdUtils_SHFileMove'   #SHFileOperation with FO_MOVE
!define StdUtils.SHFileCopy      '!insertmacro _StdUtils_SHFileCopy'   #SHFileOperation with FO_COPY
!define StdUtils.ExecShellAsUser '!insertmacro _StdUtils_ExecShlUser'  #ShellExecute() with user context (for elevated installers)
!define StdUtils.ExecShellWait   '!insertmacro _StdUtils_ExecShlWait'  #ShellExecuteEx() with process handle to wait for
!define StdUtils.WaitForProc     '!insertmacro _StdUtils_WaitForProc'  #WaitForSingleObject() to wait for process termination
!define StdUtils.GetParameter    '!insertmacro _StdUtils_GetParameter' #Get the value of a specific commandline paramater
!define StdUtils.Unload          '!insertmacro _StdUtils_Unload'       #Unload DLL for proper clean-up (don't forget!)
!define StdUtils.SetVerbose      '!insertmacro _StdUtils_SetVerbose'   #Verbose mode (for debugging)
 
 
!macro _StdUtils_Time out
	StdUtils::Time /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_Rand out
	StdUtils::Rand /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_RandMax out max
	push ${max}
	StdUtils::RandMax /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_RandMinMax out min max
	push ${min}
	push ${max}
	StdUtils::RandMinMax /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_RandList count max
	push ${max}
	push ${count}
	StdUtils::RandList /NOUNLOAD
!macroend
 
!macro _StdUtils_FormatStr out format val
	push '${format}'
	push ${val}
	StdUtils::FormatStr /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_FormatStr2 out format val1 val2
	push '${format}'
	push ${val1}
	push ${val2}
	StdUtils::FormatStr2 /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_FormatStr3 out format val1 val2 val3
	push '${format}'
	push ${val1}
	push ${val2}
	push ${val3}
	StdUtils::FormatStr3 /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_ScanStr out format input default
	push '${format}'
	push '${input}'
	push ${default}
	StdUtils::ScanStr /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_ScanStr2 out1 out2 format input default1 default2
	push '${format}'
	push '${input}'
	push ${default1}
	push ${default2}
	StdUtils::ScanStr2 /NOUNLOAD
	pop ${out1}
	pop ${out2}
!macroend
 
!macro _StdUtils_ScanStr3 out1 out2 out3 format input default1 default2 default3
	push '${format}'
	push '${input}'
	push ${default1}
	push ${default2}
	push ${default3}
	StdUtils::ScanStr3 /NOUNLOAD
	pop ${out1}
	pop ${out2}
	pop ${out3}
!macroend
 
!macro _StdUtils_TrimStr var
	push ${var}
	StdUtils::TrimStr /NOUNLOAD
	pop ${var}
!macroend
 
!macro _StdUtils_TrimStrLeft var
	push ${var}
	StdUtils::TrimStrLeft /NOUNLOAD
	pop ${var}
!macroend
 
!macro _StdUtils_TrimStrRight var
	push ${var}
	StdUtils::TrimStrRight /NOUNLOAD
	pop ${var}
!macroend
 
!macro _StdUtils_SHFileMove out from to hwnd
	push '${from}'
	push '${to}'
	push ${hwnd}
	StdUtils::SHFileMove /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_SHFileCopy out from to hwnd
	push '${from}'
	push '${to}'
	push ${hwnd}
	StdUtils::SHFileCopy /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_ExecShlUser out file verb args
	push '${file}'
	push '${verb}'
	push '${args}'
	StdUtils::ExecShellAsUser /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_ExecShlWait out file verb args
	push '${file}'
	push '${verb}'
	push '${args}'
	StdUtils::ExecShellWait /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_WaitForProc handle
	push '${handle}'
	StdUtils::WaitForProc /NOUNLOAD
!macroend
 
!macro _StdUtils_GetParameter out name default
	push '${name}'
	push '${default}'
	StdUtils::GetParameter /NOUNLOAD
	pop ${out}
!macroend
 
!macro _StdUtils_Unload
	StdUtils::Unload
!macroend
 
!macro _StdUtils_SetVerbose on
	!if "${on}" != "0"
		StdUtils::EnableVerboseMode /NOUNLOAD
	!else
		StdUtils::DisableVerboseMode /NOUNLOAD
	!endif
!macroend

Example

This example tests miscellaneous functions of the StdUtils plug-in:

!include 'StdUtils.nsh'
 
RequestExecutionLevel user
ShowInstDetails show
 
Section
	${StdUtils.Time} $1
	DetailPrint "Time: $1"
	Sleep 500
	${StdUtils.Time} $1
	DetailPrint "Time: $1"
	Sleep 500
	${StdUtils.Time} $1
	DetailPrint "Time: $1"
SectionEnd
 
Section
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
	${StdUtils.Rand} $1
	DetailPrint "Random: $1"
SectionEnd
 
Section
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
	${StdUtils.RandMax} $1 42
	DetailPrint "Random Max: $1"
SectionEnd
 
Section
	${StdUtils.RandMinMax} $1 -4 -2
	DetailPrint "Random Min/Max: $1"
	${StdUtils.RandMinMax} $1 -4 -2
	DetailPrint "Random Min/Max: $1"
	${StdUtils.RandMinMax} $1 -4 -2
	DetailPrint "Random Min/Max: $1"
	${StdUtils.RandMinMax} $1 -4 -2
	DetailPrint "Random Min/Max: $1"
	${StdUtils.RandMinMax} $1 -4 -2
	DetailPrint "Random Min/Max: $1"
	${StdUtils.RandMinMax} $1 20 21
	DetailPrint "Random Min/Max: $1"
SectionEnd
 
Section
	${StdUtils.FormatStr} $1 "Hello World is %05d woha!" 89
	DetailPrint "FormatStr: $1"
	${StdUtils.FormatStr2} $1 "Hello World is %05d and %05d woha!" 89 384
	DetailPrint "FormatStr: $1"
	${StdUtils.FormatStr3} $1 "Hello World is %05d and %05d or even %05d woha!" 89 384 2384
	DetailPrint "FormatStr: $1"
	${StdUtils.FormatStr} $1 "Hello World is %09000d." 89
	DetailPrint "FormatStr: $1"
SectionEnd
 
Section
	${StdUtils.RandList} 50 100
	Pop $1
	StrCmp $1 EOL +3
	DetailPrint "RandList: $1"
	Goto -3
SectionEnd
 
Section
	${StdUtils.ScanStr} $0 "Der Test sagt %d ist toll!" "Der Test sagt 571 ist toll!" 42
	DetailPrint "ScanStr: $0"
	${StdUtils.ScanStr} $0 "Der Hund sagt %d ist toll!" "Der Test sagt 571 ist toll!" 42
	DetailPrint "ScanStr: $0"
SectionEnd
 
Section
	${StdUtils.ScanStr2} $0 $1 "Der Test sagt %d sowie %d ist toll!" "Der Test sagt 571 sowie 831 ist toll!" 42 43
	DetailPrint "ScanStr2: $0, $1"
	${StdUtils.ScanStr2} $0 $1 "Der Test sagt %d sowie %d ist toll!" "Der Test sagt 571 horch 831 ist toll!" 42 43
	DetailPrint "ScanStr2: $0, $1"
	${StdUtils.ScanStr2} $0 $1 "Der Test sagt %d sowie %d ist toll!" "Der Hund sagt 571 horch 831 ist toll!" 42 43
	DetailPrint "ScanStr2: $0, $1"
SectionEnd
 
Section
	${StdUtils.ScanStr3} $0 $1 $2 "Der Test sagt %d sowie %d ist toll! Und %d." "Der Test sagt 571 sowie 831 ist toll! Und 325" 42 43 44
	DetailPrint "ScanStr3: $0, $1, $2"
	${StdUtils.ScanStr3} $0 $1 $2 "Der Test sagt %d sowie %d ist toll! Und %d." "Der Test sagt 571 sowie 831 ist toll! OMG 325" 42 43 44
	DetailPrint "ScanStr3: $0, $1, $2"
	${StdUtils.ScanStr3} $0 $1 $2 "Der Test sagt %d sowie %d ist toll! Und %d." "Der Test sagt 571 horch 831 ist toll! OMG 325" 42 43 44
	DetailPrint "ScanStr3: $0, $1, $2"
	${StdUtils.ScanStr3} $0 $1 $2 "Der Test sagt %d sowie %d ist toll! Und %d." "Der Hund sagt 571 horch 831 ist toll! OMG 325" 42 43 44
	DetailPrint "ScanStr3: $0, $1, $2"
SectionEnd
 
Section
	InitPluginsDir
	SetOutPath "$PLUGINSDIR\TestDirA"
	File "${NSISDIR}\Contrib\Graphics\Checks\*.*"
	SetOutPath "$PLUGINSDIR\TestDirA\SubDir"
	File "${NSISDIR}\Contrib\Graphics\Header\*.*"
	CreateDirectory "$PLUGINSDIR\SubDirX"
	CreateDirectory "$PLUGINSDIR\SubDirY"
 
	${StdUtils.SHFileCopy} $0 "$PLUGINSDIR\TestDirA" "$PLUGINSDIR\SubDirX\TestDirB" $HWNDPARENT
	DetailPrint "SHFileCopy: $0"
	${StdUtils.SHFileMove} $0 "$PLUGINSDIR\TestDirA" "$PLUGINSDIR\SubDirY\TestDirC" $HWNDPARENT
	DetailPrint "SHFileMove: $0"
	ExecShell "explore" "$PLUGINSDIR"
SectionEnd
 
Section
	${StdUtils.SHFileCopy} $0 "$PLUGINSDIR\TestDirXYZ" "$PLUGINSDIR\SubDirX\TestDirZ" $HWNDPARENT
	DetailPrint "SHFileCopy: $0"
 
	${StdUtils.SetVerbose} 1
	${StdUtils.SHFileCopy} $0 "$PLUGINSDIR\TestDirXYZ" "$PLUGINSDIR\SubDirX\TestDirZ" $HWNDPARENT
	DetailPrint "SHFileCopy: $0"
 
	${StdUtils.SetVerbose} 0
	${StdUtils.SHFileCopy} $0 "$PLUGINSDIR\TestDirXYZ" "$PLUGINSDIR\SubDirX\TestDirZ" $HWNDPARENT
	DetailPrint "SHFileCopy: $0"
SectionEnd
 
Section
	StrCpy $1 "        Some Text            "
 
	StrCpy $0 $1
	DetailPrint "String: '$0'"
	${StdUtils.TrimStr} $0
	DetailPrint "TrimStr: '$0'"
 
	StrCpy $0 $1
	DetailPrint "String: '$0'"
	${StdUtils.TrimStrLeft} $0
	DetailPrint "TrimStrLeft: '$0'"
 
	StrCpy $0 $1
	DetailPrint "String: '$0'"
	${StdUtils.TrimStrRight} $0
	DetailPrint "TrimStrRight: '$0'"
SectionEnd
 
Section
	${StdUtils.Unload}
SectionEnd

ExecShellAsUser

!include 'StdUtils.nsh'
 
RequestExecutionLevel admin ;make sure our installer will get elevated on Vista+ with UAC enabled
ShowInstDetails show
 
Section
	DetailPrint 'ExecShell: "$SYSDIR\mspaint.exe"'
	ExecShell "open" "$SYSDIR\mspaint.exe" ;this instance of MS Paint will be elevated too!
	MessageBox MB_TOPMOST "Close Paint and click 'OK' to continue..."
SectionEnd
 
Section
	DetailPrint 'ExecShellAsUser: "$SYSDIR\mspaint.exe"'
	Sleep 1000
	${StdUtils.ExecShellAsUser} $0 "$SYSDIR\mspaint.exe" "open" "" ;launch a *non-elevated* instance of MS Paint
	DetailPrint "Result: $0" ;expected result is "ok" on UAC-enabled systems or "fallback" otherwise. Failure indicated by "error" or "timeout".
	${StdUtils.Unload} ;please do not forget to unload!
SectionEnd

ExecShellWait

!include 'StdUtils.nsh'
 
RequestExecutionLevel user
ShowInstDetails show
 
Section
	DetailPrint 'ExecShellWait: "$SYSDIR\mspaint.exe"'
	Sleep 1000
	${StdUtils.ExecShellWait} $0 "$SYSDIR\mspaint.exe" "open" "" ;try to launch the process
	DetailPrint "Result: $0" ;returns process handle. Might be "no_wait". Failure indicated by "error".
	StrCmp $0 "error" WaitFailed ;check if process failed to create.
	StrCmp $0 "no_wait" WaitNotPossible ;check if process can be waited for. Always check this!
 
	DetailPrint "Waiting for process. ZZZzzzZZZzzz..."
	${StdUtils.WaitForProc} $0
	DetailPrint "Process just terminated."
	Goto WaitDone
 
	WaitFailed:
	DetailPrint "Failed to create process !!!"
	Goto WaitDone
 
	WaitNotPossible:
	DetailPrint "Can not wait for process."
	Goto WaitDone
 
	WaitDone:
	${StdUtils.Unload} ;please do not forget to unload!
SectionEnd

GetParameter

With ${StdUtils.GetParameter} you can check for the presence of a specific command-line parameter.

If the parameter was specified with a value, then the parameter's value is return. If the parameter was specified without a value, then an empty string is return. If the parameter is has not been specified, then the default value is returned.

Parameters can be passed to the installer like this:

  • Installer.exe /Foobar
  • Installer.exe /Foobar=SomeValue
  • Installer.exe "/Foobar=Some Value With Whitespaces"
!include 'StdUtils.nsh'
 
RequestExecutionLevel user
ShowInstDetails show
 
Section
	${StdUtils.GetParameter} $R0 "Foobar" "<N/A>"
 
	StrCmp "$R0" "<N/A>" 0 +3
	DetailPrint "Parameter /Foobar is *not* specified!"
	Goto Finished
 
	StrCmp "$R0" "" 0 +3 ;'Installer.exe [...] /Foobar'
	DetailPrint "Parameter /Foobar specified without a value." 
	Goto Finished
 
	;'Installer.exe /Foobar=Foo' or 'Installer.exe "/Foobar=Foo Bar"'
	${StdUtils.TrimStr} $R0
	DetailPrint "Value of parameter /Foobar is: '$R0'"
 
	Finished:
	${StdUtils.Unload} ;please do not forget to unload!
SectionEnd

Download

Download:
StdUtils.2011-10-09.zip (104 KB)

SVN Repository:
http://code.google.com/p/mulder/source/browse/trunk/Utils/nsis_stdutils/