<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://nsis.sourceforge.io/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Animaether</id>
	<title>NSIS Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://nsis.sourceforge.io/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Animaether"/>
	<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/Special:Contributions/Animaether"/>
	<updated>2026-04-05T18:12:31Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11270</id>
		<title>Repair path names with ..</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11270"/>
		<updated>2006-10-01T21:11:02Z</updated>

		<summary type="html">&lt;p&gt;Animaether: added third note and function-using section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;you have a path with relative path parts, such as&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
\\	; does nothing&lt;br /&gt;
\.\	; stay in same folder&lt;br /&gt;
\..\	; go up a folder&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you need the absolute path, then you can use the &amp;quot;GetFullPathName&amp;quot; command in NSIS to get the absolute path.	For example:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
	GetFullPathName $0 &amp;quot;c:\program files\myApp\somedir\subdir\..\somefile.ext&amp;quot;&lt;br /&gt;
	; $0 will now contain &amp;quot;c:\program files\myApp\somedir\somefile.ext&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note 1: if you specify a filename, that file has to exist or the result is null.It is therefore recommended that if you need the absolute path without necessarily having the file in existence, that you strip the filename from the path.&lt;br /&gt;
&lt;br /&gt;
Note 2: this command is limited to a 256-character string, even if the resulting absolute path is shorter than 256 characters.&lt;br /&gt;
&lt;br /&gt;
Note 3: if the string being fed does not start with an absolute reference, it will be treated as if relative to the current working folder, and the absolute path result will reflect this.  E.g.&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
	GetFullPathName $0 &amp;quot;FooBar\&amp;quot;&lt;br /&gt;
	; $0 may now contain &amp;quot;c:\test\Foobar\&amp;quot; if the installer was executed in &amp;quot;c:\test\&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If any of the above notes may preclude you from using this Command, try the below Function instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Rel2Abs&amp;quot;&lt;br /&gt;
	Push &amp;quot;c:\Alpha\\\Bravo\\Charlie..charles\\.\delta\\echo\\..\..\foxtrot\\..\Golf\\.\Hotel\\.\india\\..\\\\juliet\\..\kilo\\\..\Li.....ma\\.\..Mike\\\November\\.\oscar\\..\Papa\\\Quebec..\\\\\\\\Romeo\\sierra\\..\tang.o\\uniform\\victor\\..\whiskey\\..\\x-ray\\yankee\\..\..\.\..\..\Zu.lu\\file.ext&amp;quot;&lt;br /&gt;
	Call Abs2Rel&lt;br /&gt;
	Pop $0&lt;br /&gt;
	MessageBox MB_OK &amp;quot;Expected:$\tc:\Alpha\Bravo\Charlie..charles\Golf\Hotel\Li.....ma\..Mike\November\Papa\Quebec..\Romeo\Zu.lu\file.ext$\r$\nResult:$\t$\t$0&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
Function Abs2Rel&lt;br /&gt;
	; Stack -&amp;gt;		; &amp;lt;relative path&amp;gt;			; This and the stuff in the column below is just to keep track of the stack before and after the function so that it&#039;s clean at the end.&lt;br /&gt;
	Exch $R0		; R0						; $R0 now holds the relative path&lt;br /&gt;
	Push $0			; 0 R0						; $0 will hold the absolute path as it is being built&lt;br /&gt;
	Push $1			; 1 0 R0					; $1 will hold the length of the relative path&lt;br /&gt;
	Push $2			; 2 1 0 R0					; $2 will hold a counter for running along the path&lt;br /&gt;
	Push $3			; 3 2 1 0 R0				; $3 will hold a substring of the paths to test against&lt;br /&gt;
&lt;br /&gt;
	StrCpy $0 $R0 1 0						 	; Start by getting the first character of the relative path into the absolute path var&lt;br /&gt;
	StrLen $1 $R0								 ; Get the length of the relative path&lt;br /&gt;
	StrCpy $2 0								 ; And start the counter off at zero&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\\\Bravo\\Charlie..charles\\.\delta\\echo\\..\..\foxtrot\\..\Golf\\.\Hotel\\.\india\\..\\\\juliet\\..\kilo\\\..\Li.....ma\\.\..Mike\\\November\\.\oscar\\..\Papa\\\Quebec..\\\\\\\\Romeo\\sierra\\..\tang.o\\uniform\\victor\\..\whiskey\\..\\x-ray\\yankee\\..\..\.\..\..\Zu.lu\\file.ext&lt;br /&gt;
&lt;br /&gt;
	; double									; This section will get rid of all double backslashes.&lt;br /&gt;
		_loop_double:							 ; top of the loop&lt;br /&gt;
			IntOp $2 $2 + 1					 ; increase the counter&lt;br /&gt;
			IntCmp $2 $1 0 0 _sameDir			 ; if the counter exceeds the relative path&#039;s length, move on&lt;br /&gt;
			StrCpy $3 $R0 2 $2					; get two characters from the relative pah, starting at the position of the counter&lt;br /&gt;
			StrCmp $3 &amp;quot;\\&amp;quot; _loop_double		 ; if it&#039;s a double backslash, just go back to the top of the loop&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; otherwise, get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; and add that character to the absolute path being built&lt;br /&gt;
			goto _loop_double					 ; then go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\.\delta\echo\..\..\foxtrot\..\Golf\.\Hotel\.\india\..\juliet\..\kilo\..\Li.....ma\.\..Mike\November\.\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\.\..\..\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_sameDir:									 ; This section will get rid of all \.\ occurrences.&lt;br /&gt;
		StrCpy $R0 $0							 ; First, copy the working copy absolute path into the relative path var.	We won&#039;t need the original anymore.&lt;br /&gt;
		StrCpy $0 $R0 1 0						 ; Again, get the first character&lt;br /&gt;
		StrLen $1 $R0							 ; Get the length&lt;br /&gt;
		StrCpy $2 0							 ; Start the counter at zero&lt;br /&gt;
&lt;br /&gt;
		_loop_sameDir:							; top of the loop&lt;br /&gt;
			IntOp $2 $2 + 1					 ; increase the counter&lt;br /&gt;
			IntCmp $2 $1 0 0 _dirup			 ; if the counter exceeds the relative path&#039;s length, move on&lt;br /&gt;
			StrCpy $3 $R0 3 $2					; get three characters from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCmp $3 &amp;quot;\.\&amp;quot; 0 +3				; if that&#039;s \.\ , then we&#039;ll have to...&lt;br /&gt;
				IntOp $2 $2 + 1				 	; increase the counter by 1 to stop going over the period.&lt;br /&gt;
				goto _loop_sameDir					; and go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; otherwise, get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; and add that character to the absolute path being built&lt;br /&gt;
			goto _loop_sameDir					; then go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\delta\echo\..\..\foxtrot\..\Golf\Hotel\india\..\juliet\..\kilo\..\Li.....ma\..Mike\November\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\..\..\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_dirup:									 ; This section will deal with \..\ occurrences, removing them -and- the parent folder&lt;br /&gt;
		StrCpy $R0 $0							 ; this&lt;br /&gt;
		StrCpy $0 $R0 1 0						 ; should&lt;br /&gt;
		StrLen $1 $R0							 ; look&lt;br /&gt;
		StrCpy $2 0							 ; familar&lt;br /&gt;
		Push &amp;quot;Rel2Abs&amp;quot;							; push a tag to the top of the stack.	We&#039;ll be doing some popping further down and want to make sure we don&#039;t exceed the stack/etc.&lt;br /&gt;
		_loop_dirup:							; more&lt;br /&gt;
			IntOp $2 $2 + 1					 ; familiar&lt;br /&gt;
			IntCmp $2 $1 0 0 _loop_cleanStack	 ; things&lt;br /&gt;
