///////////////////////////////////////////////////////////////////////////////
// //
// hctjs.js //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
///////////////////////////////////////////////////////////////////////////////
//
// 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
//
// Include this file with:
// eval(new ActiveXObject("Scripting.FileSystemObject").OpenTextFile(new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings("%HLSL_SRC_DIR%\\utils\\hct\\hctjs.js"), 1).ReadAll());
function ArrayAny(arr, callback) {
/// Checks whether any element in an array satisfies a predicate.
/// Array to operate on.
/// Function to test with element and index, returning true or false.
/// true if 'callback' returns true for any element; false otherwise.
for (var i = 0; i < arr.length; i++) {
if (callback(arr[i], i)) {
return true;
}
}
return false;
}
function ArrayDistinct(arr, comparer) {
/// Returns each element in the array at-most-once.
/// Array to operate on.
/// Optional comparer.
/// Array of elements from arr, sorted as the comparer, with no repeating elements.
var result = arr.slice(0);
if (result.length === 0) {
return result;
}
if (!comparer) {
comparer = CompareValues;
}
result.sort(comparer);
var readIndex = 1, lastWriteIndex = 0;
while (readIndex < result.length) {
if (comparer(result[readIndex], result[lastWriteIndex]) !== 0) {
lastWriteIndex += 1;
if (readIndex !== lastWriteIndex) {
result[lastWriteIndex] = result[readIndex];
}
}
readIndex += 1;
}
lastWriteIndex += 1;
if (lastWriteIndex < result.length) {
result = result.slice(0, lastWriteIndex);
}
return result;
}
function ArrayForEach(arr, callback) {
/// Invokes a callback for each element in the array.
/// Array to operate on.
/// Function to invoke with element and index.
for (var i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}
function ArrayIndexOf(arr, element) {
/// Scans the specified array for the given element.
/// Array to operate on.
/// Element to look for.
for (var i = 0; i < arr.length; i++) {
if (arr[i] == element) {
return i;
}
}
return -1;
}
function ArrayMax(arr) {
/// Gets the maximum value of the specified array.
if (arr.length === 0) {
return undefined;
}
var result = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] > result) {
result = arr[i];
}
}
return result;
}
function ArraySelect(arr, selector) {
/// Invokes a selector callback for each element in the array.
/// Array to operate on.
/// Function to invoke with element and index.
/// Array of selections for the arr element.
var result = [];
for (var i = 0; i < arr.length; i++) {
result.push(selector(arr[i], i));
}
return result;
}
function ArraySelectMany(arr, selector) {
/// Invokes a selector callback for each element in the array to produce multiple results.
/// Array to operate on.
/// Function to invoke with element and index.
/// Array of flattened selections for the arr element.
var result = [];
for (var i = 0; i < arr.length; i++) {
var selectorArr = selector(arr[i], i);
if (selectorArr) {
for (var j = 0; j < selectorArr.length; j++) {
result.push(selectorArr[j]);
}
}
}
return result;
}
function ArraySelectMember(arr, memberName) {
/// Invokes a selector callback for each element in the array.
/// Array to operate on.
/// Member name to select from each array element.
/// Array of members for the arr elements.
var result = [];
for (var i = 0; i < arr.length; i++) {
result.push(arr[i][memberName]);
}
return result;
}
function ArraySort(arr, comparer) {
/// Adds the values in the array.
/// Array to operate on.
/// Sum of the arr elements.
var result = arr.slice(0);
result.sort(comparer);
return result;
}
function ArraySum(arr) {
/// Adds the values in the array.
/// Array to operate on.
/// Sum of the arr elements.
var result = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
result += arr[i];
}
}
return result;
}
function ArrayTake(arr, count) {
/// Returns the first count elements (or the original array if it has less than count elements.
if (arr.length < count) {
return arr;
}
return arr.slice(0, count);
}
function ArrayWhere(arr, callback) {
/// Returns the elements in an array that satisfy a predicate.
/// Array to operate on.
/// Function to test with element and index, returning true or false.
/// Array of elements from arr that satisfy the predicate.
var result = [];
for (var i = 0; i < arr.length; i++) {
if (callback(arr[i], i)) {
result.push(arr[i]);
}
}
return result;
}
function CheckScriptFlag(name) {
/// Checks whether a script argument was given with true or false.
/// Argument name to check.
///
/// true if the argument was given witha value of 'true' or 'True'; false otherwise.
///
var flag = WScript.Arguments.Named(name);
if (!flag) {
return false;
}
return flag === "true" || flag === "True";
}
function CreateFolderIfMissing(path) {
/// Creates a folder if it doesn't exist.
/// Path to folder to create.
/// This function will write out to the console on creation.
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 CompareValues(left, right) {
if (left === right) return 0;
if (left < right) return -1;
return 1;
}
function CompareValuesAsStrings(left, right) {
if (left === right) return 0;
left = (left === null) ? "" : left.toString();
right = (right === null) ? "" : right.toString();
if (left === right) return 0;
if (left < right) return -1;
return 1;
}
function DbValueToString(value) {
/// Returns a string representation for a database value.
/// Value from database.
/// A string representing the specified value.
if (value === null || value === undefined) {
return "NULL";
}
return value.toString();
}
function DeleteFile(path, force) {
/// Deletes a file.
/// Path to the file.
/// Whether to delete the file even if it has the read-only attribute set.
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFile(path, force);
}
function DeleteFolder(path, force) {
/// Deletes a folder.
/// Path to the folder.
/// Whether to delete the folder even if it has the read-only attribute set.
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFolder(path, force);
}
function CopyFolder(source, dest, overwrite) {
/// Recursively copies a folder and its contents from source to dest.
/// Path to the source folder location.
/// Path to the destination folder location.
/// Whether to overwrite a folder in the destination location.
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.CopyFolder(source, dest, overwrite);
}
function CopyFile(source, dest, overwrite) {
/// Copies a file from source to dest.
/// Path to the source file location.
/// Path to the destination file location.
/// Whether to overwrite a file in the destination location.
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 ExpandEnvironmentVariables(name) {
///
/// Replaces the name of each environment variable embedded in the specified string with the
/// string equivalent of the value of the variable, then returns the resulting string.
///
///
/// A string containing the names of zero or more environment variables. Each environment variable is quoted with the percent sign character (%).
///
/// A string with each environment variable replaced by its value.
var shell = new ActiveXObject("WScript.Shell");
var result = shell.ExpandEnvironmentStrings(name);
return result;
}
function ExtractContentsBetweenMarkers(path, contentOnly, isExclusion, startMarker, endMarker, callback) {
///
/// Extracts the lines from the 'path' text file between the start and end markers.
///
/// Path to file.
///
/// true to skip everything until it's found between markers, false to start including everything from the start.
///
///
/// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
///
/// Line content to match for content start.
/// Line content to match for content end.
///
/// 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.
///
/// The string content of the file.
var content = ReadAllTextFile(path);
return ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback);
}
function ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback) {
///
/// Extracts the lines from the specified text between the start and end markers.
///
/// Text to process.
///
/// true to skip everything until it's found between markers, false to start including everything from the start.
///
///
/// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
///
/// Line content to match for content start.
/// Line content to match for content end.
///
/// 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.
///
/// The extracted content.
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 (callback) {
var callbackResult = callback(line, inContent);
if (callbackResult !== null && callbackResult !== undefined) {
result.push(callbackResult);
}
} else {
if (inContent && !isExclusion) {
result.push(line);
} else if (!inContent && isExclusion) {
result.push(line);
}
}
}
return result.join("\r\n");
}
function FolderExists(path) {
/// Checks whether the specified directory exists.
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FolderExists(path)) {
return true;
}
else {
return false;
}
}
function FileExists(path) {
/// Checks whether the specified file exists.
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FileExists(path)) {
return true;
}
else {
return false;
}
}
function GetEnvironmentVariable(name) {
/// Gets the value of the specified environment variable.
/// Name of the variable value to get.
/// Value for the given environment variable; null if undefined.
var shell = new ActiveXObject("WScript.Shell");
var result = shell.ExpandEnvironmentStrings("%" + name + "%");
if (result == "%" + name + "%") {
result = null;
}
return result;
}
function GetFilesRecursive(path) {
/// Gets all file names under the specified directory path.
/// Path to directory.
/// Array of all file names under path.
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 OpenCsvConnection(path) {
/// Opens an ADO Connection object to the directory path where CSV files are found.
/// Directory path where .csv files are.
/// An open connection.
var connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + path + ";" +
"Extended Properties=\"text;HDR=YES;FMT=Delimited\"";
var objConnection = WScript.CreateObject("ADODB.Connection");
objConnection.Open(connectionString);
return objConnection;
}
function OpenSqlCeConnection(path) {
/// Opens an ADO Connection object to a SQL CE file.
/// File path for .sdf file.
/// An open connection.
var connectionString = "Provider=Microsoft.SQLSERVER.CE.OLEDB.4.0;" +
"Data Source=" + path + ";";
var objConnection = WScript.CreateObject("ADODB.Connection");
objConnection.Open(connectionString);
return objConnection;
}
function PathGetDirectory(path) {
///
/// Returns the directory of the specified path string (excluding the trailing "\\");
/// empty if there is no path.
///
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) {
///
/// Returns the file name for the specified path string; empty if there is no
/// directory information.
///
var l = path.length;
var startIndex = l;
while (--startIndex >= 0) {
var ch = path.substr(startIndex, 1);
if (ch == "\\" || ch == "/" || ch == ":") {
return path.substr(startIndex + 1);
}
}
return "";
}
function PathGetExtension(path) {
///
/// Returns the extension of the specified path string (including the ".");
/// empty if there is no extension.
///
/// The extension of the specified path, including the '.'.
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) {
/// Reads all the content of the file into a string.
/// File name to read from.
/// File contents.
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) {
/// Reads an XML document from the specified path.
/// Path to file on disk.
/// A DOMDocument with the contents of the given file.
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) {
/// Runs a command and waits for it to exit.
/// Command to run.
/// Timeout in seconds.
/// Boolean specifying whether to retry on timeout or not.
///
/// An array with stdout in 0, stderr in 1 and exit code in 2. Forced
/// termination sets the exit code to 1.
///
// WScript.Echo("running [" + strCommand + "]");
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;
}
// WScript.Echo(" stdout: " + result[0]);
// WScript.Echo(" stderr: " + result[1]);
// WScript.Echo(" exit code: " + result[2]);
return result;
}
function Say(text) {
/// Uses the Speech API to speak to the user.
var voice = new ActiveXObject("SAPI.SpVoice");
try {
voice.Speak(text);
} catch (e) {
// See http://msdn2.microsoft.com/en-us/library/ms717306.aspx for error codes.
// SPERR_DEVICE_BUSY 0x80045006 -2147201018
if (e.number == -2147201018) {
WScript.Echo("The wave device is busy.");
WScript.Echo("Happens sometimes over Terminal Services.");
}
}
}
function SaveTextToFile(content, path) {
/// Saves text content into a file.
/// Content to save.
/// Path of file to save into.
var ForReading = 1, ForWriting = 2;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile(path, ForWriting, true);
file.Write(content);
file.Close();
}
function SelectLength(value) {
return value.length;
}
function SendMicrosoftMail(subject, text, toAddress) {
var shell = new ActiveXObject("WScript.Shell");
var userName = shell.ExpandEnvironmentStrings("%username%");
var fromAddress = userName + "@microsoft.com";
var server = "smtphost.redmond.corp.microsoft.com";
if (!toAddress) {
toAddress = fromAddress;
}
var message = new ActiveXObject("CDO.Message");
var configuration = message.Configuration;
// 2 = cdoSendUsingPort; 2 = cdoNTLM
configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = server;
configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 2;
configuration.Fields.Update();
message.To = toAddress;
message.From = fromAddress;
message.Subject = subject;
message.TextBody = text;
message.Send();
}
function StringBetween(text, startMarker, endMarker) {
/// Returns the text between startMarker and endMarker in text, null if not found.
var startIndex = text.indexOf(startMarker);
if (startIndex == -1) return null;
var endIndex = text.indexOf(endMarker, startIndex + startMarker.length);
if (endIndex == -1) return null;
return text.substring(startIndex + startMarker.length, endIndex);
}
function StringPadRight(value, length, padString) {
/// Returns a padded string.
/// Value to pad.
/// Target length for string.
/// Optional string to pad with; defaults to space.
/// The padded string.
if (!padString) padString = " ";
if (value.length < length) {
value = value + Array(length + 1 - value.length).join(padString);
}
return value;
}
function StringToLower(text) {
/// Returns the lowercase form of the specified string.
/// Value to lower.
/// The lowercase value.
if (text) {
return text.toLowerCase();
} else {
return text;
}
}
function StringSplit(strLine, strSeparator) {
/// Splits a string into a string array.
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 StringTrim(text) {
var result = text.replace(/^\s*/, "").replace(/\s*$/, "");
return result
}
function PathCombine(path1, path2) {
if (path1.charAt(path1.length - 1) !== "\\") {
return path1 + "\\" + path2;
}
return path1 + path2;
}
function RemoveReadOnlyAttribute(path) {
/// Removes the read-only attribute on the specified file.
/// Path to the file.
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.getFile(path);
if (1 === (f.attributes & 1)) {
f.attributes = (f.attributes & ~1);
}
}
function RunWmiQuery(query) {
/// Runs a WMI query and returns all objects.
/// Query to run.
/// Array with results.
var result = [];
var wmiService = GetObject("winmgmts:\\\\.\\root\\cimv2");
var items = wmiService.ExecQuery(query);
var e = new Enumerator(items);
while (!e.atEnd()) {
result.push(e.item());
e.moveNext();
}
return result;
}
function WriteRecordSetToTextStreamAsAsciiTable(objRecordSet, stream) {
/// Writes all content of the specified ADO RecordSet into the given text stream.
/// RecordSet to write out to.
/// Optional TextStream to write to; defaults to WScript.Out.
var outStream = (stream) ? stream : WScript.StdOut;
var fields = objRecordSet.Fields;
var columns = new Array(fields.Count);
var rowCount = 1;
for (var i = 0; i < fields.Count; i++) {
columns[i] = [];
columns[i].push(fields.Item(i).Name);
}
while (!objRecordSet.EOF) {
for (var i = 0; i < fields.Count; i++) {
columns[i].push(DbValueToString(fields.Item(i).Value));
}
++rowCount;
objRecordSet.MoveNext();
}
var columnSizes = new Array(columns.length);
for (var i = 0; i < columns.length; ++i) {
var valueLengths = ArraySelect(columns[i], SelectLength);
columnSizes[i] = ArrayMax(valueLengths);
}
for (var rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
for (var i = 0; i < columnSizes.length; ++i) {
outStream.Write(StringPadRight(columns[i][rowIndex], 1 + columnSizes[i]));
}
outStream.WriteLine();
if (rowIndex === 0) {
for (var i = 0; i < columnSizes.length; ++i) {
outStream.Write(StringPadRight("", columnSizes[i], "-"));
outStream.Write(" ");
}
outStream.WriteLine();
}
}
}
function WriteRecordSetToTextStream(objRecordSet, separator, stream) {
/// Writes all content of the specified ADO RecordSet into the given text stream.
/// RecordSet to write out to.
/// Text between fields.
/// Optional TextStream to write to; defaults to WScript.Out.
var outStream = (stream) ? stream : WScript.StdOut;
var fields = objRecordSet.Fields;
for (var i = 0; i < fields.Count; i++) {
if (i > 0) outStream.Write(separator);
outStream.Write(fields.Item(i).Name);
}
outStream.WriteLine();
while (!objRecordSet.EOF) {
for (var i = 0; i < fields.Count; i++) {
if (i > 0) outStream.Write(separator);
outStream.Write(fields.Item(i).Value);
}
outStream.WriteLine();
objRecordSet.MoveNext();
}
}
function WriteXmlFile(document, path) {
/// Write an XML document to the specified path.
/// Path to file on disk.
document.save(path);
}