@echo off
pushd %~dp0
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~ Filename: NetFx_Enable.bat                                                ~~
rem ~~                                                                           ~~
rem ~~ Description:                                                              ~~
rem ~~   This file contains the logic and commands necessary to enable           ~~
rem ~~   the .Net Framework on Windows.                                          ~~
rem ~~                                                                           ~~
rem ~~ Instructions:                                                             ~~
rem ~~   To enable the .Net Framework on Windows, run this batch file with       ~~
rem ~~   admin privileges. To do this, simply add it to a WiX Burn bundle as     ~~
rem ~~   an ExePackage, with this batch file being the value of @SourceFile      ~~
rem ~~   and the unquoted path to the log file as the value of @InstallCommand.  ~~
rem ~~   Make sure to set the value of @InstallCommand to the following.         ~~
rem ~~     InstallCommand='[VersionNT] [FullPathToLogFile]'                      ~~
rem ~~   where FullPathToLogFile is the name of the variable containing the      ~~
rem ~~   full path to the log file.                                              ~~
rem ~~   See the NetFxPackages.wxs file for an example.                          ~~
rem ~~                                                                           ~~
rem ~~   Alternatively and more simply, you can import the NetFxPackages.targets ~~
rem ~~   file to the bundle project and add the following element to the bundle  ~~
rem ~~   as a child of the Chain element.                                        ~~
rem ~~     <PackageGroupRef Id="NetFx_Enable" />                                 ~~
rem ~~                                                                           ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

set ThisBatchFile=%~f0
set AllArguments=%*
set MagicValue=D01C198753F74599800068B2718B4410

if "%1" == "%MagicValue%" (
	rem If this batch script is being called by itself, with the correct parameters, then enable the .Net Framework.

	echo Currently running command: %0 %*
	echo.

	set VersionNT=%2
	call :LaunchNetFxEnableCommand

) else (
	rem If this batch script is being called by an outside process, then re-call this batch script recursively.

	echo Relaunching batch file: '%ThisBatchFile%'
	echo.

	call :SeparateArgs
	call :CreateLogFolder
	call :RelaunchScriptUsingNativeArchitecture
)

echo Process completed.
echo Exit code: '%errorlevel%'

popd
exit /b %errorlevel%


rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~       Subroutines                                                         ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~ Function: SeparateArgs                                        ~~
rem ~~                                                               ~~
rem ~~ Description:                                                  ~~
rem ~~   Separates the first arguments from the rest of the          ~~
rem ~~   arguments, which together make up the full file path to     ~~
rem ~~   the log file.                                               ~~
rem ~~                                                               ~~
rem ~~ Parameters: None                                              ~~
rem ~~                                                               ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:SeparateArgs
	for /f "tokens=1,*" %%G in ("%AllArguments%") do (
		rem The first argument is the value of VersionNT, something like 6.1.0.0
		set VersionNT=%%G
		rem The rest is the path to the log file.
		rem This works even with whitespace in the path, including multiple consecutive spaces.
		set LogFilePath=%%H
		set LogFileFolder=%%~dpH
	)
exit /b %errorlevel%


rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~ Function: CreateLogFolder                                     ~~
rem ~~                                                               ~~
rem ~~ Description:                                                  ~~
rem ~~   Creates the log file's folder if it does not already exist. ~~
rem ~~                                                               ~~
rem ~~ Parameters: None                                              ~~
rem ~~                                                               ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:CreateLogFolder
	rem Remove the trailing backslash to prevent errors when a folder is surrounded in quotes.
	if "%LogFileFolder:~-1%" == "\" (
		set LogFileFolder=%LogFileFolder:~,-1%
	)
	rem Create the folder, if it does not already exist.
	if not exist "%LogFileFolder%" md "%LogFileFolder%"
exit /b %errorlevel%


rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~ Function: RelaunchScriptUsingNativeArchitecture               ~~
rem ~~                                                               ~~
rem ~~ Description:                                                  ~~
rem ~~   Relaunches this batch script file, with the specified log   ~~
rem ~~   file as its output. It also uses the system's native        ~~
rem ~~   architecture to launch cmd.exe, so that PowerShell and      ~~
rem ~~   Dism commands behave as expected.                           ~~
rem ~~                                                               ~~
rem ~~ Parameters: None                                              ~~
rem ~~                                                               ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:RelaunchScriptUsingNativeArchitecture
	if "%PROCESSOR_ARCHITEW6432%" == "" (
		rem Run this batch file recursively.
		"%comspec%" /c ""%ThisBatchFile%" %MagicValue% %VersionNT% > "%LogFilePath%""
	) else (
		rem When running this batch script as a 32-bit process on
		rem  an x64 system, re-run it recursively using the sysnative redirection.
		echo Redirecting command processor to native architecture: '%SystemRoot%\Sysnative\cmd.exe'
		echo.

		"%SystemRoot%\Sysnative\cmd.exe" /c ""%ThisBatchFile%" %MagicValue% %VersionNT% > "%LogFilePath%""
	)
exit /b %errorlevel%


rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rem ~~ Function: LaunchNetFxEnableCommand                            ~~
rem ~~                                                               ~~
rem ~~ Description:                                                  ~~
rem ~~   Launches the command to enable the .Net Framework, based    ~~
rem ~~   on the OS version passed to this batch script from the      ~~
rem ~~   command line.                                               ~~
rem ~~                                                               ~~
rem ~~ Parameters: None                                              ~~
rem ~~                                                               ~~
rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:LaunchNetFxEnableCommand
	rem Convert a version number string to include only its Major and Minor version numbers.
	rem   Note: Batch script arithmetic comparisons don't play nice with decimal points, so set the OS version without one.
	rem         This is the same math used by the Windows Installer to assign the OS version to the VersionNT property.
	rem         (Major * 100) + Minor
	rem   Example: Converts 6.1.0.0 to 601
	for /f "tokens=1,2 delims=." %%G in ("%VersionNT%") do (
		set VersionNT_Major=%%G
		set VersionNT_Minor=%%H
	)
	set /a "VersionNT=(VersionNT_Major*100)+VersionNT_Minor"
	echo Windows version: '%VersionNT%'
	echo.

	rem Enable the .Net Framework 3.5 SP1 on Windows 7 (and Server 2008 R2).
	rem Note: On Windows Server 2008 R2, the following command would work as well.
	rem       powershell.exe -ImportSystemModules Add-WindowsFeature net-framework
	if %VersionNT% EQU 601 set NetFxEnableCommand=dism.exe /Online /Enable-Feature /FeatureName:NetFx3 /NoRestart

	rem Enable the .Net Framework 4.x on Windows 8 (and Server 2012) and later.
	if %VersionNT% GEQ 602 set NetFxEnableCommand=powershell.exe Install-WindowsFeature Net-Framework-45-Core

	rem Run the command.
	echo Beginning execution of the command: '%NetFxEnableCommand%'
	echo.
	%NetFxEnableCommand%

exit /b %errorlevel%