&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; add that character to the absolute path being built&lt;br /&gt;
			StrCmp $3 &amp;quot;\&amp;quot; 0 _loop_dirup		 ; if the character was a backslash, continue - otherwise, go back to the top of the stack&lt;br /&gt;
				StrCpy $3 $0 4 -4				 ; get -four- characters from the relative path, starting at the position of the counter&lt;br /&gt;
				StrCmp $3 &amp;quot;\..\&amp;quot; 0 _subDir		; if those four were \..\, continue to process this as going up a dir - otherwise we&#039;re just going down a dir&lt;br /&gt;
					Pop $0							; Get the top of the stack into our absolute path. Say the stack looked like &amp;quot;c:\test\&amp;quot;, &amp;quot;c:\test\hello\&amp;quot;, and we just encountered &amp;quot;c:\test\hello\,,\&amp;quot;, then this will be &amp;quot;c:\test\hello\&amp;quot;&lt;br /&gt;
					StrCmp $0 &amp;quot;Rel2Abs&amp;quot; _error		; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out.&lt;br /&gt;
					Pop $0							; Get the top of the stack in our absolute path.	Going with the previous example, this value will now be &amp;quot;c:\test\&amp;quot;, and as such as we just moved up a dir.&lt;br /&gt;
					StrCmp $0 &amp;quot;Rel2Abs&amp;quot; _error		; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out.&lt;br /&gt;
					Push $0						 ; Push this value back onto the stack because we&#039;ll need it on there.&lt;br /&gt;
					goto _loop_dirup				; And go back to the top of the loop&lt;br /&gt;
				_subDir:						; Otherwise we went down a dir&lt;br /&gt;
					Push $0						 ; So we&#039;ll just push this absolute path so far onto the stacak.&lt;br /&gt;
					goto _loop_dirup				; and go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\Golf\Hotel\Li.....ma\..Mike\November\Papa\Quebec..\Romeo\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_loop_cleanStack:							 ; At this point we already have our relative path - but there&#039;s a bunch of bits stuck on the stack&lt;br /&gt;
		Pop $1									; So we pop the stack&lt;br /&gt;
		StrCmp $1 &amp;quot;Rel2Abs&amp;quot; 0 _loop_cleanStack	; and as long as the value isn&#039;t our tag, we&#039;ll keep on popping&lt;br /&gt;
&lt;br /&gt;
	StrCpy $R0 $0							 	; Once it is, we&#039;re done entirely - copy the absolute path into $R0 for end-function stack purposes&lt;br /&gt;
	goto _end									 ; goto the end (skip over the error)&lt;br /&gt;
&lt;br /&gt;
	_error:									 ; This is where we went if the path being fed was mangled or we ran into our tag early otherwise&lt;br /&gt;
		StrCpy $R0 &amp;quot;-1&amp;quot;						 ; we&#039;ll just set the return value to -1&lt;br /&gt;
&lt;br /&gt;
	_end:										 ; end of the function, time to restore variables off the stack and push the result onto it.&lt;br /&gt;
	; Stack -&amp;gt;		; 3 2 1 0 R0&lt;br /&gt;
	Pop $3			; 2 1 0 R0&lt;br /&gt;
	Pop $2			; 1 0 R0&lt;br /&gt;
	Pop $1			; 0 R0&lt;br /&gt;
	Pop $0			; R0&lt;br /&gt;
	Exch $R0		; &amp;lt;absolute path&amp;gt;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Talk:Repair_path_names_with_..&amp;diff=11269</id>
		<title>Talk:Repair path names with ..</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Talk:Repair_path_names_with_..&amp;diff=11269"/>
		<updated>2006-10-01T21:04:25Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Kichik, GetFullPathname was failing in an instance I was using it in - couldn&#039;t for the life of me figure out why.  Found two causes and documented them here, also provided the Function I&#039;m now using. [[User:Animaether|Animaether]] 14:04, 1 October 2006 (PDT)&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11268</id>
		<title>Repair path names with ..</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11268"/>
		<updated>2006-10-01T21:03:05Z</updated>

		<summary type="html">&lt;p&gt;Animaether: forgot to login, fixed formatting in top&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;you have a path with relative path parts, such as&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
\\	; does nothing&lt;br /&gt;
\.\	; stay in same folder&lt;br /&gt;
\..\	; go up a folder&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you need the absolute path, then you can use the &amp;quot;GetFullPathName&amp;quot; command in NSIS to get the absolute path.	For example:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
	GetFullPathName $0 &amp;quot;c:\program files\myApp\somedir\subdir\..\somefile.ext&amp;quot;&lt;br /&gt;
	; $0 will now contain &amp;quot;c:\program files\myApp\somedir\somefile.ext&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that if you specify a filename, that file has to exist or the result is null.	It is therefore recommended that if you need the absolute path without necessarily having the file in existence, that you strip the filename from the path.&lt;br /&gt;
&lt;br /&gt;
Please also note that this command is limited to a 256-character string, even if the resulting absolute path is shorter than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If you have a longer string, you may try the below function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Abs2Rel&lt;br /&gt;
	; Stack -&amp;gt;		; &amp;lt;relative path&amp;gt;			; This and the stuff in the column below is just to keep track of the stack before and after the function so that it&#039;s clean at the end.&lt;br /&gt;
	Exch $R0		; R0						; $R0 now holds the relative path&lt;br /&gt;
	Push $0			; 0 R0						; $0 will hold the absolute path as it is being built&lt;br /&gt;
	Push $1			; 1 0 R0					; $1 will hold the length of the relative path&lt;br /&gt;
	Push $2			; 2 1 0 R0					; $2 will hold a counter for running along the path&lt;br /&gt;
	Push $3			; 3 2 1 0 R0				; $3 will hold a substring of the paths to test against&lt;br /&gt;
&lt;br /&gt;
	StrCpy $0 $R0 1 0						 	; Start by getting the first character of the relative path into the absolute path var&lt;br /&gt;
	StrLen $1 $R0								 ; Get the length of the relative path&lt;br /&gt;
	StrCpy $2 0								 ; And start the counter off at zero&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\\\Bravo\\Charlie..charles\\.\delta\\echo\\..\..\foxtrot\\..\Golf\\.\Hotel\\.\india\\..\\\\juliet\\..\kilo\\\..\Li.....ma\\.\..Mike\\\November\\.\oscar\\..\Papa\\\Quebec..\\\\\\\\Romeo\\sierra\\..\tang.o\\uniform\\victor\\..\whiskey\\..\\x-ray\\yankee\\..\..\.\..\..\Zu.lu\\file.ext&lt;br /&gt;
&lt;br /&gt;
	; double									; This section will get rid of all double backslashes.&lt;br /&gt;
		_loop_double:							 ; top of the loop&lt;br /&gt;
			IntOp $2 $2 + 1					 ; increase the counter&lt;br /&gt;
			IntCmp $2 $1 0 0 _sameDir			 ; if the counter exceeds the relative path&#039;s length, move on&lt;br /&gt;
			StrCpy $3 $R0 2 $2					; get two characters from the relative pah, starting at the position of the counter&lt;br /&gt;
			StrCmp $3 &amp;quot;\\&amp;quot; _loop_double		 ; if it&#039;s a double backslash, just go back to the top of the loop&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; otherwise, get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; and add that character to the absolute path being built&lt;br /&gt;
			goto _loop_double					 ; then go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\.\delta\echo\..\..\foxtrot\..\Golf\.\Hotel\.\india\..\juliet\..\kilo\..\Li.....ma\.\..Mike\November\.\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\.\..\..\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_sameDir:									 ; This section will get rid of all \.\ occurrences.&lt;br /&gt;
		StrCpy $R0 $0							 ; First, copy the working copy absolute path into the relative path var.	We won&#039;t need the original anymore.&lt;br /&gt;
		StrCpy $0 $R0 1 0						 ; Again, get the first character&lt;br /&gt;
		StrLen $1 $R0							 ; Get the length&lt;br /&gt;
		StrCpy $2 0							 ; Start the counter at zero&lt;br /&gt;
