hctjs.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // hctjs.js //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. //
  10. // References:
  11. //
  12. // JScript Language Reference
  13. // http://msdn2.microsoft.com/en-us/library/yek4tbz0
  14. //
  15. // Windows Script Host Object Model
  16. // http://msdn2.microsoft.com/en-us/library/a74hyyw0
  17. //
  18. // Script Runtime
  19. // http://msdn2.microsoft.com/en-us/library/hww8txat.aspx
  20. //
  21. // Include this file with:
  22. // eval(new ActiveXObject("Scripting.FileSystemObject").OpenTextFile(new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings("%HLSL_SRC_DIR%\\utils\\hct\\hctjs.js"), 1).ReadAll());
  23. function ArrayAny(arr, callback) {
  24. /// <summary>Checks whether any element in an array satisfies a predicate.</summary>
  25. /// <param name="arr" type="Array">Array to operate on.</param>
  26. /// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param>
  27. /// <returns type="Boolean">true if 'callback' returns true for any element; false otherwise.</returns>
  28. for (var i = 0; i < arr.length; i++) {
  29. if (callback(arr[i], i)) {
  30. return true;
  31. }
  32. }
  33. return false;
  34. }
  35. function ArrayDistinct(arr, comparer) {
  36. /// <summary>Returns each element in the array at-most-once.</summary>
  37. /// <param name="arr" type="Array">Array to operate on.</param>
  38. /// <param name="comparer" type="Function">Optional comparer.</param>
  39. /// <returns type="Array">Array of elements from arr, sorted as the comparer, with no repeating elements.</returns>
  40. var result = arr.slice(0);
  41. if (result.length === 0) {
  42. return result;
  43. }
  44. if (!comparer) {
  45. comparer = CompareValues;
  46. }
  47. result.sort(comparer);
  48. var readIndex = 1, lastWriteIndex = 0;
  49. while (readIndex < result.length) {
  50. if (comparer(result[readIndex], result[lastWriteIndex]) !== 0) {
  51. lastWriteIndex += 1;
  52. if (readIndex !== lastWriteIndex) {
  53. result[lastWriteIndex] = result[readIndex];
  54. }
  55. }
  56. readIndex += 1;
  57. }
  58. lastWriteIndex += 1;
  59. if (lastWriteIndex < result.length) {
  60. result = result.slice(0, lastWriteIndex);
  61. }
  62. return result;
  63. }
  64. function ArrayForEach(arr, callback) {
  65. /// <summary>Invokes a callback for each element in the array.</summary>
  66. /// <param name="arr" type="Array">Array to operate on.</param>
  67. /// <param name="callback" type="Function">Function to invoke with element and index.</param>
  68. for (var i = 0; i < arr.length; i++) {
  69. callback(arr[i], i);
  70. }
  71. }
  72. function ArrayIndexOf(arr, element) {
  73. /// <summary>Scans the specified array for the given element.</summary>
  74. /// <param name="arr" type="Array">Array to operate on.</param>
  75. /// <param name="element">Element to look for.</param>
  76. for (var i = 0; i < arr.length; i++) {
  77. if (arr[i] == element) {
  78. return i;
  79. }
  80. }
  81. return -1;
  82. }
  83. function ArrayMax(arr) {
  84. /// <summary>Gets the maximum value of the specified array.</summary>
  85. if (arr.length === 0) {
  86. return undefined;
  87. }
  88. var result = arr[0];
  89. for (var i = 1; i < arr.length; i++) {
  90. if (arr[i] > result) {
  91. result = arr[i];
  92. }
  93. }
  94. return result;
  95. }
  96. function ArraySelect(arr, selector) {
  97. /// <summary>Invokes a selector callback for each element in the array.</summary>
  98. /// <param name="arr" type="Array">Array to operate on.</param>
  99. /// <param name="callback" type="Function">Function to invoke with element and index.</param>
  100. /// <returns type="Array">Array of selections for the arr element.</returns>
  101. var result = [];
  102. for (var i = 0; i < arr.length; i++) {
  103. result.push(selector(arr[i], i));
  104. }
  105. return result;
  106. }
  107. function ArraySelectMany(arr, selector) {
  108. /// <summary>Invokes a selector callback for each element in the array to produce multiple results.</summary>
  109. /// <param name="arr" type="Array">Array to operate on.</param>
  110. /// <param name="callback" type="Function">Function to invoke with element and index.</param>
  111. /// <returns type="Array">Array of flattened selections for the arr element.</returns>
  112. var result = [];
  113. for (var i = 0; i < arr.length; i++) {
  114. var selectorArr = selector(arr[i], i);
  115. if (selectorArr) {
  116. for (var j = 0; j < selectorArr.length; j++) {
  117. result.push(selectorArr[j]);
  118. }
  119. }
  120. }
  121. return result;
  122. }
  123. function ArraySelectMember(arr, memberName) {
  124. /// <summary>Invokes a selector callback for each element in the array.</summary>
  125. /// <param name="arr" type="Array">Array to operate on.</param>
  126. /// <param name="memberName" type="String">Member name to select from each array element.</param>
  127. /// <returns type="Array">Array of members for the arr elements.</returns>
  128. var result = [];
  129. for (var i = 0; i < arr.length; i++) {
  130. result.push(arr[i][memberName]);
  131. }
  132. return result;
  133. }
  134. function ArraySort(arr, comparer) {
  135. /// <summary>Adds the values in the array.</summary>
  136. /// <param name="arr" type="Array">Array to operate on.</param>
  137. /// <returns type="Number">Sum of the arr elements.</returns>
  138. var result = arr.slice(0);
  139. result.sort(comparer);
  140. return result;
  141. }
  142. function ArraySum(arr) {
  143. /// <summary>Adds the values in the array.</summary>
  144. /// <param name="arr" type="Array">Array to operate on.</param>
  145. /// <returns type="Number">Sum of the arr elements.</returns>
  146. var result = 0;
  147. for (var i = 0; i < arr.length; i++) {
  148. if (arr[i]) {
  149. result += arr[i];
  150. }
  151. }
  152. return result;
  153. }
  154. function ArrayTake(arr, count) {
  155. /// <summary>Returns the first count elements (or the original array if it has less than count elements.</summary>
  156. if (arr.length < count) {
  157. return arr;
  158. }
  159. return arr.slice(0, count);
  160. }
  161. function ArrayWhere(arr, callback) {
  162. /// <summary>Returns the elements in an array that satisfy a predicate.</summary>
  163. /// <param name="arr" type="Array">Array to operate on.</param>
  164. /// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param>
  165. /// <returns type="Array">Array of elements from arr that satisfy the predicate.</returns>
  166. var result = [];
  167. for (var i = 0; i < arr.length; i++) {
  168. if (callback(arr[i], i)) {
  169. result.push(arr[i]);
  170. }
  171. }
  172. return result;
  173. }
  174. function CheckScriptFlag(name) {
  175. /// <summary>Checks whether a script argument was given with true or false.</summary>
  176. /// <param name="name" type="String">Argument name to check.</param>
  177. /// <returns type="Boolean">
  178. /// true if the argument was given witha value of 'true' or 'True'; false otherwise.
  179. /// </returns>
  180. var flag = WScript.Arguments.Named(name);
  181. if (!flag) {
  182. return false;
  183. }
  184. return flag === "true" || flag === "True";
  185. }
  186. function CreateFolderIfMissing(path) {
  187. /// <summary>Creates a folder if it doesn't exist.</summary>
  188. /// <param name="path" type="String">Path to folder to create.</param>
  189. /// <remarks>This function will write out to the console on creation.</remarks>
  190. if (!path) return;
  191. var parent = PathGetDirectory(path);
  192. var fso = new ActiveXObject("Scripting.FileSystemObject");
  193. if (!fso.FolderExists(parent)) {
  194. CreateFolderIfMissing(parent);
  195. }
  196. if (!fso.FolderExists(path)) {
  197. WScript.Echo("Creating " + path + "...");
  198. fso.CreateFolder(path);
  199. }
  200. }
  201. function CompareValues(left, right) {
  202. if (left === right) return 0;
  203. if (left < right) return -1;
  204. return 1;
  205. }
  206. function CompareValuesAsStrings(left, right) {
  207. if (left === right) return 0;
  208. left = (left === null) ? "" : left.toString();
  209. right = (right === null) ? "" : right.toString();
  210. if (left === right) return 0;
  211. if (left < right) return -1;
  212. return 1;
  213. }
  214. function DbValueToString(value) {
  215. /// <summary>Returns a string representation for a database value.</summary>
  216. /// <param name="value">Value from database.</param>
  217. /// <returns type="String">A string representing the specified value.</returns>
  218. if (value === null || value === undefined) {
  219. return "NULL";
  220. }
  221. return value.toString();
  222. }
  223. function DeleteFile(path, force) {
  224. /// <summary>Deletes a file.</summary>
  225. /// <param name="path" type="String">Path to the file.</param>
  226. /// <param name="force" type="Boolean">Whether to delete the file even if it has the read-only attribute set.</param>
  227. var fso = new ActiveXObject("Scripting.FileSystemObject");
  228. fso.DeleteFile(path, force);
  229. }
  230. function DeleteFolder(path, force) {
  231. /// <summary>Deletes a folder.</summary>
  232. /// <param name="path" type="String">Path to the folder.</param>
  233. /// <param name="force" type="Boolean">Whether to delete the folder even if it has the read-only attribute set.</param>
  234. var fso = new ActiveXObject("Scripting.FileSystemObject");
  235. fso.DeleteFolder(path, force);
  236. }
  237. function CopyFolder(source, dest, overwrite) {
  238. /// <summary>Recursively copies a folder and its contents from source to dest.</summary>
  239. /// <param name="source" type="String">Path to the source folder location.</param>
  240. /// <param name="dest" type="String">Path to the destination folder location.</param>
  241. /// <param name="overwrite" type="Boolean">Whether to overwrite a folder in the destination location.</param>
  242. var fso = new ActiveXObject("Scripting.FileSystemObject");
  243. fso.CopyFolder(source, dest, overwrite);
  244. }
  245. function CopyFile(source, dest, overwrite) {
  246. /// <summary>Copies a file from source to dest.</summary>
  247. /// <param name="source" type="String">Path to the source file location.</param>
  248. /// <param name="dest" type="String">Path to the destination file location.</param>
  249. /// <param name="overwrite" type="Boolean">Whether to overwrite a file in the destination location.</param>
  250. var fso = new ActiveXObject("Scripting.FileSystemObject");
  251. if (overwrite && fso.FileExists(dest)) {
  252. var f = fso.getFile(dest);
  253. f.attributes = 0;
  254. }
  255. fso.CopyFile(source, dest, overwrite);
  256. }
  257. function ExpandEnvironmentVariables(name) {
  258. /// <summary>
  259. /// Replaces the name of each environment variable embedded in the specified string with the
  260. /// string equivalent of the value of the variable, then returns the resulting string.
  261. /// </summary>
  262. /// <param name="name" type="String">
  263. /// A string containing the names of zero or more environment variables. Each environment variable is quoted with the percent sign character (%).
  264. /// </param>
  265. /// <returns type="String">A string with each environment variable replaced by its value.</returns>
  266. var shell = new ActiveXObject("WScript.Shell");
  267. var result = shell.ExpandEnvironmentStrings(name);
  268. return result;
  269. }
  270. function ExtractContentsBetweenMarkers(path, contentOnly, isExclusion, startMarker, endMarker, callback) {
  271. /// <summary>
  272. /// Extracts the lines from the 'path' text file between the start and end markers.
  273. /// </summary>
  274. /// <param name="path" type="String">Path to file.</param>
  275. /// <param name="contentOnly" type="Boolean">
  276. /// true to skip everything until it's found between markers, false to start including everything from the start.
  277. /// </param>
  278. /// <param name="isExclusion" type="Boolean">
  279. /// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
  280. /// </param>
  281. /// <param name="startMarker" type="String">Line content to match for content start.</param>
  282. /// <param name="endMarker" type="String">Line content to match for content end.</param>
  283. /// <param name="callback" type="Function" mayBeNull="true">
  284. /// If true, then this function is called for every line along with the inContent flag
  285. /// before the line is added; the called function may return a line
  286. /// to be added in its place, null to skip processing.
  287. /// </param>
  288. /// <returns type="String">The string content of the file.</returns>
  289. var content = ReadAllTextFile(path);
  290. return ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback);
  291. }
  292. function ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback) {
  293. /// <summary>
  294. /// Extracts the lines from the specified text between the start and end markers.
  295. /// </summary>
  296. /// <param name="content" type="String">Text to process.</param>
  297. /// <param name="contentOnly" type="Boolean">
  298. /// true to skip everything until it's found between markers, false to start including everything from the start.
  299. /// </param>
  300. /// <param name="isExclusion" type="Boolean">
  301. /// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
  302. /// </param>
  303. /// <param name="startMarker" type="String">Line content to match for content start.</param>
  304. /// <param name="endMarker" type="String">Line content to match for content end.</param>
  305. /// <param name="callback" type="Function" mayBeNull="true">
  306. /// If true, then this function is called for every line along with the inContent flag
  307. /// before the line is added; the called function may return a line
  308. /// to be added in its place, null to skip processing.
  309. /// </param>
  310. /// <returns type="String">The extracted content.</returns>
  311. var inContent = contentOnly === false;
  312. var lines = StringSplit(content, "\r\n");
  313. var result = [];
  314. var i, len;
  315. for (i = 0, len = lines.length; i < len; i++) {
  316. var line = lines[i];
  317. var contentStartIndex = line.indexOf(startMarker);
  318. if (inContent === false && contentStartIndex !== -1) {
  319. inContent = true;
  320. continue;
  321. }
  322. var contentEndIndex = line.indexOf(endMarker);
  323. if (inContent === true && contentEndIndex !== -1) {
  324. inContent = false;
  325. continue;
  326. }
  327. if (callback) {
  328. var callbackResult = callback(line, inContent);
  329. if (callbackResult !== null && callbackResult !== undefined) {
  330. result.push(callbackResult);
  331. }
  332. } else {
  333. if (inContent && !isExclusion) {
  334. result.push(line);
  335. } else if (!inContent && isExclusion) {
  336. result.push(line);
  337. }
  338. }
  339. }
  340. return result.join("\r\n");
  341. }
  342. function FolderExists(path) {
  343. /// <summary>Checks whether the specified directory exists.</summary>
  344. var fso = new ActiveXObject("Scripting.FileSystemObject");
  345. if (fso.FolderExists(path)) {
  346. return true;
  347. }
  348. else {
  349. return false;
  350. }
  351. }
  352. function FileExists(path) {
  353. /// <summary>Checks whether the specified file exists.</summary>
  354. var fso = new ActiveXObject("Scripting.FileSystemObject");
  355. if (fso.FileExists(path)) {
  356. return true;
  357. }
  358. else {
  359. return false;
  360. }
  361. }
  362. function GetEnvironmentVariable(name) {
  363. /// <summary>Gets the value of the specified environment variable.</summary>
  364. /// <param name="name" type="String">Name of the variable value to get.</param>
  365. /// <returns type="String">Value for the given environment variable; null if undefined.</returns>
  366. var shell = new ActiveXObject("WScript.Shell");
  367. var result = shell.ExpandEnvironmentStrings("%" + name + "%");
  368. if (result == "%" + name + "%") {
  369. result = null;
  370. }
  371. return result;
  372. }
  373. function GetFilesRecursive(path) {
  374. /// <summary>Gets all file names under the specified directory path.</summary>
  375. /// <param name="path" type="String">Path to directory.</param>
  376. /// <returns type="Array">Array of all file names under path.</returns>
  377. var result = [];
  378. var fso = new ActiveXObject("Scripting.FileSystemObject");
  379. var pending = [path];
  380. while (pending.length) {
  381. var item = pending.pop();
  382. var folder = fso.GetFolder(item);
  383. for (var files = new Enumerator(folder.Files); !files.atEnd(); files.moveNext()) {
  384. result.push(files.item().Path);
  385. }
  386. for (var subFolders = new Enumerator(folder.SubFolders); !subFolders.atEnd(); subFolders.moveNext()) {
  387. pending.push(subFolders.item().Path);
  388. }
  389. }
  390. return result;
  391. }
  392. function GetRelativePathFrom(startPath, endPath) {
  393. if (startPath[startPath.length - 1] !== "\\") {
  394. startPath += "\\";
  395. }
  396. if (startPath.length > endPath.length) {
  397. throw { message: "traversing up NYI" };
  398. }
  399. return endPath.substr(startPath.length);
  400. }
  401. function MatchesMask(file, mask) {
  402. if (!mask) {
  403. return false;
  404. }
  405. if (file === mask) {
  406. return true;
  407. }
  408. if (mask.substr(0, 1) === "*") {
  409. var rest = mask.substr(1);
  410. return file.substr(file.length - rest.length) === rest;
  411. } else if (mask.substr(mask.length - 1) === "*") {
  412. var end = mask.substr(0, mask.length - 1);
  413. return file.substr(0, end.length) === end;
  414. }
  415. return false;
  416. }
  417. function OpenCsvConnection(path) {
  418. /// <summary>Opens an ADO Connection object to the directory path where CSV files are found.</summary>
  419. /// <param name="path" type="String">Directory path where .csv files are.</param>
  420. /// <returns type="ADODB.Connection">An open connection.</returns>
  421. var connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
  422. "Data Source=" + path + ";" +
  423. "Extended Properties=\"text;HDR=YES;FMT=Delimited\"";
  424. var objConnection = WScript.CreateObject("ADODB.Connection");
  425. objConnection.Open(connectionString);
  426. return objConnection;
  427. }
  428. function OpenSqlCeConnection(path) {
  429. /// <summary>Opens an ADO Connection object to a SQL CE file.</summary>
  430. /// <param name="path" type="String">File path for .sdf file.</param>
  431. /// <returns type="ADODB.Connection">An open connection.</returns>
  432. var connectionString = "Provider=Microsoft.SQLSERVER.CE.OLEDB.4.0;" +
  433. "Data Source=" + path + ";";
  434. var objConnection = WScript.CreateObject("ADODB.Connection");
  435. objConnection.Open(connectionString);
  436. return objConnection;
  437. }
  438. function PathGetDirectory(path) {
  439. /// <summary>
  440. /// Returns the directory of the specified path string (excluding the trailing "\\");
  441. /// empty if there is no path.
  442. /// </summary>
  443. var l = path.length;
  444. var startIndex = l;
  445. while (--startIndex >= 0) {
  446. var ch = path.substr(startIndex, 1);
  447. if (ch == "\\") {
  448. if (startIndex === 0) {
  449. return "";
  450. } else {
  451. return path.substr(0, startIndex);
  452. }
  453. }
  454. }
  455. return "";
  456. }
  457. function PathGetFileName(path) {
  458. /// <summary>
  459. /// Returns the file name for the specified path string; empty if there is no
  460. /// directory information.
  461. /// </summary>
  462. var l = path.length;
  463. var startIndex = l;
  464. while (--startIndex >= 0) {
  465. var ch = path.substr(startIndex, 1);
  466. if (ch == "\\" || ch == "/" || ch == ":") {
  467. return path.substr(startIndex + 1);
  468. }
  469. }
  470. return "";
  471. }
  472. function PathGetExtension(path) {
  473. /// <summary>
  474. /// Returns the extension of the specified path string (including the ".");
  475. /// empty if there is no extension.
  476. /// </summary>
  477. /// <returns type="String">The extension of the specified path, including the '.'.</returns>
  478. var l = path.length;
  479. var startIndex = l;
  480. while (--startIndex >= 0) {
  481. var ch = path.substr(startIndex, 1);
  482. if (ch == ".") {
  483. if (startIndex != (l - 1)) {
  484. return path.substr(startIndex, l - startIndex);
  485. }
  486. return "";
  487. }
  488. else if (ch == "\\" || ch == ":") {
  489. break;
  490. }
  491. }
  492. return "";
  493. }
  494. function ReadAllTextFile(path) {
  495. /// <summary>Reads all the content of the file into a string.</summary>
  496. /// <param name="path" type="String">File name to read from.</param>
  497. /// <returns type="String">File contents.</returns>
  498. var ForReading = 1, ForWriting = 2;
  499. var fso = new ActiveXObject("Scripting.FileSystemObject");
  500. var file = fso.OpenTextFile(path, ForReading);
  501. try {
  502. var result;
  503. if (file.AtEndOfStream) {
  504. result = "";
  505. } else {
  506. result = file.ReadAll();
  507. }
  508. } finally {
  509. file.Close();
  510. }
  511. return result;
  512. }
  513. function ReadXmlFile(path) {
  514. /// <summary>Reads an XML document from the specified path.</summary>
  515. /// <param name="path" type="String">Path to file on disk.</param>
  516. /// <returns>A DOMDocument with the contents of the given file.</returns>
  517. var result = new ActiveXObject("Msxml2.DOMDocument.6.0");
  518. result.async = false;
  519. result.load(path);
  520. if (result.parseError.errorCode !== 0) {
  521. throw { message: "Error reading '" + path + "': " + result.parseError.reason };
  522. }
  523. return result;
  524. }
  525. // Runs the specified function catching exceptions and quits the current script.
  526. function RunAndQuit(f) {
  527. try {
  528. f();
  529. }
  530. catch (e) {
  531. // An error with 'statusCode' defined will avoid the usual error dump handling.
  532. if (e.statusCode !== undefined) {
  533. if (e.message) {
  534. WScript.Echo(e.message);
  535. }
  536. WScript.Quit(e.statusCode);
  537. }
  538. WScript.Echo("Error caught while running this function:");
  539. WScript.Echo(f.toString());
  540. WScript.Echo("Error details:");
  541. if (typeof (e) == "object" && e.toString() == "[object Object]" || e.toString() === "[object Error]") {
  542. for (var p in e) WScript.Echo(" " + p + ": " + e[p]);
  543. }
  544. else {
  545. WScript.Echo(e);
  546. }
  547. WScript.Quit(1);
  548. }
  549. WScript.Quit(0);
  550. }
  551. function RunConsoleCommand(strCommand, timeout, retry) {
  552. /// <summary>Runs a command and waits for it to exit.</summary>
  553. /// <param name="strCommand" type="String">Command to run.</param>
  554. /// <param name="timeout" type="int">Timeout in seconds.</param>
  555. /// <param name="timeout" type="bool">Boolean specifying whether to retry on timeout or not.</param>
  556. /// <returns type="Array">
  557. /// An array with stdout in 0, stderr in 1 and exit code in 2. Forced
  558. /// termination sets the exit code to 1.
  559. /// </returns>
  560. // WScript.Echo("running [" + strCommand + "]");
  561. var WshShell = new ActiveXObject("WScript.Shell");
  562. var result = new Array(3);
  563. var oExec = WshShell.Exec(strCommand);
  564. var counter = 0;
  565. if (timeout) {
  566. // Status of 0 means the process is still running
  567. while (oExec.Status === 0 && counter < timeout) {
  568. WScript.Sleep(1000);
  569. counter++;
  570. }
  571. if (timeout === counter && oExec.Status === 0) {
  572. WScript.Echo("Forcefully terminating " + strCommand + " after " + timeout + " seconds.");
  573. oExec.Terminate();
  574. result[2] = 1;
  575. if (retry) {
  576. return RunConsoleCommand(strCommand, timeout, false);
  577. }
  578. }
  579. }
  580. result[0] = oExec.StdOut.ReadAll();
  581. result[1] = oExec.StdErr.ReadAll();
  582. if (!result[2]) {
  583. result[2] = oExec.ExitCode;
  584. }
  585. // WScript.Echo(" stdout: " + result[0]);
  586. // WScript.Echo(" stderr: " + result[1]);
  587. // WScript.Echo(" exit code: " + result[2]);
  588. return result;
  589. }
  590. function Say(text) {
  591. /// <summary>Uses the Speech API to speak to the user.</summary>
  592. var voice = new ActiveXObject("SAPI.SpVoice");
  593. try {
  594. voice.Speak(text);
  595. } catch (e) {
  596. // See http://msdn2.microsoft.com/en-us/library/ms717306.aspx for error codes.
  597. // SPERR_DEVICE_BUSY 0x80045006 -2147201018
  598. if (e.number == -2147201018) {
  599. WScript.Echo("The wave device is busy.");
  600. WScript.Echo("Happens sometimes over Terminal Services.");
  601. }
  602. }
  603. }
  604. function SaveTextToFile(content, path) {
  605. /// <summary>Saves text content into a file.</summary>
  606. /// <param name="content" type="String">Content to save.</param>
  607. /// <param name="path" type="String">Path of file to save into.</param>
  608. var ForReading = 1, ForWriting = 2;
  609. var fso = new ActiveXObject("Scripting.FileSystemObject");
  610. var file = fso.OpenTextFile(path, ForWriting, true);
  611. file.Write(content);
  612. file.Close();
  613. }
  614. function SelectLength(value) {
  615. return value.length;
  616. }
  617. function SendMicrosoftMail(subject, text, toAddress) {
  618. var shell = new ActiveXObject("WScript.Shell");
  619. var userName = shell.ExpandEnvironmentStrings("%username%");
  620. var fromAddress = userName + "@microsoft.com";
  621. var server = "smtphost.redmond.corp.microsoft.com";
  622. if (!toAddress) {
  623. toAddress = fromAddress;
  624. }
  625. var message = new ActiveXObject("CDO.Message");
  626. var configuration = message.Configuration;
  627. // 2 = cdoSendUsingPort; 2 = cdoNTLM
  628. configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
  629. configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = server;
  630. configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 2;
  631. configuration.Fields.Update();
  632. message.To = toAddress;
  633. message.From = fromAddress;
  634. message.Subject = subject;
  635. message.TextBody = text;
  636. message.Send();
  637. }
  638. function StringBetween(text, startMarker, endMarker) {
  639. /// <summary>Returns the text between startMarker and endMarker in text, null if not found.</summary>
  640. var startIndex = text.indexOf(startMarker);
  641. if (startIndex == -1) return null;
  642. var endIndex = text.indexOf(endMarker, startIndex + startMarker.length);
  643. if (endIndex == -1) return null;
  644. return text.substring(startIndex + startMarker.length, endIndex);
  645. }
  646. function StringPadRight(value, length, padString) {
  647. /// <summary>Returns a padded string.</summary>
  648. /// <param name="value" type="String">Value to pad.</param>
  649. /// <param name="length" type="Number" integer="true">Target length for string.</param>
  650. /// <param name="padString" type="String" optional="true">Optional string to pad with; defaults to space.</param>
  651. /// <returns type="String">The padded string.</returns>
  652. if (!padString) padString = " ";
  653. if (value.length < length) {
  654. value = value + Array(length + 1 - value.length).join(padString);
  655. }
  656. return value;
  657. }
  658. function StringToLower(text) {
  659. /// <summary>Returns the lowercase form of the specified string.</summary>
  660. /// <param name="text" type="String">Value to lower.</param>
  661. /// <returns type="String">The lowercase value.</returns>
  662. if (text) {
  663. return text.toLowerCase();
  664. } else {
  665. return text;
  666. }
  667. }
  668. function StringSplit(strLine, strSeparator) {
  669. /// <summary>Splits a string into a string array.</summary>
  670. var result = new Array();
  671. var startIndex = 0;
  672. var resultIndex = 0;
  673. while (startIndex < strLine.length) {
  674. var endIndex = strLine.indexOf(strSeparator, startIndex);
  675. if (endIndex == -1) {
  676. endIndex = strLine.length;
  677. }
  678. result[resultIndex] = strLine.substring(startIndex, endIndex);
  679. startIndex = endIndex + strSeparator.length;
  680. resultIndex++;
  681. }
  682. return result;
  683. }
  684. function StringTrim(text) {
  685. var result = text.replace(/^\s*/, "").replace(/\s*$/, "");
  686. return result
  687. }
  688. function PathCombine(path1, path2) {
  689. if (path1.charAt(path1.length - 1) !== "\\") {
  690. return path1 + "\\" + path2;
  691. }
  692. return path1 + path2;
  693. }
  694. function RemoveReadOnlyAttribute(path) {
  695. /// <summary>Removes the read-only attribute on the specified file.</summary>
  696. /// <param name="path" type="String">Path to the file.</param>
  697. var fso = new ActiveXObject("Scripting.FileSystemObject");
  698. var f = fso.getFile(path);
  699. if (1 === (f.attributes & 1)) {
  700. f.attributes = (f.attributes & ~1);
  701. }
  702. }
  703. function RunWmiQuery(query) {
  704. /// <summary>Runs a WMI query and returns all objects.</summary>
  705. /// <param name="query" type="String">Query to run.</param>
  706. /// <returns type="Array">Array with results.</returns>
  707. var result = [];
  708. var wmiService = GetObject("winmgmts:\\\\.\\root\\cimv2");
  709. var items = wmiService.ExecQuery(query);
  710. var e = new Enumerator(items);
  711. while (!e.atEnd()) {
  712. result.push(e.item());
  713. e.moveNext();
  714. }
  715. return result;
  716. }
  717. function WriteRecordSetToTextStreamAsAsciiTable(objRecordSet, stream) {
  718. /// <summary>Writes all content of the specified ADO RecordSet into the given text stream.</summary>
  719. /// <param name="objRecordSet">RecordSet to write out to.</param>
  720. /// <param name="stream">Optional TextStream to write to; defaults to WScript.Out.</param>
  721. var outStream = (stream) ? stream : WScript.StdOut;
  722. var fields = objRecordSet.Fields;
  723. var columns = new Array(fields.Count);
  724. var rowCount = 1;
  725. for (var i = 0; i < fields.Count; i++) {
  726. columns[i] = [];
  727. columns[i].push(fields.Item(i).Name);
  728. }
  729. while (!objRecordSet.EOF) {
  730. for (var i = 0; i < fields.Count; i++) {
  731. columns[i].push(DbValueToString(fields.Item(i).Value));
  732. }
  733. ++rowCount;
  734. objRecordSet.MoveNext();
  735. }
  736. var columnSizes = new Array(columns.length);
  737. for (var i = 0; i < columns.length; ++i) {
  738. var valueLengths = ArraySelect(columns[i], SelectLength);
  739. columnSizes[i] = ArrayMax(valueLengths);
  740. }
  741. for (var rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
  742. for (var i = 0; i < columnSizes.length; ++i) {
  743. outStream.Write(StringPadRight(columns[i][rowIndex], 1 + columnSizes[i]));
  744. }
  745. outStream.WriteLine();
  746. if (rowIndex === 0) {
  747. for (var i = 0; i < columnSizes.length; ++i) {
  748. outStream.Write(StringPadRight("", columnSizes[i], "-"));
  749. outStream.Write(" ");
  750. }
  751. outStream.WriteLine();
  752. }
  753. }
  754. }
  755. function WriteRecordSetToTextStream(objRecordSet, separator, stream) {
  756. /// <summary>Writes all content of the specified ADO RecordSet into the given text stream.</summary>
  757. /// <param name="objRecordSet">RecordSet to write out to.</param>
  758. /// <param name="separator" type="String">Text between fields.</param>
  759. /// <param name="stream">Optional TextStream to write to; defaults to WScript.Out.</param>
  760. var outStream = (stream) ? stream : WScript.StdOut;
  761. var fields = objRecordSet.Fields;
  762. for (var i = 0; i < fields.Count; i++) {
  763. if (i > 0) outStream.Write(separator);
  764. outStream.Write(fields.Item(i).Name);
  765. }
  766. outStream.WriteLine();
  767. while (!objRecordSet.EOF) {
  768. for (var i = 0; i < fields.Count; i++) {
  769. if (i > 0) outStream.Write(separator);
  770. outStream.Write(fields.Item(i).Value);
  771. }
  772. outStream.WriteLine();
  773. objRecordSet.MoveNext();
  774. }
  775. }
  776. function WriteXmlFile(document, path) {
  777. /// <summary>Write an XML document to the specified path.</summary>
  778. /// <param name="path" type="String">Path to file on disk.</param>
  779. document.save(path);
  780. }