| // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. |
| // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
| // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
| // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the |
| // Software is furnished to do so, subject to the following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| // |
| // References: |
| // |
| // JScript Language Reference |
| // http://msdn2.microsoft.com/en-us/library/yek4tbz0 |
| // |
| // Windows Script Host Object Model |
| // http://msdn2.microsoft.com/en-us/library/a74hyyw0 |
| // |
| // Script Runtime |
| // http://msdn2.microsoft.com/en-us/library/hww8txat.aspx |
| // |
| |
| function ArrayAny(arr, callback) { |
| /// <summary>Checks whether any element in an array satisfies a predicate.</summary> |
| /// <param name="arr" type="Array">Array to operate on.</param> |
| /// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param> |
| /// <returns type="Boolean">true if 'callback' returns true for any element; false otherwise.</returns> |
| for (var i = 0; i < arr.length; i++) { |
| if (callback(arr[i], i)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| function ArrayWhere(arr, callback) { |
| /// <summary>Returns the elements in an array that satisfy a predicate.</summary> |
| /// <param name="arr" type="Array">Array to operate on.</param> |
| /// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param> |
| /// <returns type="Array">Array of elements from arr that satisfy the predicate.</returns> |
| |
| var result = []; |
| |
| for (var i = 0; i < arr.length; i++) { |
| if (callback(arr[i], i)) { |
| result.push(arr[i]); |
| } |
| } |
| return result; |
| } |
| |
| function ArrayForEach(arr, callback) { |
| /// <summary>Invokes a callback for each element in the array.</summary> |
| /// <param name="arr" type="Array">Array to operate on.</param> |
| /// <param name="callback" type="Function">Function to invoke with element and index.</param> |
| for (var i = 0; i < arr.length; i++) { |
| callback(arr[i], i); |
| } |
| } |
| |
| function CheckScriptFlag(name) { |
| /// <summary>Checks whether a script argument was given with true or false.</summary> |
| /// <param name="name" type="String">Argument name to check.</param> |
| /// <returns type="Boolean"> |
| /// true if the argument was given witha value of 'true' or 'True'; false otherwise. |
| /// </returns> |
| var flag = WScript.Arguments.Named(name); |
| if (!flag) { |
| return false; |
| } |
| |
| return flag === "true" || flag === "True"; |
| } |
| |
| function CreateFolderIfMissing(path) { |
| /// <summary>Creates a folder if it doesn't exist.</summary> |
| /// <param name="path" type="String">Path to folder to create.</param> |
| /// <remarks>This function will write out to the console on creation.</remarks> |
| if (!path) return; |
| var parent = PathGetDirectory(path); |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| if (!fso.FolderExists(parent)) { |
| CreateFolderIfMissing(parent); |
| } |
| if (!fso.FolderExists(path)) { |
| WScript.Echo("Creating " + path + "..."); |
| fso.CreateFolder(path); |
| } |
| } |
| |
| function DeleteFile(path, force) { |
| /// <summary>Deletes a file.</summary> |
| /// <param name="path" type="String">Path to the file.</param> |
| /// <param name="force" type="Boolean">Whether to delete the file even if it has the read-only attribute set.</param> |
| |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| fso.DeleteFile(path, force); |
| } |
| |
| function DeleteFolder(path, force) { |
| /// <summary>Deletes a folder.</summary> |
| /// <param name="path" type="String">Path to the folder.</param> |
| /// <param name="force" type="Boolean">Whether to delete the folder even if it has the read-only attribute set.</param> |
| |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| fso.DeleteFolder(path, force); |
| } |
| |
| function CopyFolder(source, dest, overwrite) { |
| /// <summary>Recursively copies a folder and its contents from source to dest.</summary> |
| /// <param name="source" type="String">Path to the source folder location.</param> |
| /// <param name="dest" type="String">Path to the destination folder location.</param> |
| /// <param name="overwrite" type="Boolean">Whether to overwrite a folder in the destination location.</param> |
| |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| fso.CopyFolder(source, dest, overwrite); |
| } |
| |
| |
| function CopyFile(source, dest, overwrite) { |
| /// <summary>Copies a file from source to dest.</summary> |
| /// <param name="source" type="String">Path to the source file location.</param> |
| /// <param name="dest" type="String">Path to the destination file location.</param> |
| /// <param name="overwrite" type="Boolean">Whether to overwrite a file in the destination location.</param> |
| |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| |
| if (overwrite && fso.FileExists(dest)) { |
| var f = fso.getFile(dest); |
| f.attributes = 0; |
| } |
| |
| fso.CopyFile(source, dest, overwrite); |
| } |
| |
| function ExtractContentsBetweenMarkers(path, contentOnly, isExclusion, startMarker, endMarker, callback) { |
| /// <summary> |
| /// Extracts the lines from the 'path' text file between the start and end markers. |
| /// </summary> |
| /// <param name="path" type="String">Path to file.</param> |
| /// <param name="contentOnly" type="Boolean"> |
| /// true to skip everything until it's found between markers, false to start including everything from the start. |
| /// </param> |
| /// <param name="isExclusion" type="Boolean"> |
| /// false if the 'extraction' means keeping the content; true if it means not excluding it from the result. |
| /// </param> |
| /// <param name="startMarker" type="String">Line content to match for content start.</param> |
| /// <param name="endMarker" type="String">Line content to match for content end.</param> |
| /// <param name="callback" type="Function" mayBeNull="true"> |
| /// If true, then this function is called for every line along with the inContent flag |
| /// before the line is added; the called function may return a line |
| /// to be added in its place, null to skip processing. |
| /// </param> |
| /// <returns type="String">The string content of the file.</returns> |
| |
| var content = ReadAllTextFile(path); |
| return ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback); |
| } |
| |
| function ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback) { |
| /// <summary> |
| /// Extracts the lines from the specified text between the start and end markers. |
| /// </summary> |
| /// <param name="content" type="String">Text to process.</param> |
| /// <param name="contentOnly" type="Boolean"> |
| /// true to skip everything until it's found between markers, false to start including everything from the start. |
| /// </param> |
| /// <param name="isExclusion" type="Boolean"> |
| /// false if the 'extraction' means keeping the content; true if it means not excluding it from the result. |
| /// </param> |
| /// <param name="startMarker" type="String">Line content to match for content start.</param> |
| /// <param name="endMarker" type="String">Line content to match for content end.</param> |
| /// <param name="callback" type="Function" mayBeNull="true"> |
| /// If true, then this function is called for every line along with the inContent flag |
| /// before the line is added; the called function may return a line |
| /// to be added in its place, null to skip processing. |
| /// </param> |
| /// <returns type="String">The extracted content.</returns> |
| |
| var inContent = contentOnly === false; |
| var lines = StringSplit(content, "\r\n"); |
| var result = []; |
| var i, len; |
| for (i = 0, len = lines.length; i < len; i++) { |
| var line = lines[i]; |
| var contentStartIndex = line.indexOf(startMarker); |
| if (inContent === false && contentStartIndex !== -1) { |
| inContent = true; |
| continue; |
| } |
| |
| var contentEndIndex = line.indexOf(endMarker); |
| if (inContent === true && contentEndIndex !== -1) { |
| inContent = false; |
| continue; |
| } |
| |
| if (inContent !== isExclusion) { |
| if (callback) { |
| var callbackResult = callback(line, inContent); |
| if (callbackResult !== null && callbackResult !== undefined) { |
| result.push(callbackResult); |
| } |
| } else { |
| result.push(line); |
| } |
| } |
| } |
| |
| return result.join("\r\n"); |
| } |
| |
| function FolderExists(path) { |
| /// <summary>Checks whether the specified directory exists.</summary> |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| if (fso.FolderExists(path)) { |
| return true; |
| } |
| else { |
| return false; |
| } |
| } |
| |
| function FileExists(path) { |
| /// <summary>Checks whether the specified file exists.</summary> |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| if (fso.FileExists(path)) { |
| return true; |
| } |
| else { |
| return false; |
| } |
| } |
| |
| function GetEnvironmentVariable(name) { |
| /// <summary>Gets the value of the specified environment variable.</summary> |
| /// <param name="name" type="String">Name of the variable value to get.</param> |
| /// <returns type="String">Value for the given environment variable; null if undefined.</returns> |
| var shell = new ActiveXObject("WScript.Shell"); |
| var result = shell.ExpandEnvironmentStrings("%" + name + "%"); |
| if (result == "%" + name + "%") { |
| result = null; |
| } |
| |
| return result; |
| } |
| |
| function GetFilesRecursive(path) { |
| /// <summary>Gets all file names under the specified directory path.</summary> |
| /// <param name="path" type="String">Path to directory.</param> |
| /// <returns type="Array">Array of all file names under path.</returns> |
| |
| var result = []; |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| var pending = [path]; |
| |
| while (pending.length) { |
| var item = pending.pop(); |
| var folder = fso.GetFolder(item); |
| for (var files = new Enumerator(folder.Files); !files.atEnd(); files.moveNext()) { |
| result.push(files.item().Path); |
| } |
| |
| for (var subFolders = new Enumerator(folder.SubFolders); !subFolders.atEnd(); subFolders.moveNext()) { |
| pending.push(subFolders.item().Path); |
| } |
| } |
| |
| return result; |
| } |
| |
| function GetRelativePathFrom(startPath, endPath) { |
| if (startPath[startPath.length - 1] !== "\\") { |
| startPath += "\\"; |
| } |
| |
| if (startPath.length > endPath.length) { |
| throw { message: "traversing up NYI" }; |
| } |
| |
| return endPath.substr(startPath.length); |
| } |
| |
| function MatchesMask(file, mask) { |
| if (!mask) { |
| return false; |
| } |
| |
| if (file === mask) { |
| return true; |
| } |
| |
| if (mask.substr(0, 1) === "*") { |
| var rest = mask.substr(1); |
| return file.substr(file.length - rest.length) === rest; |
| } else if (mask.substr(mask.length - 1) === "*") { |
| var end = mask.substr(0, mask.length - 1); |
| return file.substr(0, end.length) === end; |
| } |
| |
| return false; |
| } |
| |
| function PathGetDirectory(path) { |
| /// <summary> |
| /// Returns the directory of the specified path string (excluding the trailing "\\"); |
| /// empty if there is no path. |
| /// </summary> |
| |
| var l = path.length; |
| var startIndex = l; |
| while (--startIndex >= 0) { |
| var ch = path.substr(startIndex, 1); |
| if (ch == "\\") { |
| if (startIndex === 0) { |
| return ""; |
| } else { |
| return path.substr(0, startIndex); |
| } |
| } |
| } |
| |
| return ""; |
| } |
| |
| function PathGetFileName(path) { |
| /// <summary> |
| /// Returns the file name for the specified path string; empty if there is no |
| /// directory information. |
| /// </summary> |
| var l = path.length; |
| var startIndex = l; |
| while (--startIndex >= 0) { |
| var ch = path.substr(startIndex, 1); |
| if (ch == "\\" || ch == "/" || ch == ":") { |
| return path.substr(startIndex, l - startIndex); |
| } |
| } |
| return ""; |
| } |
| |
| function PathGetExtension(path) { |
| /// <summary> |
| /// Returns the extension of the specified path string (including the "."); |
| /// empty if there is no extension. |
| /// </summary> |
| var l = path.length; |
| var startIndex = l; |
| while (--startIndex >= 0) { |
| var ch = path.substr(startIndex, 1); |
| if (ch == ".") { |
| if (startIndex != (l - 1)) { |
| return path.substr(startIndex, l - startIndex); |
| } |
| return ""; |
| } |
| else if (ch == "\\" || ch == ":") { |
| break; |
| } |
| } |
| return ""; |
| } |
| |
| function ReadAllTextFile(path) { |
| /// <summary>Reads all the content of the file into a string.</summary> |
| /// <param name="path" type="String">File name to read from.</param> |
| /// <returns type="String">File contents.</returns> |
| var ForReading = 1, ForWriting = 2; |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| var file = fso.OpenTextFile(path, ForReading); |
| try { |
| var result; |
| if (file.AtEndOfStream) { |
| result = ""; |
| } else { |
| result = file.ReadAll(); |
| } |
| } finally { |
| file.Close(); |
| } |
| |
| return result; |
| } |
| |
| function ReadXmlFile(path) { |
| /// <summary>Reads an XML document from the specified path.</summary> |
| /// <param name="path" type="String">Path to file on disk.</param> |
| /// <returns>A DOMDocument with the contents of the given file.</returns> |
| var result = new ActiveXObject("Msxml2.DOMDocument.6.0"); |
| result.async = false; |
| result.load(path); |
| if (result.parseError.errorCode !== 0) { |
| throw { message: "Error reading '" + path + "': " + result.parseError.reason }; |
| } |
| |
| return result; |
| } |
| |
| // Runs the specified function catching exceptions and quits the current script. |
| function RunAndQuit(f) { |
| try { |
| f(); |
| } |
| catch (e) { |
| // An error with 'statusCode' defined will avoid the usual error dump handling. |
| if (e.statusCode !== undefined) { |
| if (e.message) { |
| WScript.Echo(e.message); |
| } |
| |
| WScript.Quit(e.statusCode); |
| } |
| |
| WScript.Echo("Error caught while running this function:"); |
| WScript.Echo(f.toString()); |
| WScript.Echo("Error details:"); |
| if (typeof (e) == "object" && e.toString() == "[object Object]" || e.toString() === "[object Error]") { |
| for (var p in e) WScript.Echo(" " + p + ": " + e[p]); |
| } |
| else { |
| WScript.Echo(e); |
| } |
| |
| WScript.Quit(1); |
| } |
| WScript.Quit(0); |
| } |
| |
| function RunConsoleCommand(strCommand, timeout, retry) { |
| /// <summary>Runs a command and waits for it to exit.</summary> |
| /// <param name="strCommand" type="String">Command to run.</param> |
| /// <param name="timeout" type="int">Timeout in seconds.</param> |
| /// <param name="timeout" type="bool">Boolean specifying whether to retry on timeout or not.</param> |
| /// <returns type="Array">An array with stdout in 0, stderr in 1 and exit code in 2. Forced |
| /// termination sets 2 to 1.</returns> |
| var WshShell = new ActiveXObject("WScript.Shell"); |
| var result = new Array(3); |
| var oExec = WshShell.Exec(strCommand); |
| var counter = 0; |
| |
| if (timeout) { |
| // Status of 0 means the process is still running |
| while (oExec.Status === 0 && counter < timeout) { |
| WScript.Sleep(1000); |
| counter++; |
| } |
| |
| if (timeout === counter && oExec.Status === 0) { |
| WScript.Echo("Forcefully terminating " + strCommand + " after " + timeout + " seconds."); |
| oExec.Terminate(); |
| result[2] = 1; |
| if (retry) { |
| return RunConsoleCommand(strCommand, timeout, false); |
| } |
| } |
| } |
| |
| result[0] = oExec.StdOut.ReadAll(); |
| result[1] = oExec.StdErr.ReadAll(); |
| |
| if (!result[2]) { |
| result[2] = oExec.ExitCode; |
| } |
| |
| return result; |
| } |
| |
| function SaveTextToFile(content, path) { |
| /// <summary>Saves text content into a file.</summary> |
| /// <param name="content" type="String">Content to save.</param> |
| /// <param name="path" type="String">Path of file to save into.</param> |
| var ForReading = 1, ForWriting = 2; |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| var file = fso.OpenTextFile(path, ForWriting, true); |
| file.Write(content); |
| file.Close(); |
| } |
| |
| function StringSplit(strLine, strSeparator) { |
| /// <summary>Splits a string into a string array.</summary> |
| var result = new Array(); |
| var startIndex = 0; |
| var resultIndex = 0; |
| while (startIndex < strLine.length) { |
| var endIndex = strLine.indexOf(strSeparator, startIndex); |
| if (endIndex == -1) { |
| endIndex = strLine.length; |
| } |
| result[resultIndex] = strLine.substring(startIndex, endIndex); |
| startIndex = endIndex + strSeparator.length; |
| resultIndex++; |
| } |
| return result; |
| } |
| |
| function PathCombine(path1, path2) { |
| if (path1.charAt(path1.length - 1) !== "\\") { |
| return path1 + "\\" + path2; |
| } |
| return path1 + path2; |
| } |
| |
| function RemoveReadOnlyAttribute(path) { |
| /// <summary>Removes the read-only attribute on the specified file.</summary> |
| /// <param name="path" type="String">Path to the file.</param> |
| var fso = new ActiveXObject("Scripting.FileSystemObject"); |
| var f = fso.getFile(path); |
| if (1 === (f.attributes & 1)) { |
| f.attributes = (f.attributes & ~1); |
| } |
| } |
| |
| function WriteXmlFile(document, path) { |
| /// <summary>Write an XML document to the specified path.</summary> |
| /// <param name="path" type="String">Path to file on disk.</param> |
| document.save(path); |
| } |