&lt;br /&gt;
		_loop_sameDir:							; top of the loop&lt;br /&gt;
			IntOp $2 $2 + 1					 ; increase the counter&lt;br /&gt;
			IntCmp $2 $1 0 0 _dirup			 ; if the counter exceeds the relative path&#039;s length, move on&lt;br /&gt;
			StrCpy $3 $R0 3 $2					; get three characters from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCmp $3 &amp;quot;\.\&amp;quot; 0 +3				; if that&#039;s \.\ , then we&#039;ll have to...&lt;br /&gt;
				IntOp $2 $2 + 1				 	; increase the counter by 1 to stop going over the period.&lt;br /&gt;
				goto _loop_sameDir					; and go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; otherwise, get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; and add that character to the absolute path being built&lt;br /&gt;
			goto _loop_sameDir					; then go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\delta\echo\..\..\foxtrot\..\Golf\Hotel\india\..\juliet\..\kilo\..\Li.....ma\..Mike\November\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\..\..\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_dirup:									 ; This section will deal with \..\ occurrences, removing them -and- the parent folder&lt;br /&gt;
		StrCpy $R0 $0							 ; this&lt;br /&gt;
		StrCpy $0 $R0 1 0						 ; should&lt;br /&gt;
		StrLen $1 $R0							 ; look&lt;br /&gt;
		StrCpy $2 0							 ; familar&lt;br /&gt;
		Push &amp;quot;Rel2Abs&amp;quot;							; push a tag to the top of the stack.	We&#039;ll be doing some popping further down and want to make sure we don&#039;t exceed the stack/etc.&lt;br /&gt;
		_loop_dirup:							; more&lt;br /&gt;
			IntOp $2 $2 + 1					 ; familiar&lt;br /&gt;
			IntCmp $2 $1 0 0 _loop_cleanStack	 ; things&lt;br /&gt;
&lt;br /&gt;
			StrCpy $3 $R0 1 $2					; get a single character from the relative path, starting at the position of the counter&lt;br /&gt;
			StrCpy $0 &amp;quot;$0$3&amp;quot;					; add that character to the absolute path being built&lt;br /&gt;
			StrCmp $3 &amp;quot;\&amp;quot; 0 _loop_dirup		 ; if the character was a backslash, continue - otherwise, go back to the top of the stack&lt;br /&gt;
				StrCpy $3 $0 4 -4				 ; get -four- characters from the relative path, starting at the position of the counter&lt;br /&gt;
				StrCmp $3 &amp;quot;\..\&amp;quot; 0 _subDir		; if those four were \..\, continue to process this as going up a dir - otherwise we&#039;re just going down a dir&lt;br /&gt;
					Pop $0							; Get the top of the stack into our absolute path. Say the stack looked like &amp;quot;c:\test\&amp;quot;, &amp;quot;c:\test\hello\&amp;quot;, and we just encountered &amp;quot;c:\test\hello\,,\&amp;quot;, then this will be &amp;quot;c:\test\hello\&amp;quot;&lt;br /&gt;
					StrCmp $0 &amp;quot;Rel2Abs&amp;quot; _error		; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out.&lt;br /&gt;
					Pop $0							; Get the top of the stack in our absolute path.	Going with the previous example, this value will now be &amp;quot;c:\test\&amp;quot;, and as such as we just moved up a dir.&lt;br /&gt;
					StrCmp $0 &amp;quot;Rel2Abs&amp;quot; _error		; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out.&lt;br /&gt;
					Push $0						 ; Push this value back onto the stack because we&#039;ll need it on there.&lt;br /&gt;
					goto _loop_dirup				; And go back to the top of the loop&lt;br /&gt;
				_subDir:						; Otherwise we went down a dir&lt;br /&gt;
					Push $0						 ; So we&#039;ll just push this absolute path so far onto the stacak.&lt;br /&gt;
					goto _loop_dirup				; and go back to the top of the loop&lt;br /&gt;
&lt;br /&gt;
	; example path at this point&lt;br /&gt;
	; c:\Alpha\Bravo\Charlie..charles\Golf\Hotel\Li.....ma\..Mike\November\Papa\Quebec..\Romeo\Zu.lu\file.ext&lt;br /&gt;
&lt;br /&gt;
	_loop_cleanStack:							 ; At this point we already have our relative path - but there&#039;s a bunch of bits stuck on the stack&lt;br /&gt;
		Pop $1									; So we pop the stack&lt;br /&gt;
		StrCmp $1 &amp;quot;Rel2Abs&amp;quot; 0 _loop_cleanStack	; and as long as the value isn&#039;t our tag, we&#039;ll keep on popping&lt;br /&gt;
&lt;br /&gt;
	StrCpy $R0 $0							 	; Once it is, we&#039;re done entirely - copy the absolute path into $R0 for end-function stack purposes&lt;br /&gt;
	goto _end									 ; goto the end (skip over the error)&lt;br /&gt;
&lt;br /&gt;
	_error:									 ; This is where we went if the path being fed was mangled or we ran into our tag early otherwise&lt;br /&gt;
		StrCpy $R0 &amp;quot;-1&amp;quot;						 ; we&#039;ll just set the return value to -1&lt;br /&gt;
&lt;br /&gt;
	_end:										 ; end of the function, time to restore variables off the stack and push the result onto it.&lt;br /&gt;
	; Stack -&amp;gt;		; 3 2 1 0 R0&lt;br /&gt;
	Pop $3			; 2 1 0 R0&lt;br /&gt;
	Pop $2			; 1 0 R0&lt;br /&gt;
	Pop $1			; 0 R0&lt;br /&gt;
	Pop $0			; R0&lt;br /&gt;
	Exch $R0		; &amp;lt;absolute path&amp;gt;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11239</id>
		<title>Repair path names with ..</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11239"/>
		<updated>2006-09-28T22:22:13Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seeing as how this page didn&#039;t exist yet, but the topic did, hopefully somebody else can clean it up...&lt;br /&gt;
&lt;br /&gt;
Below is a very naive piece of code, which uses LogicLib a bit to keep things sane.  DON&#039;T USE THIS CODE :D&lt;br /&gt;
(not until somebody cleans it up anyway)&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Bladeebla&amp;quot;&lt;br /&gt;
    StrCpy $R0 &amp;quot;C:\folder\subfolder\.\anotherfolder\..\someotherfolder\somefile.ext&amp;quot;&lt;br /&gt;
    StrCpy $4 $R0 1 0&lt;br /&gt;
    StrLen $1 $R0&lt;br /&gt;
    StrCpy $2 0&lt;br /&gt;
    Push &amp;quot;RelAbs&amp;quot;&lt;br /&gt;
	_loop:&lt;br /&gt;
	    IntOp $2 $2 + 1&lt;br /&gt;
	    ${If} $2 &amp;gt; $1&lt;br /&gt;
	        goto _end&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		StrCpy $0 $R0 3 $2&lt;br /&gt;
		${If} $0 == &amp;quot;..\&amp;quot;&lt;br /&gt;
		    Pop $4&lt;br /&gt;
		    Pop $4&lt;br /&gt;
		    IntOp $2 $2 + 2&lt;br /&gt;
		${ElseIf} $0 == &amp;quot;\.\&amp;quot;&lt;br /&gt;
			IntOp $2 $2 + 1&lt;br /&gt;
		${Else}&lt;br /&gt;
		    StrCpy $3 $R0 1 $2&lt;br /&gt;
		    StrCpy $4 &amp;quot;$4$3&amp;quot;&lt;br /&gt;
		    ${If} $3 == &amp;quot;\&amp;quot;&lt;br /&gt;
				Push $4&lt;br /&gt;
			${EndIf}&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		goto _loop&lt;br /&gt;
	_end:&lt;br /&gt;
