// This script runs the NET NGen utility against a series of DLLs. In MSI, it should be run as a Deferred Mode In System Context Custom Action, // with a companion SetProperty CA that sets CustomActionData for this CA to [INSTALLDIR]. // It is written so it can be run outside of MSI to [vastly] simplify debugging. var ClassName_ScriptingRuntimeShell = "WScript.Shell"; var ClassName_ScriptingRuntimeFilesystem = "Scripting.FileSystemObject"; var argumentString = ""; var arguments = null; var commandLineToRun = ""; var netFrameworkRoot = ""; var net2Directory = ""; var ngenPathname = ""; var installDir = ""; // CustomActionData format: [INSTALLDIR]<?> // If running in MSI, use arguments via standard CustomActionData interface, otherwise assume running outside MSI in debugger if (DetectRunningInMSI()) argumentString = Session.Property("CustomActionData"); else argumentString = "c:\\service\\"; arguments = argumentString.split("<?>"); if (arguments.length == 1) { installDir = arguments[0]; } else { LogMessage("Argument string invalid (" +arguments.length+ "): " +argumentString); throw 3; } installDir = EnsureEndsInBackslash(installDir); // Locate native image generation tool (ngen) netFrameworkRoot = ReadRegistryValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\.NETFramework\\InstallRoot"); netFrameworkRoot = EnsureEndsInBackslash(netFrameworkRoot); net2Directory = netFrameworkRoot +"v2.0.50727\\"; ngenPathname = net2Directory +"ngen.exe"; LogMessage("GenerateNativeImages: NGen located at "+ngenPathname); // Process only EXEs. NGen will automatically recurse into all referenced assemblies. LogMessage("GenerateNativeImages: Generating images for EXEs..."); CreateNativeImagesForFiles(installDir, "exe", ngenPathname); function CreateNativeImagesForFiles( targetDirectory, targetExtension, ngenPathname ) // Compiles native machine images for all files meeting in the specified directory meeting the specified filename specification { var targetDirectoryBackslash = ""; var allFiles = null; var filesToProcess = new Array(); var currFileFullPathname = ""; var commandLineToRun = ""; // Find all files in the specified directory with the specified extension targetDirectoryBackslash = EnsureEndsInBackslash(targetDirectory); allFiles = GetDirectoryFiles(targetDirectory); for (currFileNo = 0; currFileNo < allFiles.length; currFileNo++) { if (GetFileExtension(allFiles[currFileNo]).toUpperCase() == targetExtension.toUpperCase()) { currFileFullPathname = targetDirectoryBackslash + allFiles[currFileNo]; filesToProcess.push(currFileFullPathname); } } // NGen the filtered file list for (currFileNo = 0; currFileNo < filesToProcess.length; currFileNo++) { commandLineToRun = "\""+ ngenPathname +"\" install \"" +filesToProcess[currFileNo]+ "\""; RunCommand(commandLineToRun); // Ignore Run errors, this operation is non-critical } } function GetDirectoryFiles( targetDirectory ) // Returns an array with all filenames in the specified directory. Filenames are relative to targetDirectory. { var fsUtil = null; var directoryContents = null; var targetFilesEnumerator = null; var filesArray = null; fsUtil = new SafeGetActiveXObject(ClassName_ScriptingRuntimeFilesystem); if (fsUtil != null) { try { directoryContents = fsUtil.GetFolder(targetDirectory); targetFilesEnumerator = new Enumerator(directoryContents.files); filesArray = new Array(); for (; !targetFilesEnumerator.atEnd(); targetFilesEnumerator.moveNext()) filesArray.push(targetFilesEnumerator.item().Name); } catch (unexpectedException) { LogMessage("GetDirectoryFiles: Error " +unexpectedException.number+ ": " +unexpectedException.message); } } return filesArray; } function GetFileExtension( x ) // Returns the extension of a filename (no leading .) { var separatorPos = -1; separatorPos = x.lastIndexOf("."); if (separatorPos > 0) return x.substr(separatorPos+1); else return ""; } function ReadRegistryValue( valuePath ) // Reads the specified registry value and returns it, or "" if not found { var shellObject = null; var returnVal = ""; shellObject = SafeGetActiveXObject(ClassName_ScriptingRuntimeShell); if (shellObject != null) { try { returnVal = shellObject.RegRead(valuePath); } catch (ignoreException) { // Ignore it returnVal = ""; } shellObject = null; } return returnVal; } function RunCommand( commandLine ) // Runs the specified command line and returns the process exit code or failure code { var returnVal = -1; var shellUtil = null; // Validate parameters if (commandLine == "") return -1; shellUtil = SafeGetActiveXObject(ClassName_ScriptingRuntimeShell); if (shellUtil != null) { try { LogMessage("RunCommand: Running "+commandLine); returnVal = shellUtil.Run(commandLine, 0, true); if (returnVal != 0) LogMessage("RunCommand: Error " +returnVal+ " returned by command line "+commandLine); } catch (runException) { if (runException.number == -2147024894) LogMessage("RunCommand: File not found error running command " +commandLine+ ": " +runException.message); else LogMessage("RunCommand: Error " +runException.number+ " running command " +commandLine+ ": " +runException.message); returnVal = runException.number; } shellUtil = null; } return returnVal; } function LogMessage( messageString ) // Writes a line to the MSI log, or the console if running outside MSI. { var customActionName = "CreateRemoteExecutionService"; if (DetectRunningInMSI()) { var msiMessageTypeInfo = 0x04000000 var logRecord = null; var currTime = new Date(); logRecord = Installer.CreateRecord(1); logRecord.StringData(0) = currTime.toTimeString() +" "+ customActionName +": [1]"; logRecord.StringData(1) = messageString; Session.Message(msiMessageTypeInfo, logRecord); logRecord = null; } else { var currTime = new Date(); messageString = currTime.toTimeString() +" "+ customActionName +": "+ messageString; WScript.Echo(messageString); } } function DetectRunningInMSI() // Returns TRUE if running in MSI, else FALSE { var returnVal = true; var stringVal = ""; try { // Try to reference the Session object, which is only provided by the MSI runtime engine stringVal = Session.Property("ProductCode"); } catch (thisException) { // An exception is only thrown if the runtime couldn't resolve Session, which means // this script is not running under MSI returnVal = false; } return returnVal; } function SafeGetActiveXObject( className ) // Creates an instance of className and returns it, or null if an error occurs, and logs the error { var returnVal = null; try { returnVal = new ActiveXObject(className); } catch (createException) { LogMessage("SafeGetActiveXObject: Error " +createException.number+ " creating object of class " +className+ ": " +createException.message); } return returnVal; } function EnsureEndsInBackslash( directoryPath ) // Returns directoryPath ending in a backslash if it does not already end in one. { var returnVal = directoryPath; if (returnVal.substring(returnVal.length, returnVal.length-1) != "\\") returnVal = returnVal + "\\"; return returnVal; } |