&lt;br /&gt;
	_loop2:&lt;br /&gt;
		Pop $0&lt;br /&gt;
		${If} $0 == &amp;quot;RelAbs&amp;quot;&lt;br /&gt;
		    goto _end2&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		goto _loop2&lt;br /&gt;
	_end2:&lt;br /&gt;
&lt;br /&gt;
	MessageBox MB_OK &amp;quot;$R0$\r$\n$4&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display a messagebox with:&lt;br /&gt;
C:\folder\subfolder\.\anotherfolder\..\someotherfolder\somefile.ext&lt;br /&gt;
C:\folder\subfolder\someotherfolder\somefile.ext&lt;br /&gt;
&lt;br /&gt;
Note that instead of lots of string manipulations, this code is either lazy or smart, depending on how you look at it.  Everytime a &amp;quot;\.\&amp;quot; is encountered, it ignores it.  Everytime a &amp;quot;..\&amp;quot; is encountered, it also ignores it, and Pops the currently collected path off the stack, twice, to get back to what the collected path was before the parent folder was added.&lt;br /&gt;
If a &amp;quot;\&amp;quot; is encountered not as part of the above two, the currently collected path is pushed to the stack, effectively pushing the path with each folder encountered to the stack.&lt;br /&gt;
Then at the end the stack is cleaned up by popping off until &amp;quot;RelAbs&amp;quot; is the value popped.&lt;br /&gt;
&lt;br /&gt;
Please note that this means you can&#039;t feed it paths like &amp;quot;..\whatever&amp;quot; because it doesn&#039;t know where to start in.  It also doesn&#039;t deal with forward slashes &amp;quot;/&amp;quot;.  It doesn&#039;t bother cleaning up &amp;quot;\\&amp;quot;, it fails when you&#039;ve got &amp;quot;A\B\C\D\..\..\&amp;quot; (returning &amp;quot;A\&amp;quot;) etc.  So the above code really is quite naive, should be cleaned up, etc. but may be a good starting point as it doesn&#039;t do insane things with strings using a ton of variables.&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11238</id>
		<title>Repair path names with ..</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Repair_path_names_with_..&amp;diff=11238"/>
		<updated>2006-09-28T22:19:22Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seeing as how this page didn&#039;t exist yet, but the topic did, hopefully somebody else can clean it up...&lt;br /&gt;
&lt;br /&gt;
Below is a very naive piece of code, which uses LogicLib a bit to keep things sane.&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Bladeebla&amp;quot;&lt;br /&gt;
    StrCpy $R0 &amp;quot;C:\folder\subfolder\.\anotherfolder\..\someotherfolder\somefile.ext&amp;quot;&lt;br /&gt;
    StrCpy $4 $R0 1 0&lt;br /&gt;
    StrLen $1 $R0&lt;br /&gt;
    StrCpy $2 0&lt;br /&gt;
    Push &amp;quot;RelAbs&amp;quot;&lt;br /&gt;
	_loop:&lt;br /&gt;
	    IntOp $2 $2 + 1&lt;br /&gt;
	    ${If} $2 &amp;gt; $1&lt;br /&gt;
	        goto _end&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		StrCpy $0 $R0 3 $2&lt;br /&gt;
		${If} $0 == &amp;quot;..\&amp;quot;&lt;br /&gt;
		    Pop $4&lt;br /&gt;
		    Pop $4&lt;br /&gt;
		    IntOp $2 $2 + 2&lt;br /&gt;
		${ElseIf} $0 == &amp;quot;\.\&amp;quot;&lt;br /&gt;
			IntOp $2 $2 + 1&lt;br /&gt;
		${Else}&lt;br /&gt;
		    StrCpy $3 $R0 1 $2&lt;br /&gt;
		    StrCpy $4 &amp;quot;$4$3&amp;quot;&lt;br /&gt;
		    ${If} $3 == &amp;quot;\&amp;quot;&lt;br /&gt;
				Push $4&lt;br /&gt;
			${EndIf}&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		goto _loop&lt;br /&gt;
	_end:&lt;br /&gt;
&lt;br /&gt;
	_loop2:&lt;br /&gt;
		Pop $0&lt;br /&gt;
		${If} $0 == &amp;quot;RelAbs&amp;quot;&lt;br /&gt;
		    goto _end2&lt;br /&gt;
		${EndIf}&lt;br /&gt;
		goto _loop2&lt;br /&gt;
	_end2:&lt;br /&gt;
&lt;br /&gt;
	MessageBox MB_OK &amp;quot;$R0$\r$\n$4&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display a messagebox with:&lt;br /&gt;
C:\folder\subfolder\.\anotherfolder\..\someotherfolder\somefile.ext&lt;br /&gt;
C:\folder\subfolder\someotherfolder\somefile.ext&lt;br /&gt;
&lt;br /&gt;
Note that instead of lots of string manipulations, this code is either lazy or smart, depending on how you look at it.  Everytime a &amp;quot;\.\&amp;quot; is encountered, it ignores it.  Everytime a &amp;quot;..\&amp;quot; is encountered, it also ignores it, and Pops the currently collected path off the stack, twice, to get back to what the collected path was before the parent folder was added.&lt;br /&gt;
If a &amp;quot;\&amp;quot; is encountered not as part of the above two, the currently collected path is pushed to the stack, effectively pushing the path with each folder encountered to the stack.&lt;br /&gt;
Then at the end the stack is cleaned up by popping off until &amp;quot;RelAbs&amp;quot; is the value popped.&lt;br /&gt;
&lt;br /&gt;
Please note that this means you can&#039;t feed it paths like &amp;quot;..\whatever&amp;quot; because it doesn&#039;t know where to start in.  It also doesn&#039;t deal with forward slashes &amp;quot;/&amp;quot;.  It doesn&#039;t bother cleaning up &amp;quot;\\&amp;quot;, etc.  So the above code really is quite naive, should be cleaned up, etc. but may be a good starting point as it doesn&#039;t do insane things with strings using a ton of variables.&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11178</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11178"/>
		<updated>2006-09-16T16:01:53Z</updated>

		<summary type="html">&lt;p&gt;Animaether: PSx, added Conclusion section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 1.1.5, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing functions between Installer and Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
Let&#039;s start again with what the NSIS Help file says on them:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Functions are similar to Sections in that they contain zero or more instructions.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s try a different definition.  Functions are like macros, except that the code does -not- actually get inserted or copy/pasted, if you will, when compiling.  The compiled code only exists just once in your final installer.&lt;br /&gt;
&lt;br /&gt;
A Function use equivalent to the Macro example 1.1.1 would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You also cannot pass parameters/arguments to Functions as easily as you can with Macros.  I.e. the following is NOT a valid code equivalent of Example 1.1.3:&lt;br /&gt;
&lt;br /&gt;
Example: 1.2.2&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You could, of course, try to take a page out of the earlier installer/uninstaller book and wrap the function in a macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
But this is -also- invalid code, as the code would end up having a Function definition within a section, which is not allowed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
( even if Function definitions were allowed within Sections, keep in mind that you would have more than a single Function named &amp;quot;Hello&amp;quot; - which is also not allowed )&lt;br /&gt;
&lt;br /&gt;
Instead, passing parameters/arguments to Functions is typically done through variables...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
var myVar&lt;br /&gt;
&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello $myVar&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  StrCpy $myVar &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...or, more commonly, the stack (to save memory used by variables)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  Exch $0&lt;br /&gt;
  DetailPrint &amp;quot;Hello $0&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which ends up acting as (but please note that the code is not actually inserted as such!):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.7&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  ; At this point, the stack looks like the following (top is left, bottom is right)&lt;br /&gt;
  ; :: &amp;quot;World&amp;quot; -rest of the stack, if anything-&lt;br /&gt;
  Exch $0&lt;br /&gt;
  ; At this point the old value of $0 is now at the top of the stack, while &amp;quot;World&amp;quot; is copied into variable $0&lt;br /&gt;
  ; :: old$0 -rest of the stack, if anything-&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
  ; At this point the old value of $0 is restored, and the stack just looks like the following:&lt;br /&gt;
  ; :: -rest of the stack, if anything-&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Functions can either clear the stack relevant to the function, as in the above, or they can leave an item on the stack for use after the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.8&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function isDir&lt;br /&gt;
  Exch $0&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; _dir _notdir&lt;br /&gt;
  _dir:&lt;br /&gt;
    StrCpy $0 &amp;quot;true&amp;quot;&lt;br /&gt;
    return&lt;br /&gt;
  _notdir:&lt;br /&gt;
    StrCpy $0 &amp;quot;false&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;some path on your drive&amp;quot;&lt;br /&gt;
  Call isDir&lt;br /&gt;
  Pop $0&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where in the above code, after the call to &amp;quot;isDir&amp;quot;, $0 contains &amp;quot;true&amp;quot; if the path was a directory, and &amp;quot;false&amp;quot; if not.&lt;br /&gt;
&lt;br /&gt;
= Hybrid =&lt;br /&gt;
Mainly because of the fact that you can&#039;t easily pass parameters to Functions, many users adopt a hybrid approach employing both macros -and- functions, and a little bit of a define. (a define just allows you to say that e.g. &amp;quot;NSIS&amp;quot; means &amp;quot;Nullsoft Scriptable Install System&amp;quot; without having to write out as much).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!define writeFile &amp;quot;!insertmacro writeFile&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!macro writeFile File String&lt;br /&gt;
  Push ${File}&lt;br /&gt;
  Push ${String}&lt;br /&gt;
  Call writeFile&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Function writeFile&lt;br /&gt;
                              ; Stack: &amp;lt;file&amp;gt; &amp;lt;string&amp;gt;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  Exch $0                     ; Stack: $0 &amp;lt;string&amp;gt;&lt;br /&gt;
  Exch                        ; Stack: &amp;lt;string&amp;gt; $0&lt;br /&gt;
  Exch $1                     ; Stack: $1 $0&lt;br /&gt;
  Push $2                     ; Stack: $2 $1 $0&lt;br /&gt;
  ; $0 = file&lt;br /&gt;
  ; $1 = string&lt;br /&gt;
  FileOpen $2 &amp;quot;$0&amp;quot; &amp;quot;a&amp;quot;&lt;br /&gt;
  FileSeek $2 0 END&lt;br /&gt;
  FileWrite $2 $1&lt;br /&gt;
  FileClose $2&lt;br /&gt;
  Pop $2                      ; Stack: $1 $0&lt;br /&gt;
  Pop $1                      ; Stack: $0&lt;br /&gt;
  Pop $0                      ; Stack: -empty-&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  ${writeFile} &amp;quot;$TEMP\a_log_file.txt&amp;quot; &amp;quot;A log entry&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this allows you to combine the best of both worlds by reducing code redundancy both in your installation script -and- in the compiled installer and allowing you to &#039;pass&#039; parameters/arguments to a function by using a macro as an intermediate.  And in the end, your code looks even cleaner.&lt;br /&gt;
&lt;br /&gt;
= Caveats - or Pros/Cons =&lt;br /&gt;
Now you might think that macros and functions rather look the same - when should you use which?  That all depends on your needs / desires for the most part.  However, there are certainly pros/cons to both.&lt;br /&gt;
&lt;br /&gt;
As pointed in the definitions already, there are some immediately obvious advantages over each other:&lt;br /&gt;
&#039;&#039;&#039;Macros&#039;&#039;&#039;&lt;br /&gt;
* + easier follow (the code simply gets copy/pasted)&lt;br /&gt;
* + can easily pass parameters / arguments&lt;br /&gt;
* - code gets duplicated in the compiled result&lt;br /&gt;
Note that the code duplication is marginal (the files you are installing are typically much larger than the base installer code), and with compression it becomes even less of an issue.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Functions&#039;&#039;&#039;&lt;br /&gt;
* + code does not get duplicated in the compiled result&lt;br /&gt;
* - cannot easily pass parameters / arguments&lt;br /&gt;
* - a bit less easy to follow&lt;br /&gt;
( The Hybrid approach pretty much eliminates the parameter / argument passing con of Functions )&lt;br /&gt;
&lt;br /&gt;
However, there are also some less obvious Pros/Cons.&lt;br /&gt;
For example, Macros are faster to execute than Functions, as there are no opcodes for calling / returning required in the installer.  However, this is also marginal and even on older hardware negligable.&lt;br /&gt;
&lt;br /&gt;
More intricate Pros/Cons are described in the next sections.&lt;br /&gt;
&lt;br /&gt;
== Macros ==&lt;br /&gt;
=== labels ===&lt;br /&gt;
As a Macro literally gets inserted, or copy/pasted, into your code when compiling you may find yourself running into an issue of duplicating labels;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro LoopThreeTimes&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end&lt;br /&gt;
    goto loop&lt;br /&gt;
  end:&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  !insertmacro LoopThreeTimes&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above could be read as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end&lt;br /&gt;
    goto loop&lt;br /&gt;
  end:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the problem should be clear - there are now two labels named &amp;quot;end&amp;quot;, which is not allowed.  You could rename your labels in your macros to be supposedly unique - in example 3.1.1 you could call them &amp;quot;LoopThreeTimes_loop&amp;quot; and &amp;quot;LoopThreeTimes_end&amp;quot;.  But what if you use the macro more than once in the same section?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 LoopThreeTimes_end&lt;br /&gt;
    goto loop&lt;br /&gt;
  LoopThreeTimes_end:&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 LoopThreeTimes_end&lt;br /&gt;
    goto loop&lt;br /&gt;
  LoopThreeTimes_end:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You then again get a duplicate label name.  A common way to prevent this is to actually make the label names unique for each time the macro is inserted.  You can do this by adding a line number that is first defined to the label;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro LoopThreeTimes&lt;br /&gt;
  !define ID ${__LINE__}&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop_${ID}:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end_${ID}&lt;br /&gt;
    goto loop_${ID}&lt;br /&gt;
  end_${ID}:&lt;br /&gt;
  !undefine ID&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  !insertmacro LoopThreeTimes&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which would then end up as (presuming the line number the !define was on was 55):&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop_55:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end_55&lt;br /&gt;
    goto loop_55&lt;br /&gt;
  end_55:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
You can read more about this in: [[Tutorial: Using labels in macro&#039;s]]&lt;br /&gt;
&lt;br /&gt;
Although this is a reasonably minor Con, given the easy workaround, it should be clear that Functions do not suffer from any issues with labels at all.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
=== File command ===&lt;br /&gt;
When you use a Macro, the code gets inserted or copy/pasted if you will into the area of use.  This becomes especially important when you use the File command.  Consider the following two examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2.1 - Macro&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro InstallFilesTo Path Filespec&lt;br /&gt;
  SetOutPath &amp;quot;${Path}&amp;quot;&lt;br /&gt;
  File &amp;quot;${Filespec}&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro InstallFilesTo &amp;quot;$INSTDIR&amp;quot; &amp;quot;data\*.*&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2.2 - Function&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function InstallFilesTo&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  SetOutPath &amp;quot;$1&amp;quot;&lt;br /&gt;
  File &amp;quot;$0&amp;quot;&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;data\*.*&amp;quot;&lt;br /&gt;
  Push &amp;quot;$INSTDIR&amp;quot;&lt;br /&gt;
  Call InstallFilesTo&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two perform exactly the same job, namely installing all files in the installer source&#039;s &amp;quot;data&amp;quot; sub-folder to the installation folder.&lt;br /&gt;
&lt;br /&gt;
The big difference is that with the Macro variant, the size of the files can directly be added to the Section.  Which means that your installer will correct report the amount of free space required on the drive, and the &amp;quot;SectionGetSize&amp;quot; command will work correctly.&lt;br /&gt;
&lt;br /&gt;
With the Function variant, the compiler doesn&#039;t know to figure this out, and the required space is not calculated correctly, nor does &amp;quot;SectionGetSize&amp;quot; work correctly.&lt;br /&gt;
&lt;br /&gt;
A workaround for this would be to use &amp;quot;SectionSetSize&amp;quot; where appropriate, but it does mean that you would need to know the size of the files -before- you use &amp;quot;SectionSetSize&amp;quot;, which would have to be handled by a separate NSIS script, or some cheating by extracting the file before actually installing, getting the file size, and then moving it or deleting it when installing/not installing.  In other words, there is no easy / proper workaround for it.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Although Macros and Functions are very similar beasts, each has its strengths and weaknesses, and certainly things to look out for.  In general, however, you can follow these guidelines:&lt;br /&gt;
* if you&#039;re not using the code more than once and it&#039;s just a single line or a few lines, don&#039;t bother using either a Macro or a Function.&lt;br /&gt;
* if you&#039;re not using the code more than once, but it&#039;s a good number of lines and is really a procedure that you want to easily be able to maintain or is otherwise just clogging up the view of the surrounding code, consider putting it into a Macro.&lt;br /&gt;
* if you&#039;re using non-trivial code more than once, always consider putting it into a Macro or Function&lt;br /&gt;
* if it&#039;s a lot of code (many, many lines), considering using a Function rather than a Macro&lt;br /&gt;
* if you need to use the File command, consider using a Macro rather than a Function - or, if possible, re-think the process to keep the File command outside of the Function.&lt;br /&gt;
* if you don&#039;t want to fuss around with labels, consider using a Function rather than a Macro - or consider using the work-around which is really quite painless.&lt;br /&gt;
* consider setting up a !define for your Macros to make the code cleaner&lt;br /&gt;
* consider using the Hybrid approach whenever you decided to go with a Function but need to pass parameters/arguments&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11176</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11176"/>
		<updated>2006-09-16T15:46:52Z</updated>

		<summary type="html">&lt;p&gt;Animaether: Finished for now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 1.1.5, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
Let&#039;s start again with what the NSIS Help file says on them:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Functions are similar to Sections in that they contain zero or more instructions.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s try a different definition.  Functions are like macros, except that the code does -not- actually get inserted or copy/pasted, if you will, when compiling.  The compiled code only exists just once in your final installer.&lt;br /&gt;
&lt;br /&gt;
A Function use equivalent to the Macro example 1.1.1 would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You also cannot pass parameters/arguments to Functions as easily as you can with Macros.  I.e. the following is NOT a valid code equivalent of Example 1.1.3:&lt;br /&gt;
&lt;br /&gt;
Example: 1.2.2&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You could, of course, try to take a page out of the earlier installer/uninstaller book and wrap the function in a macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
But this is -also- invalid code, as the code would end up having a Function definition within a section, which is not allowed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
( even if Function definitions were allowed within Sections, keep in mind that you would have more than a single Function named &amp;quot;Hello&amp;quot; - which is also not allowed )&lt;br /&gt;
&lt;br /&gt;
Instead, passing parameters/arguments to Functions is typically done through variables...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
var myVar&lt;br /&gt;
&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello $myVar&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  StrCpy $myVar &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...or, more commonly, the stack (to save memory used by variables)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  Exch $0&lt;br /&gt;
  DetailPrint &amp;quot;Hello $0&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which ends up acting as (but please note that the code is not actually inserted as such!):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.7&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  ; At this point, the stack looks like the following (top is left, bottom is right)&lt;br /&gt;
  ; :: &amp;quot;World&amp;quot; -rest of the stack, if anything-&lt;br /&gt;
  Exch $0&lt;br /&gt;
  ; At this point the old value of $0 is now at the top of the stack, while &amp;quot;World&amp;quot; is copied into variable $0&lt;br /&gt;
  ; :: old$0 -rest of the stack, if anything-&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
  ; At this point the old value of $0 is restored, and the stack just looks like the following:&lt;br /&gt;
  ; :: -rest of the stack, if anything-&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Functions can either clear the stack relevant to the function, as in the above, or they can leave an item on the stack for use after the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.8&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function isDir&lt;br /&gt;
  Exch $0&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; _dir _notdir&lt;br /&gt;
  _dir:&lt;br /&gt;
    StrCpy $0 &amp;quot;true&amp;quot;&lt;br /&gt;
    return&lt;br /&gt;
  _notdir:&lt;br /&gt;
    StrCpy $0 &amp;quot;false&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;some path on your drive&amp;quot;&lt;br /&gt;
  Call isDir&lt;br /&gt;
  Pop $0&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where in the above code, after the call to &amp;quot;isDir&amp;quot;, $0 contains &amp;quot;true&amp;quot; if the path was a directory, and &amp;quot;false&amp;quot; if not.&lt;br /&gt;
&lt;br /&gt;
= Hybrid =&lt;br /&gt;
Mainly because of the fact that you can&#039;t easily pass parameters to Functions, many users adopt a hybrid approach employing both macros -and- functions, and a little bit of a define. (a define just allows you to say that e.g. &amp;quot;NSIS&amp;quot; means &amp;quot;Nullsoft Scriptable Install System&amp;quot; without having to write out as much).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!define writeFile &amp;quot;!insertmacro writeFile&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!macro writeFile File String&lt;br /&gt;
  Push ${File}&lt;br /&gt;
  Push ${String}&lt;br /&gt;
  Call writeFile&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Function WriteFile&lt;br /&gt;
                              ; Stack: &amp;lt;file&amp;gt; &amp;lt;string&amp;gt;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  Exch $0                     ; Stack: $0 &amp;lt;string&amp;gt;&lt;br /&gt;
  Exch                        ; Stack: &amp;lt;string&amp;gt; $0&lt;br /&gt;
  Exch $1                     ; Stack: $1 $0&lt;br /&gt;
  Push $2                     ; Stack: $2 $1 $0&lt;br /&gt;
  ; $0 = file&lt;br /&gt;
  ; $1 = string&lt;br /&gt;
  FileOpen $2 &amp;quot;$0&amp;quot; &amp;quot;a&amp;quot;&lt;br /&gt;
  FileSeek $2 0 END&lt;br /&gt;
  FileWrite $2 $1&lt;br /&gt;
  FileClose $2&lt;br /&gt;
  Pop $2                      ; Stack: $1 $0&lt;br /&gt;
  Pop $1                      ; Stack: $0&lt;br /&gt;
  Pop $0                      ; Stack: -empty-&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  ${writeFile} &amp;quot;$TEMP\alogfile.txt&amp;quot; &amp;quot;A log entry&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this allows you to combine the best of both worlds by reducing code redundancy both in your installation script -and- in the compiled installer and allowing you to &#039;pass&#039; parameters/arguments to a function by using a macro as an intermediate.  And in the end, your code looks even cleaner.&lt;br /&gt;
&lt;br /&gt;
= Caveats - or Pros/Cons =&lt;br /&gt;
Now you might think that macros and functions rather look the same - when should you use which?  That all depends on your needs / desires for the most part.  However, there are certainly pros/cons to both.&lt;br /&gt;
&lt;br /&gt;
As pointed in the definitions already, there are some immediately obvious advantages over eachother:&lt;br /&gt;
&#039;&#039;&#039;Macros&#039;&#039;&#039;&lt;br /&gt;
* + easier follow (the code simply gets copy/pasted)&lt;br /&gt;
* + can easily pass parameters / arguments&lt;br /&gt;
* - code gets duplicated in the compiled result&lt;br /&gt;
Note that the code duplication is marginal (the files you are installing are typically much larger than the base installer code), and with compression even moreso.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Functions&#039;&#039;&#039;&lt;br /&gt;
* + code does not get duplicated in the compiled result&lt;br /&gt;
* - cannot easily pass parameters / arguments&lt;br /&gt;
* - a bit less easy to follow&lt;br /&gt;
( The Hybrid approach pretty much eliminates the parameter / argument passing con of Functions )&lt;br /&gt;
&lt;br /&gt;
However, there are also some less obvious Pros/Cons.&lt;br /&gt;
For example, Macros are faster to execute than Functions, as there are no opcodes for calling / returning required in the installer.  However, this is also marginal and even on older hardware neglectable.&lt;br /&gt;
&lt;br /&gt;
More intricate Pros/Cons are described in the next sections.&lt;br /&gt;
&lt;br /&gt;
== Macros ==&lt;br /&gt;
=== labels ===&lt;br /&gt;
As a Macro literally gets inserted, or copy/pasted, into your code when compiling you may find yourself running into an issue of duplicating labels;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro LoopThreeTimes&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end&lt;br /&gt;
    goto loop&lt;br /&gt;
  end:&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  !insertmacro LoopThreeTimes&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above could be read as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end&lt;br /&gt;
    goto loop&lt;br /&gt;
  end:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the problem should be clear - there are now two labels named &amp;quot;end&amp;quot;, which is not allowed.  You could rename your labels in your macros to be supposedly unique - in example 3.1.1 you could call them &amp;quot;LoopThreeTimes_loop&amp;quot; and &amp;quot;LoopThreeTimes_end&amp;quot;.  But what if you use the macro more than once in the same section?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 LoopThreeTimes_end&lt;br /&gt;
    goto loop&lt;br /&gt;
  LoopThreeTimes_end:&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 LoopThreeTimes_end&lt;br /&gt;
    goto loop&lt;br /&gt;
  LoopThreeTimes_end:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You then again get a duplicate label name.  A common way to prevent this is to actually make the label names unique for each time the macro is inserted.  You can do this by adding a line number that is first defined to the label;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro LoopThreeTimes&lt;br /&gt;
  !define ID ${__LINE__}&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop_${ID}:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end_${ID}&lt;br /&gt;
    goto loop_${ID}&lt;br /&gt;
  end_${ID}:&lt;br /&gt;
  !undefine ID&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  !insertmacro LoopThreeTimes&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which would then end up as (presuming the line number the !define was on was 55):&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  IfFileExists &amp;quot;$TEMP\install.log&amp;quot; end&lt;br /&gt;
  StrCpy $0 0&lt;br /&gt;
  loop_55:&lt;br /&gt;
    IntOp $0 $0 + 1&lt;br /&gt;
    IntCmp $0 3 end_55&lt;br /&gt;
    goto loop_55&lt;br /&gt;
  end_55:&lt;br /&gt;
  end:&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
You can read more about this in: [[Tutorial: Using labels in macro&#039;s]]&lt;br /&gt;
&lt;br /&gt;
Although this is a reasonably minor Con, given the easy workaround, it should be clear that Functions do not suffer from any issues with labels at all.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
=== File command ===&lt;br /&gt;
When you use a Macro, the code gets inserted or copy/pasted if you will into the area of use.  This becomes especially important when you use the File command.  Consider the following two examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2.1 - Macro&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro InstallFilesTo Path Filespec&lt;br /&gt;
  SetOutPath &amp;quot;${Path}&amp;quot;&lt;br /&gt;
  File &amp;quot;${Filespec}&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro InstallFilesTo &amp;quot;$INSTDIR&amp;quot; &amp;quot;data\*.*&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2.2 - Function&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function InstallFilesTo&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  SetOutPath &amp;quot;$1&amp;quot;&lt;br /&gt;
  File &amp;quot;$0&amp;quot;&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;data\*.*&amp;quot;&lt;br /&gt;
  Push &amp;quot;$INSTDIR&amp;quot;&lt;br /&gt;
  Call InstallFilesTo&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two perform exactly the same job, namely installing all files in the installer source&#039;s &amp;quot;data&amp;quot; subfolder to the installation folder.&lt;br /&gt;
&lt;br /&gt;
The big difference is that with the Macro variant, the size of the files can directly be added to the Section.  Which means that your installer will correct report the amount of free space required on the drive, and the &amp;quot;SectionGetSize&amp;quot; command will work correctly.&lt;br /&gt;
&lt;br /&gt;
With the Function variant, the compiler doesn&#039;t know to figure this out, and the required space is not calculated correctly, nor does &amp;quot;SectionGetSize&amp;quot; work correctly.&lt;br /&gt;
&lt;br /&gt;
A workaround for this would be to use &amp;quot;SectionSetSize&amp;quot; where appropriate, but it does mean that you would need to know the size of the files -before- you use &amp;quot;SectionSetSize&amp;quot;, which would have to be handled by a separate NSIS script, or some cheating by extracting the file before actually installing, getting the file size, and then moving it or deleting it when installing/not installing.  In other words, there is no easy / proper workaround for it.&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11175</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11175"/>
		<updated>2006-09-16T14:19:01Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 1.1.5, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
Let&#039;s start again with what the NSIS Help file says on them:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Functions are similar to Sections in that they contain zero or more instructions.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s try a different definition.  Functions are like macros, except that the code does -not- actually get inserted or copy/pasted, if you will, when compiling.  The compiled code only exists just once in your final installer.&lt;br /&gt;
&lt;br /&gt;
A Function use equivalent to the Macro example 1.1.1 would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you cannot pass parameters/arguments to Functions as easily as you can with Macros.  I.e. the following is NOT a valid code equivalent of Example 1.1.3:&lt;br /&gt;
&lt;br /&gt;
Example: 1.2.2&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  Call Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You could, of course, try to take a page out of the earlier installer/uninstaller book and wrap the function in a macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
But this is -also- invalid code, as the code would end up having a Function definition within a section, which is not allowed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Function Hello&lt;br /&gt;
    DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
( even if Function definitions were allowed within Sections, keep in mind that you would have more than a single Function named &amp;quot;Hello&amp;quot; - which is also not allowed )&lt;br /&gt;
&lt;br /&gt;
Instead, passing parameters/arguments to Functions is typically done through variables...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
var myVar&lt;br /&gt;
&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello $myVar&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  StrCpy $myVar &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...or, more commonly, the stack (to save memory used by variables)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  Exch $0&lt;br /&gt;
  DetailPrint &amp;quot;Hello $0&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which ends up acting as (but please note that the code is not actually inserted as such!):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.7&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;World&amp;quot;&lt;br /&gt;
  ; At this point, the stack looks like the following (top is left, bottom is right)&lt;br /&gt;
  ; :: &amp;quot;World&amp;quot; -rest of the stack, if anything-&lt;br /&gt;
  Exch $0&lt;br /&gt;
  ; At this point the old value of $0 is now at the top of the stack, while &amp;quot;World&amp;quot; is copied into variable $0&lt;br /&gt;
  ; :: old$0 -rest of the stack, if anything-&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  Pop $0&lt;br /&gt;
  ; At this point the old value of $0 is restored, and the stack just looks like the following:&lt;br /&gt;
  ; :: -rest of the stack, if anything-&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Functions can either clear the stack relevant to the function, as in the above, or they can leave an item on the stack for use after the function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.8&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function isDir&lt;br /&gt;
  Exch $0&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; _dir _notdir&lt;br /&gt;
  _dir:&lt;br /&gt;
    StrCpy $0 &amp;quot;true&amp;quot;&lt;br /&gt;
    return&lt;br /&gt;
  _notdir:&lt;br /&gt;
    StrCpy $0 &amp;quot;false&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Push &amp;quot;some path on your drive&amp;quot;&lt;br /&gt;
  Call isDir&lt;br /&gt;
  Pop $0&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where in the above code, after the call to &amp;quot;isDir&amp;quot;, $0 contains &amp;quot;true&amp;quot; if the path was a directory, and &amp;quot;false&amp;quot; if not.&lt;br /&gt;
&lt;br /&gt;
= Hybrid =&lt;br /&gt;
Mainly because of the fact that you can&#039;t easily pass parameters to Functions, many users adopt a hybrid approach employing both macros -and- functions, and a little bit of a define. (a define just allows you to say that e.g. &amp;quot;NSIS&amp;quot; means &amp;quot;Nullsoft Scriptable Install System&amp;quot; without having to write out as much).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!define writeFile &amp;quot;!insertmacro writeFile&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!macro writeFile File String&lt;br /&gt;
  Push ${File}&lt;br /&gt;
  Push ${String}&lt;br /&gt;
  Call writeFile&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Function WriteFile&lt;br /&gt;
                              ; Stack: &amp;lt;file&amp;gt; &amp;lt;string&amp;gt;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  Exch $0                     ; Stack: $0 &amp;lt;string&amp;gt;&lt;br /&gt;
  Exch                        ; Stack: &amp;lt;string&amp;gt; $0&lt;br /&gt;
  Exch $1                     ; Stack: $1 $0&lt;br /&gt;
  Push $2                     ; Stack: $2 $1 $0&lt;br /&gt;
  ; $0 = file&lt;br /&gt;
  ; $1 = string&lt;br /&gt;
  FileOpen $2 &amp;quot;$0&amp;quot; &amp;quot;a&amp;quot;&lt;br /&gt;
  FileSeek $2 0 END&lt;br /&gt;
  FileWrite $2 $1&lt;br /&gt;
  FileClose $2&lt;br /&gt;
  Pop $2                      ; Stack: $1 $0&lt;br /&gt;
  Pop $1                      ; Stack: $0&lt;br /&gt;
  Pop $0                      ; Stack: -empty-&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  ${writeFile} &amp;quot;$TEMP\alogfile.txt&amp;quot; &amp;quot;A log entry&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this allows you to combine the best of both worlds by reducing code redundancy both in your installation script -and- in the compiled installer and allowing you to &#039;pass&#039; parameters/arguments to a function by using a macro as an intermediate.  And in the end, your code looks even cleaner.&lt;br /&gt;
&lt;br /&gt;
= Caveats - or Pros/Cons =&lt;br /&gt;
- insert content -&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11174</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11174"/>
		<updated>2006-09-16T13:26:44Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.3&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.5&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1.6&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 1.1.5, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
Let&#039;s start again with what the NSIS Help file says on them:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Functions are similar to Sections in that they contain zero or more instructions.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s try a different definition.  Functions are like macros, except that the code does -not- actually get inserted or copy/pasted, if you will, when compiling.  The compiled code only exists just once in your final installer.&lt;br /&gt;
&lt;br /&gt;
A Function use equivalent to the Macro example 1.1.1 would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  Call Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Caveats of Macros and Functions =&lt;br /&gt;
- insert content -&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11173</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11173"/>
		<updated>2006-09-16T13:15:07Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 3.1, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
- insert content -&lt;br /&gt;
&lt;br /&gt;
= Caveats of Macros and Functions =&lt;br /&gt;
- insert content -&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11172</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11172"/>
		<updated>2006-09-16T13:08:23Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|Animaether}}&lt;br /&gt;
&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Example 3.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 3.1, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11171</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11171"/>
		<updated>2006-09-16T13:04:05Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  &lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 1.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is obviously just a simple example with a single line and really wouldn&#039;t be a good use of macros.  But if you have multiple lines of code that you may have to use over and over again, it may be a good idea to start using a macro for it; it allows you to just make the any changes once in the macro, and it will automatically be changed anywhere you insert it.  It also just makes your code look a lot cleaner (a single !insertmacro line vs perhaps a dozen lines) which makes it a lot easier to follow and edit.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;depending on defines and using the values of the defines&amp;quot;&lt;br /&gt;
&lt;br /&gt;
That bit is most likely to sound confusing, but gets a little more clear once you read the definition of macros in another section of the NSIS help:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;macro definitions can have one or more parameters defined. The parameters may be accessed the same way a !define would (e.g. ${PARMNAME}) from inside the macro.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are familiar with scripting in other languages, this may sound familiar to you, except in the context of functions - but please do not mix this up with Functions as they exist in the NSIS language.. we&#039;ll get to those later.&lt;br /&gt;
&lt;br /&gt;
What the above means is that you can have a macro take parameters, or arguments, and use those within the macro:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello What&lt;br /&gt;
  DetailPrint &amp;quot;Hello ${What}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello &amp;quot;World&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Tree&amp;quot;&lt;br /&gt;
  !insertmacro Hello &amp;quot;Flower&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.1&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
  DetailPrint &amp;quot;Hello World&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Tree&amp;quot;&lt;br /&gt;
  DetailPrint &amp;quot;Hello Flower&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.2&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, you only needed a single macro definition to get these three different results.  Let&#039;s take a more complex example, straight from the NSIS Help.  In NSIS, a Function can only be specified as being for the Installer, or the Uninstaller (prefixed by &amp;quot;un.&amp;quot;).  The reason for this is that it allows the compiler to make a smaller Uninstaller if it does not need the Installer&#039;s functions, and vice-versa.  However, sometimes you may have a function that both the Installer and the Uninstaller require. You could then code the Function twice:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Function SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
Function un.SomeFunc&lt;br /&gt;
  ; Lots of code here&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.3&amp;lt;/small&amp;gt;&lt;br /&gt;
However, as it should be apparent, if there&#039;s lots of code involved you have two separate areas where you have to make code changes, your code looks less clean, etc.&lt;br /&gt;
&lt;br /&gt;
With the use of macros, this can easily be resolved by writing a macro around the function that simply adds the &amp;quot;un.&amp;quot; prefix when requested:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro SomeFunc un&lt;br /&gt;
  Function ${un}SomeFunc&lt;br /&gt;
    ; lots of code here&lt;br /&gt;
  FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro SomeFunc &amp;quot;un.&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&amp;lt;small&amp;gt;Example 2.4&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will then be written out as example 2.3, but now you only have a single portion of code to maintain.&lt;br /&gt;
&lt;br /&gt;
For more information on this specific topic, see: [[Sharing_functions_between_Installer_and_Uninstaller]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11170</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11170"/>
		<updated>2006-09-16T12:42:44Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is currently in process of heavy editing.  Please do not modify!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Macros and Functions in NSIS are powerful tools to help make coding your installer easier and more flexible.  They can also be very powerful tools, allowing you to extend the NSIS scripting language to an extent - LogicLib is a great example of this.&lt;br /&gt;
&lt;br /&gt;
= Definitions =&lt;br /&gt;
== Macros ==&lt;br /&gt;
From the NSIS help file: &amp;quot;Macros are used to insert code at compile time, depending on defines and using the values of the defines. The macro&#039;s commands are inserted at compile time. This allows you to write a general code only once and use it a lot of times but with a few changes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you are new to macros in any scripting language, then this may sound a bit confusing.  Let&#039;s go through a few examples to show what the above means.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Macros are used to insert code at compile time&amp;quot;&lt;br /&gt;
What this means is that the code you define in a macro will simply be inserted at the location of your !insertmacro, as if copy/pasted, when you compile your installer script.  For example:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!macro Hello&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
&lt;br /&gt;
Section Test&lt;br /&gt;
  !insertmacro Hello&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Could be seen as just:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section Test&lt;br /&gt;
  DetailPrint &amp;quot;Hello world&amp;quot;&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11169</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11169"/>
		<updated>2006-09-16T12:28:40Z</updated>

		<summary type="html">&lt;p&gt;Animaether: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just making sure this page exists - initial content + formatting and linking to from the FAQ will follow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting FAQ]]&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11168</id>
		<title>Macro vs Function</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Macro_vs_Function&amp;diff=11168"/>
		<updated>2006-09-16T12:22:41Z</updated>

		<summary type="html">&lt;p&gt;Animaether: initial creation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just making sure this page exists - initial content + formatting and linking to from the FAQ will follow.&lt;/div&gt;</summary>
		<author><name>Animaether</name></author>
	</entry>
</feed>