//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // System wide constants. // These constants are not expected to change. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var CLASSID_MTSCRIPT = "{854c316d-c854-4a77-b189-606859e4391b}"; Error.prototype.toString = Error_ToString; Object.prototype.toString = Object_ToString; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Global constants // These are subject to change and tuning. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var g_aProcsToKill = ["mtscript.exe", "mshta.exe", "build.exe", "nmake.exe", "mtodaemon.exe"]; // "sleep.exe" is also killed seperately. // The lists of files to copy. // g_aCopyBCDistDir and g_aCopyBCDistDirD are the set of files which are in the same directory as this // script is, and are necessary for the operation of bcdist itself. // The g_aCopyBCDistDirD files are optional and are only necessary for running a debug MTScript.exe var g_aCopyBCDistDirScript = ['registermtscript.cmd']; var g_aCopyBCDistDir = ['jscript.dll', 'bcrunas.exe', 'sleep.exe']; var g_aCopyBCDistDirD = ['mshtmdbg.dll', 'msvcrtd.dll']; // The g_aCopyFromScripts files are the Build Console Scripts. // These files are copied from either the current directory or .\mtscript var g_aCopyFromScripts = [ 'buildreport.js', 'harness.js', 'master.js', 'msgqueue.js', 'mtscript.js', 'publicdataupdate.js', 'robocopy.js', 'sendmail.js', 'slave.js', 'slaveproxy.js', 'slavetask.js', 'staticstrings.js', 'task.js', 'types.js', 'updatestatusvalue.js', 'utils.js', 'utilthrd.js', 'config_schema.xml', 'enviro_schema.xml' ]; // The g_aCopyFromBin files are the Build Console executable files. // These files are copied from either the current directory or .\%ARCH% (x86, axp64,...) var g_aCopyFromBin = [ 'mtscript.exe', 'mtlocal.dll', 'mtscrprx.dll', 'mtrcopy.dll', "mtodaemon.exe", "mtodproxy.dll"]; var g_strDropServer = "\\\\ptt\\cftools\\test\\bcrel"; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Global Variables //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var g_strMyLocation; var g_objNet; var g_strLocalHost; var g_objFS; var g_strShareDir; var g_Opts; if (DoLocalSetup()) { g_Opts = ParseArguments(new DefaultArguments()); if (g_Opts) { if (main(g_Opts)) WScript.Quit(0); } } WScript.Quit(1); // GetMachineList(objArgs) // // // // Reads the XML BC environment template to extract the // // list of machines in the build. // // // function GetMachineList(objArgs) { var xml = new ActiveXObject('Microsoft.XMLDOM'); var node; var nodelist; var objMach; var nIndex; xml.async = false; // It's unlikely they have the schema file available for this template, // so we turn off schema validation right now. The script engine will // validate it when we start the build. xml.validateOnParse = false; xml.resolveExternals = false; if (!xml.load(objArgs.strXMLFile) || !xml.documentElement) { Usage("Not a valid xml file: " + objArgs.strXMLFile); } node = xml.documentElement.selectSingleNode('BuildManager'); if (!node) { Usage("Not a valid xml file: " + objArgs.strXMLFile); } objArgs.aMachines[0] = new MachineInfo(node.getAttribute("Name")); objArgs.aMachines[0].WriteStatusInfo("Initializing"); nodelist = xml.documentElement.selectNodes('Machine'); for (node = nodelist.nextNode(); node; node = nodelist.nextNode()) { // Don't initialize the build manager machine twice // just because it is also used in the building process if ( objArgs.aMachines[0].strName.toLowerCase() == node.getAttribute("Name").toLowerCase() ) continue; nIndex = objArgs.aMachines.length; objArgs.aMachines[nIndex] = new MachineInfo(node.getAttribute("Name")); objArgs.aMachines[nIndex].WriteStatusInfo("Initializing"); } } // GetStringArgument(objArgs, strMember) // // // // Helper function for ParseArguments. Stores the // // next argument in the "strMember" member of "objArgs". // // Exits script with Usage() if there is no available argument. // function GetStringArgument(objArgs, strMember) { if (objArgs[strMember] == null) { LogMsg("ParseArguments internal error: Unknown member: " + strMember); WScript.Quit(1); } objArgs.argn++; if (objArgs.argn < objArgs.objArguments.length) objArgs[strMember] = objArgs.objArguments(objArgs.argn); else Usage("missing paramter"); } function ParseArguments(objArgs) { var strArg; var chArg0; var chArg1; var nIndex; var fMachineList = false; for(objArgs.argn = 0; objArgs.argn < objArgs.objArguments.length; objArgs.argn++) { strArg = objArgs.objArguments(objArgs.argn); chArg0 = strArg.charAt(0); chArg1 = strArg.toLowerCase().slice(1); if (chArg0 != '-' && chArg0 != '/') { if (objArgs.strXMLFile != '') { Usage("Enter an XML file or a list of the machines but not both"); } else { fMachineList = true; nIndex = objArgs.aMachines.length; objArgs.aMachines[nIndex] = new MachineInfo(strArg); objArgs.aMachines[nIndex].WriteStatusInfo("Initializing"); } } else { // Currently, no options switch(chArg1) { case 'v': objArgs.fVerbose = true; break; case 'd': objArgs.argn++; if (objArgs.argn < objArgs.objArguments.length) { if (objArgs.strSrcDir == '') objArgs.nDropNum = Number(objArgs.objArguments(objArgs.argn)); else Usage("Only one of -src and -d may be specified"); } else Usage("missing parameter for -d arugment"); if (objArgs.nDropNum < 1000 || objArgs.nDropNum >= 10000) Usage("dropnum range is 1000...9999"); break; case 'dropsrc': GetStringArgument(objArgs, "strDropSrc"); break; case 'src': GetStringArgument(objArgs, "strSrcDir"); break; case 'dst': GetStringArgument(objArgs, "strDstDir"); break; case 'u': GetStringArgument(objArgs, "strUserName"); if (objArgs.strUserName == '*') { objArgs.strUserName = g_objNet.UserDomain + '\\' + g_objNet.UserName; } break; case 'p': GetStringArgument(objArgs, "strPassword"); break; case 'arch': GetStringArgument(objArgs, "strArch"); break; case 'f': // Entered an XML file on the command line. Get the list of machines from here. if (fMachineList) Usage("Enter an XML file or a list of the machines but not both"); GetStringArgument(objArgs, "strXMLFile"); GetMachineList(objArgs); nIndex = objArgs.aMachines.length; break; case 'debug': objArgs.strExeType = 'debug'; break; default: Usage("Unknown argument: " + strArg); break; } } } if (objArgs.aMachines.length == 0) Usage("you must specify one or more machine names or an XML file"); if (objArgs.nDropNum) objArgs.strSrcDir = objArgs.strDropSrc + "\\" + objArgs.nDropNum; else if (objArgs.strSrcDir == '') Usage("you must specify a drop number or source location"); if (objArgs.strUserName == '' || objArgs.strPassword == '') Usage("username and password required"); delete objArgs.objArguments; delete objArgs.argn; return objArgs; } function Usage(strError) { WScript.Echo(''); WScript.Echo('Usage: BCDist -u domain\\username -p password '); WScript.Echo(' [-v] [-d nnnn [-dropsrc path] | -src path] '); WScript.Echo(' [-dst path] [-arch x86] [-debug] machines...'); WScript.Echo(' -u d\\u = domain\\username'); WScript.Echo(' -f xmlFile = environment xml template'); WScript.Echo(' -p passwd = password'); WScript.Echo(' -v = verbose'); WScript.Echo(' -d = drop number'); WScript.Echo(' -dropsrc = drop source location ("' + g_strDropServer + '")'); WScript.Echo(' -src = source directory'); WScript.Echo(' -dst = destination directory'); WScript.Echo(' -arch = Specifiy x86 or alpha'); WScript.Echo(' -debug = copy debug exes instead of retail'); if (strError && strError != '') { WScript.Echo(''); WScript.Echo('Error: ' + strError); } WScript.Quit(1); } // DefaultArguments() // // // // Create an options object with the default // // options filled in. // function DefaultArguments() { var obj = { objArguments:WScript.Arguments, argn:0, aMachines:new Array(), fVerbose:false, nDropNum:0, strDropSrc:g_strDropServer, strSrcDir:'', strDstDir:'', strArch:"x86", strExeType:"retail", strUserName:'', strPassword:'', strXMLFile:'' }; return obj; } // DoLocalSetup() // // // // Setup some globals. Necessary before arugment parsing // // can succeed. // // // function DoLocalSetup() { var i = -1; var objFile; var strPath; var objLogin; var objRemote; try { g_objNet = WScript.CreateObject("WScript.Network"); g_strLocalHost = g_objNet.ComputerName; g_objFS = new FileSystemObject(); g_strMyLocation = SplitFileName(WScript.ScriptFullName)[0]; LogMsg("Creating local share..."); objLogin = { strMachine:g_strLocalHost } objRemote = new WMIInterface(objLogin, ''); g_strShareDir = g_strMyLocation + "bcdiststatus"; g_objFS.CreateFolder(g_strShareDir); strPath = objRemote.RemoteShareExists("BC_DISTSTATUS"); if (strPath != "") g_strShareDir = strPath; else objRemote.RemoteCreateShare("BC_DISTSTATUS", g_strShareDir, "Build Console Distribution Status"); } catch(ex) { LogMsg("BCDist failed to do local setup: " + ex); return false; } return true; } function main(objOpts) { var strPath; var strPathUNC; var fSuccess = true; var strDomain = objOpts.strUserName.split("\\")[0]; var strUser = objOpts.strUserName.split("\\")[1]; var fLocal; var strCmd; LogMsg("Upgrading the following machines:"); for(i = 0; i < objOpts.aMachines.length;++i) { LogMsg(" " + objOpts.aMachines[i].strName); } for(i = 0; i < objOpts.aMachines.length;++i) { fLocal = false; strCmd = ''; try { LogMsg("Distributing to " + objOpts.aMachines[i].strName); var objLogin = { strMachine:objOpts.aMachines[i].strName, strUser:objOpts.strUserName, // Unneccessary if the same as the current user. strPassword:objOpts.strPassword } if (objLogin.strMachine.toUpperCase() == g_objNet.ComputerName.toUpperCase()) { // On the local host you may not specify a username if (objLogin.strUser.toUpperCase() != (g_objNet.UserDomain + '\\' + g_objNet.UserName).toUpperCase()) throw new Error(-1, "Specified username does not match current login for local machine"); delete objLogin.strUser; delete objLogin.strPassword; fLocal = true; } objOpts.aMachines[i].WriteStatusInfo("Connecting"); var objRemote = new WMIInterface(objLogin, ''); var objRegistry = new WMIRegistry(objLogin); objOpts.aMachines[i].WriteStatusInfo("Terminating MTScript.exe"); LogMsg(" Terminating remote processes"); TerminateMTScript(objRemote, objRegistry); strPath = DetermineInstallPoint(objOpts, objRemote, objRegistry); strPathUNC = PathToUNC(objOpts.aMachines[i].strName, strPath); objOpts.aMachines[i].WriteStatusInfo("Copying files"); CopyFiles(objRemote, strPathUNC, objOpts); objOpts.aMachines[i].WriteStatusInfo("Creating share"); ResetRegistry(objRegistry, strPath); objOpts.aMachines[i].WriteStatusInfo("Registering"); objOpts.aMachines[i].DisableWriteStatusInfo(); LogMsg(" Registering"); // We don't use BCRunAs when running on the local machine. if (!fLocal) { // Usage: BCRunAs UserName Domain Password CWD Cmdline // strCmd = strPath + '\\BCRunAs.exe ' + strUser + ' ' + strDomain + ' "' + objOpts.strPassword + '" "'; } strCmd += 'cmd.exe /K ' + strPath + "\\RegisterMTScript.cmd " + g_strLocalHost; if (!fLocal) { strCmd += '"'; } objRemote.RemoteExecuteCmd(strCmd, strPath); // Do not write any more status after this point -- the remote machine should do it now. } catch(ex) { fSuccess = false; objOpts.aMachines[i].WriteStatusInfo("FAILED " + ex); } } if (! CheckStatus(objOpts) ) fSuccess = false; return fSuccess; } function CheckStatus(objOpts) { var i; var fTerminalState; var strStatus; var aStatus; var aState = new Array() var fChanged; LogMsg(""); LogMsg("Current status on the remote machines...(Press Ctrl-C to quit)"); do { fTerminalState = true; fChanged = false; for(i = 0; i < objOpts.aMachines.length;++i) { strStatus = objOpts.aMachines[i].ReadStatusInfo(); aStatus = strStatus.split(" "); if (aStatus.length == 0 || aStatus[0] != 'OK' && aStatus[0] != 'FAILED') fTerminalState = false; if (aState[i] == null || aState[i] != strStatus) { aState[i] = strStatus; fChanged = true; } } if (fChanged) { for(i = 0; i < objOpts.aMachines.length;++i) LogMsg(objOpts.aMachines[i].strName + ": " + aState[i]); if (!fTerminalState) LogMsg("Waiting..."); LogMsg(""); } if (!fTerminalState) WScript.Sleep(1000); } while(!fTerminalState); } // TerminateMTScript(objRemote, objRegistry) // // // // Using WMI, terminate processes which may be involved // // in a build. This is neccessary before a BC upgrade can happen. // // Also, remote "mtscript.exe" to prevent it getting restarted // // prematurely. // // // function TerminateMTScript(objRemote, objRegistry) { var i; var fRenamed = false; var strMTScriptPath = '' try { strMTScriptPath = objRegistry.GetExpandedStringValue(WMIRegistry.prototype.HKCR, "CLSID\\" + CLASSID_MTSCRIPT + "\\LocalServer32", ''); } catch(ex) { } if (strMTScriptPath != '') { if (objRemote.RemoteFileExists(strMTScriptPath + ".UpdateInProgress")) objRemote.RemoteDeleteFile(strMTScriptPath + ".UpdateInProgress"); if (objRemote.RemoteFileExists(strMTScriptPath) && objRemote.RemoteRenameFile(strMTScriptPath, strMTScriptPath + ".UpdateInProgress")) { fRenamed = true; } } for(i = 0; i < g_aProcsToKill.length; ++i) objRemote.RemoteTerminateExe(g_aProcsToKill[i], 1); objRemote.RemoteTerminateExe("sleep.exe", 0); // If sleep.exe sets ERRORLEVEL != 0, then the remote cmd.exe windows will not close. if (fRenamed) { for( i = 3; i >= 0; --i) { try { objRemote.RemoteDeleteFile(strMTScriptPath + ".UpdateInProgress"); } catch(ex) { if (i == 0) throw ex; WScript.Sleep(500); // It sometimes takes a little while for the remote mtscript.exe to quit. continue; } break; } } return true; } // DetermineInstallPoint(objOpts, objRemote, objRegistry) // // // // If the user has supplied a destination path, use that. // // Otherwise if mtscript.exe has previously been registered on the remote machine // // then install to the same location. // // Else, report an error. // function DetermineInstallPoint(objOpts, objRemote, objRegistry) { var strMTScriptPath = '' if (objOpts.strDstDir != '') return objOpts.strDstDir; try { strMTScriptPath = objRegistry.GetExpandedStringValue(WMIRegistry.prototype.HKCR, "CLSID\\" + CLASSID_MTSCRIPT + "\\LocalServer32", ''); } catch(ex) { } if (strMTScriptPath != '') strMTScriptPath = SplitFileName(strMTScriptPath)[0]; else throw new Error(-1, "-dst must be specified -- mtscript was not previously registered"); return strMTScriptPath; } // CopyFiles(objRemote, strDstPath, objOpts) // // // // Copy the necessary files to the remote machine. // // The files are always copied to a "flat" install -- the executables and the scripts // // and as the same directory level. // // The files in a daily drop are not flat - the executables and the // // scripts are in seperate directories. // function CopyFiles(objRemote, strDstPath, objOpts) { var i; var strSourcePath; var strDstPathUNC; var strAltLocation; strSourcePath = RemoveEndChar(objOpts.strSrcDir, "\\"); strDstPathUNC = RemoveEndChar(strDstPath, "\\"); Trace("Copy files from " + strSourcePath + " to " + strDstPathUNC); g_objFS.CreateFolder(strDstPathUNC); strAltLocation = strSourcePath + "\\" + objOpts.strArch; CopyListOfFiles(g_aCopyBCDistDirScript, g_strMyLocation, null, strDstPathUNC, true); if (objOpts.nDropNum) { LogMsg(" Copying files from drop " + strSourcePath); CopyListOfFiles(g_aCopyFromScripts, strSourcePath + "\\scripts", null, strDstPathUNC, true); CopyListOfFiles(g_aCopyBCDistDir, strSourcePath + "\\" + objOpts.strArch + "\\" + objOpts.strExeType, null, strDstPathUNC, true); CopyListOfFiles(g_aCopyBCDistDirD, strSourcePath + "\\" + objOpts.strArch + "\\" + objOpts.strExeType, null, strDstPathUNC, false); CopyListOfFiles(g_aCopyFromBin, strSourcePath + "\\" + objOpts.strArch + "\\" + objOpts.strExeType, null, strDstPathUNC, true); } else { LogMsg(" Copying files from " + strSourcePath); CopyListOfFiles(g_aCopyFromScripts, strSourcePath, strSourcePath + "\\mtscript", strDstPathUNC, true); CopyListOfFiles(g_aCopyBCDistDir, strSourcePath, strSourcePath + "\\" + objOpts.strArch, strDstPathUNC, true); CopyListOfFiles(g_aCopyBCDistDirD, strSourcePath, strSourcePath + "\\" + objOpts.strArch, strDstPathUNC, false); CopyListOfFiles(g_aCopyFromBin, strSourcePath, strSourcePath + "\\" + objOpts.strArch, strDstPathUNC, true); } } // CopyListOfFiles(aFiles, strSrc, strAltSrc, strDst, fRequired) // // // // Copy a list of files. // // Check for the existance of each file in either the strSrc or strAltSrc path. // // Copy to the strDst path. // // If a file does not exist, and fRequired is set, then throw an exception. // function CopyListOfFiles(aFiles, strSrc, strAltSrc, strDst, fRequired) { var i; for(i = 0; i < aFiles.length; ++i) { if (g_objFS.FileExists(strSrc + "\\" + aFiles[i])) g_objFS.CopyFile(strSrc + "\\" + aFiles[i], strDst + "\\" + aFiles[i]); else if (strAltSrc && g_objFS.FileExists(strAltSrc + "\\" + aFiles[i])) g_objFS.CopyFile(strAltSrc + "\\" + aFiles[i], strDst + "\\" + aFiles[i]); else if (fRequired) throw new Error(-1, "File not found: " + strSrc + "\\" + aFiles[i]); } } // ResetRegistry(objRegistry, strPath) // // // // Reset the registry entries for the script path. // function ResetRegistry(objRegistry, strPath) { objRegistry.CreateKey(WMIRegistry.prototype.HKCU, "Software\\Microsoft\\MTScript\\File Paths"); objRegistry.SetStringValue(WMIRegistry.prototype.HKCU, "Software\\Microsoft\\MTScript\\File Paths", "Script Path", strPath); objRegistry.SetStringValue(WMIRegistry.prototype.HKCU, "Software\\Microsoft\\MTScript\\File Paths", "Initial Script", "mtscript.js"); } //********************************************************************* //********************************************************************* //********************************************************************* //********************************************************************* // Library funtions // SplitFileName(strPath) // Return an array of 3 elements, path,filename,extension // [0] == "C:\path\" // [1] == "filename" // [2] == ".ext" function SplitFileName(strPath) { var nDot = strPath.lastIndexOf('.'); var nSlash = strPath.lastIndexOf('\\'); var nColon = strPath.lastIndexOf(':'); if (nDot >= 0 && nDot > nSlash && nDot > nColon) { return [strPath.slice(0, nSlash + 1), strPath.slice(nSlash + 1, nDot), strPath.slice(nDot)]; } // We get here if the file had no extension if (nSlash >= 2) // do not slice the UNC double \ at the start of a filename. { return [strPath.slice(0, nSlash + 1), strPath.slice(nSlash + 1, nDot), '']; } return ['', strPath, '']; } // RemoveEndChar(str, strChar) // // // // If 'strChar' appears as the last character // // in a string, remove it. // function RemoveEndChar(str, strChar) { var length = str.length; if (str.charAt(length - 1) == strChar) str = str.slice(0, length - 1); return str; } function PathToUNC(strMachineName, strPath) { return "\\\\" + strMachineName + "\\" + strPath.charAt(0) + "$" + strPath.slice(2) } function Assert(fOK, msg) { if (!fOK) { var caller = GetCallerName(null); LogMsg("ASSERTION FAILED :(" + caller + ") " + msg); WScript.Quit(0); } } function unevalString(str) { var i; var newstr = '"'; var c; for(i = 0; i < str.length; ++i) { c = str.charAt(i); switch(c) { case'\\': newstr += "\\\\"; break; case '"': newstr += '\\"'; break; case "'": newstr += "\\'"; break; case "\n": newstr += "\\n"; break; case "\r": newstr += "\\r"; break; case "\t": newstr += "\\t"; break; default: newstr += c; break; } } return newstr + '"'; } // Object_ToString() // // // // Provide a useful version of conversion // // from "object" to string - great for dumping // // objects to the debug log. // function Object_ToString() { var i; var str = "{"; var strComma = ''; for(i in this) { str += strComma + i + ":" + this[i]; strComma = ', '; } return str + "}"; } function Error_ToString() { var i; var str = 'Exception('; /* Only some error messages get filled in for "ex". Specifically the text for disk full never seems to get set by functions such as CreateTextFile(). */ if (this.number != null && this.description == '') { switch(this.number) { case -2147024784: this.description = "There is not enough space on the disk."; break; case -2147024894: this.description = "The system cannot find the file specified."; break; case -2147023585: this.description = "There are currently no logon servers available to service the logon request."; break; case -2147023170: this.description = "The remote procedure call failed."; break; case -2147024837: this.description = "An unexpected network error occurred"; break; case -2147024890: this.description = "The handle is invalid."; break; default: this.description = "Error text not set for (" + this.number + ")"; break; } } if (this.description) { var end = this.description.length - 1; while (this.description.charAt(end) == '\n' || this.description.charAt(end) == '\r') { end--; } this.description = this.description.slice(0, end+1); } for(i in this) { str += i + ": " + this[i] + " "; } return str + ")"; } function LogMsg(msg) { WScript.Echo(msg); } function Trace(msg) { if (g_Opts && g_Opts.fVerbose) WScript.Echo(" TRACE: " + msg); } function GetCallerName(cIgnoreCaller) { var tokens; if (cIgnoreCaller == null) cIgnoreCaller = 0; ++cIgnoreCaller; var caller = GetCallerName.caller; while (caller != null && cIgnoreCaller) { caller = caller.caller; --cIgnoreCaller; } if (caller != null) { tokens = caller.toString().split(/ |\t|\)|,/); if (tokens.length > 1 && tokens[0] == "function") { return tokens[1] + ")"; } } return ""; } // class WMIInterface(objLogin, strNameSpace) // // // // This class provides an easier to use interface to the WMI // // functionality. // // // // You must provide login information and the WMI namespace // // you wish to use. // // // // RemoteFileExists(strPath) NOTHROW // // returns true if the given file exists on the remote machine // // // // RemoteRenameFile(strFrom, strTo) // // Renames the given file. // // Throws on any error. // // // // RemoteDeleteFile(strPath) // // Delete the file. // // Throws on any error. // // // // RemoteTerminateExe(strExeName) // // Terminates all processes with the given name. // // Does not throw if the process does not exist. // // It will throw if the RPC to terminate a process fails. // // Does not return error status. // // // // RemoteExecuteCmd(strCmd, strDirectory) // // Runs the given command in the specified directory. // // It will throw if the RPC to start the process fails. // // Its not possible to retrieve status from the command // // which is run. // // // // RemoteDeleteShare(strShareName) // // If the named share exists, remove it. // // Throw on error (except if the error is "not found") // // // // RemoteCreateShare(strShareName, strSharePath, strShareComment) // // Create a share name "strShareName" with the given path and comment. // // Throw on error (it is an error if strShareName is already shared). // // // // RemoteShareExists(strShareName) // // Returns the shared path, or "" // // does not throw any errors. // // // function WMIInterface(objLogin, strNameSpace) { try { WMIInterface.prototype.wbemErrNotFound = -2147217406; WMIInterface.prototype.RemoteFileExists = _WMIInterface_FileExists; WMIInterface.prototype.RemoteRenameFile = _WMIInterface_RenameFile; WMIInterface.prototype.RemoteDeleteFile = _WMIInterface_DeleteFile; WMIInterface.prototype.RemoteTerminateExe = _WMIInterface_TerminateExe; WMIInterface.prototype.RemoteExecuteCmd = _WMIInterface__ExecuteCMD; WMIInterface.prototype.RemoteDeleteShare = _WMIInterface__DeleteShare; WMIInterface.prototype.RemoteCreateShare = _WMIInterface__CreateShare; WMIInterface.prototype.RemoteShareExists = _WMIInterface__ShareExists; // Private methods WMIInterface.prototype._FindFiles = _WMIInterface__FindFiles; WMIInterface.prototype._FileOperation = _WMIInterface__FileOperation; if (!strNameSpace || strNameSpace == '') strNameSpace = "root\\cimv2"; this._strNameSpace = strNameSpace; this._objLogin = objLogin; this._objLocator = new ActiveXObject("WbemScripting.SWbemLocator"); this._objService = this._objLocator.ConnectServer(this._objLogin.strMachine, this._strNameSpace, this._objLogin.strUser, this._objLogin.strPassword); this._objService.Security_.impersonationlevel = 3 } catch(ex) { LogMsg("WMIInterface logon failed " + ex); throw ex; } } function _WMIInterface__FindFiles(strPattern) { var objFileSet = this._objService.ExecQuery('Select * from CIM_DataFile Where name=' + unevalString(strPattern)); if (!objFileSet.Count) throw new Error(-1, "File not found: " + strPattern); return objFileSet; } function _WMIInterface__FileOperation(strPattern, strOperation, objInArgs) { try { var objFileSet = this._FindFiles(strPattern); var enumSet = new Enumerator(objFileSet); for (; !enumSet.atEnd(); enumSet.moveNext()) { Trace("remote " + strOperation + " " + (objInArgs ? objInArgs : '')); var objOut = CallMethod(enumSet.item(), strOperation, objInArgs); break; } } catch(ex) { ex.description = strOperation + '(' + strPattern + ')' + " Failed, " + ex.description; throw ex; } return true; } function _WMIInterface_FileExists(strName) { try { var objFileSet = this._objService.ExecQuery('Select * from CIM_DataFile Where name=' + unevalString(strName)); if (objFileSet.Count) return true; } catch(ex) { } Trace("RemoteFileExists: not found " + strName); return false; } function _WMIInterface_RenameFile(strFrom, strTo) { return this._FileOperation(strFrom, "Rename", {FileName:strTo}); } function _WMIInterface_DeleteFile(strName) { return this._FileOperation(strName, "Delete"); } function _WMIInterface_TerminateExe(strName, nExitCode) { var setQueryResults = this._objService.ExecQuery("Select Name,ProcessId From Win32_Process"); var enumSet = new Enumerator(setQueryResults); var nCount = 0; for( ; !enumSet.atEnd(); enumSet.moveNext()) { var item = enumSet.item(); if (item.Name == strName) { var outParam = CallMethod(item, "Terminate", {Reason:nExitCode}); // Reason will be the return code. Trace("Killed " + item.Name + " pid = " + item.ProcessId); nCount++; } } if (!nCount) Trace("Cannot terminate process " + strName + ": not found"); } function _WMIInterface__ExecuteCMD(strCmd, strDir) { try { Trace("Executing :" + strCmd); var objInstance = this._objService.Get("Win32_Process"); var outParam = CallMethod(objInstance, "Create", { CommandLine:strCmd, CurrentDirectory:strDir }); //EnumerateSetOfProperties("outParam properties", outParam.Properties_); Trace("ExecuteCMD " + strCmd + ", pid = " + outParam.ProcessId); } catch(ex) { ex.description = "ExecuteCMD " + strCmd + " failed " + ex.description; throw ex; } } function _WMIInterface__DeleteShare(strShareName) { try { var objInstance = this._objService.Get("Win32_Share='" + strShareName + "'"); Trace("DeleteShare " + objInstance.Name + "," + objInstance.Path); CallMethod(objInstance, "Delete"); } catch(ex) { if (ex.number != this.wbemErrNotFound) { ex.description = "DeleteShare " + strShareName + " failed " + ex.description; throw ex; } else Trace("DeleteShare " + strShareName + " not found"); } } function _WMIInterface__ShareExists(strShareName) { try { var objInstance = this._objService.Get("Win32_Share='" + strShareName + "'"); Trace("ShareExists " + objInstance.Name + "," + objInstance.Path); return objInstance.Path; } catch(ex) { if (ex.number != this.wbemErrNotFound) { ex.description = "ShareExists " + strShareName + " failed " + ex.description; throw ex; } else Trace("ShareExists " + strShareName + " not found"); } return ""; } function _WMIInterface__CreateShare(strShareName, strSharePath, strShareComment) { try { var objInstance = this._objService.Get("Win32_Share"); var outParam = CallMethod( objInstance, "Create", { Description:strShareComment, Name:strShareName, Path:strSharePath, Type:0 }); } catch(ex) { ex.description = "CreateShare " + strShareName + " failed " + ex.description; throw ex; } } // class WMIRegistry(objLogin) // // Class to enable remote registry access via WMI // // // // This class provides an easier to use interface to the WMI // // functionality. // // // // You must provide login information and the WMI namespace // // you wish to use. // // // // GetExpandedStringValue(hkey, strSubKeyName, strValueName) // // Retieves the string value for the given registry key. // // If strValueName == '', then retrieve the default value. // // // // If the value is of type REG_EXPAND_SZ, then the returned // // string will be the expanded value. // // // // Throw any errors. // // // // SetStringValue(hkey, strSubKeyName, strValueName, strValue) // // Sets a string value for the given registry key. // // If strValueName == '', then set the default value. // // Throw any errors. // // // // CreateKey(hkey, strSubKeyName) // // Create the specified registry key. // // Multiple levels of keys can be created at once. // // It is not an error to create a key which already exists. // // // // Throw any errors. // function WMIRegistry(objLogin) { try { WMIRegistry.prototype.HKCR = 0x80000000; // Required by StdRegProv WMIRegistry.prototype.HKCU = 0x80000001; // Required by StdRegProv WMIRegistry.prototype.GetExpandedStringValue = _WMIRegistry_GetExpandedStringValue; WMIRegistry.prototype.SetStringValue = _WMIRegistry_SetStringValue; WMIRegistry.prototype.CreateKey = _WMIRegistry_CreateKey; this._objRemote = new WMIInterface(objLogin, "root\\default"); this._objInstance = this._objRemote._objService.Get("StdRegProv"); } catch(ex) { LogMsg("WMIRegistry failed " + ex); throw ex; } } function _WMIRegistry_GetExpandedStringValue(hkey, strSubKeyName, strValueName) { try { var outParam = CallMethod(this._objInstance, "GetExpandedStringValue", {hDefKey:hkey, sSubKeyName:strSubKeyName, sValueName:strValueName}); return outParam.sValue; } catch(ex) { ex.description = "GetExpandedStringValue failed ('" + strSubKeyName + "', '" + strValueName + "'): " + ex.description; throw ex; } } function _WMIRegistry_SetStringValue(hkey, strSubKeyName, strValueName, strValue) { try { var outParam = CallMethod(this._objInstance, "SetStringValue", {hDefKey:hkey, sSubKeyName:strSubKeyName, sValueName:strValueName, sValue:strValue}); // outParam.ReturnValue == 0; } catch(ex) { ex.description = "SetStringValue failed ('" + strSubKeyName + "', '" + strValueName + "'): " + ex.description; throw ex; } } function _WMIRegistry_CreateKey(hkey, strSubKeyName) { try { var outParam = CallMethod(this._objInstance, "CreateKey", {hDefKey:hkey, sSubKeyName:strSubKeyName}); } catch(ex) { ex.description = "CreateKey failed ('" + strSubKeyName + "', '" + strValueName + "'): " + ex.description; throw ex; } } // FileSystemObject() // // // // Provide enhanced file system access. // // The primary functionaly here is to provide better error // // reporting. // function FileSystemObject() { if (!FileSystemObject.prototype.objFS) { FileSystemObject.prototype.objFS = new ActiveXObject("Scripting.FileSystemObject"); FileSystemObject.prototype.FileExists = _FileSystemObject_FileExists; FileSystemObject.prototype.FolderExists = _FileSystemObject_FolderExists; FileSystemObject.prototype.CreateFolder = _FileSystemObject_CreateFolder; FileSystemObject.prototype.DeleteFile = _FileSystemObject_DeleteFile; FileSystemObject.prototype.DeleteFolder = _FileSystemObject_DeleteFolder; FileSystemObject.prototype.MoveFolder = _FileSystemObject_MoveFolder; FileSystemObject.prototype.CopyFolder = _FileSystemObject_CopyFolder; FileSystemObject.prototype.CopyFile = _FileSystemObject_CopyFile; FileSystemObject.prototype.CreateTextFile = _FileSystemObject_CreateTextFile; FileSystemObject.prototype.OpenTextFile = _FileSystemObject_OpenTextFile; } } function _FileSystemObject_FileExists(str) { try { var fRet = this.objFS.FileExists(str); Trace("FileExists('" + str + "') = " + fRet); return fRet; } catch(ex) { ex.description = "FileExists('" + str + "') failed: " + ex.description; throw ex; } } function _FileSystemObject_FolderExists(str) { try { var fRet = this.objFS.FolderExists(str); Trace("FolderExists('" + str + "') = " + fRet); return fRet; } catch(ex) { Trace("FolderExists('" + str + "') failed: " + ex); return false; } } function _FileSystemObject_CreateFolder(str) { try { if (!this.FolderExists(str)) this.objFS.CreateFolder(str); } catch(ex) { ex.description = "CreateFolder('" + str + "') failed: " + ex.description; throw ex; } } function _FileSystemObject_DeleteFile(str) { try { Trace("DeleteFile '" + str + "'"); this.objFS.DeleteFile(str, true); } catch(ex) { ex.description = "DeleteFile(" + str + ") failed " + ex.description; throw ex; } } function _FileSystemObject_DeleteFolder(str) { try { Trace("DeleteFolder '" + str + "'"); this.objFS.DeleteFolder(str, true); } catch(ex) { ex.description = "DeleteFolder('" + str + "' failed: " + ex.description; throw ex; } } function _FileSystemObject_MoveFolder(str, strDst) { try { Trace("MoveFolder '" + str + "', '" + strDst + "'"); this.objFS.MoveFolder(str, strDst); } catch(ex) { ex.description = "MoveFolder('" + str + "', '" + strDst + "' failed: " + ex.description; throw ex; } } function _FileSystemObject_CreateTextFile(strFileName, fOverwrite) { do { Trace("CreateTextFile '" + strFileName + "'"); try { return this.objFS.CreateTextFile(strFileName, fOverwrite); } catch(ex) { if (fOverwrite && this.FileExists(strFileName)) { Trace(" CreateTextFile: Attempt to delete " + strFileName); this.DeleteFile(strFileName); continue; } ex.description = "CreateTextFile('" + strFileName + "' failed: " + ex.description; throw ex; } } while(true); } function _FileSystemObject_OpenTextFile(strFileName) { var objFile; do { try { objFile = this.objFS.OpenTextFile(strFileName, 1); Trace("OpenTextFile '" + strFileName + "' success"); return objFile; } catch(ex) { ex.description = "OpenTextFile('" + strFileName + "' failed: " + ex.description; throw ex; } } while(true); } function _FileSystemObject_CopyFile(str, strDst) { do { Trace("CopyFile '" + str + "', '" + strDst + "'"); try { this.objFS.CopyFile(str, strDst, true); break; } catch(ex) { if (this.FileExists(strDst)) { Trace(" CopyFile: Attempt to delete " + strDst); this.DeleteFile(strDst); continue; } ex.description = "CopyFile('" + str + "', '" + strDst + "' failed: " + ex.description; throw ex; } } while(true); } function _FileSystemObject_CopyFolder(str, strDst) { var strName; var folder; var fc; try { Trace("CopyFolder '" + str + "', '" + strDst + "'"); this.CreateFolder(strDst); folder = this.objFS.GetFolder(str); fc = new Enumerator(folder.Files); for (; !fc.atEnd(); fc.moveNext()) { strName = String(fc.item()); this.CopyFile(strName, strDst + "\\" + fc.item().Name); } fc = new Enumerator(folder.SubFolders); for (; !fc.atEnd(); fc.moveNext()) { strName = String(fc.item()); this.CopyFolder(strName, strDst + "\\" + fc.item().Name); } } catch(ex) { Trace("CopyFolder('" + str + "', '" + strDst + "' failed: " + ex); throw ex; } } function MachineInfo(strName) { this.strName = strName; this.strStatusFile = g_strShareDir + "\\" + strName + ".txt"; this.fDisabledWriteStatus = false; MachineInfo.prototype.ReadStatusInfo = _MachineInfo_ReadStatusInfo; MachineInfo.prototype.WriteStatusInfo = _MachineInfo_WriteStatusInfo; MachineInfo.prototype.DisableWriteStatusInfo = _MachineInfo_DisableWriteStatusInfo; } function _MachineInfo_DisableWriteStatusInfo() { this.fDisabledWriteStatus = true; } function _MachineInfo_ReadStatusInfo(strText) { var strText; var objFile; try { objFile = g_objFS.OpenTextFile(this.strStatusFile); strText = objFile.ReadLine(); objFile.Close(); } catch(ex) { strText = "cannot read status file"; } return strText; } function _MachineInfo_WriteStatusInfo(strText) { var objFile; try { Trace("WriteStatusInfo(" + strText + ") for " + this.strName); if (this.fDisabledWriteStatus) { LogMsg("Error: Attempting to write status to " + this.strName + " after disabling"); } else { objFile = g_objFS.CreateTextFile(this.strStatusFile, true); objFile.WriteLine(strText); objFile.Close(); } } catch(ex) { LogMsg("WriteStatusInfo(" + strText + ") for " + this.strName + " failed: " + ex); } } //********************************************************************* //********************************************************************* // CallMethod(objInstance, strMethodName, hParameters) // // // // Call a method on the given object, with the supplied // // named parameters. // // // // Throw if the method returns a non-zero ReturnValue. // // Else return the outParams. // function CallMethod(objInstance, strMethodName, hParameters) { try { Trace("CallMethod " + strMethodName + " " + (hParameters ? hParameters : '')); var objMethod = objInstance.Methods_(strMethodName); var inParams; var outParam; if (hParameters) { if (objMethod.inParameters) inParams = objMethod.inParameters.SpawnInstance_(); } var strParamName; if (hParameters) { for(strParamName in hParameters) inParams[strParamName] = hParameters[strParamName]; outParam = objInstance.ExecMethod_(strMethodName, inParams); } else outParam = objInstance.ExecMethod_(strMethodName); } catch(ex) { ex.description = "CallMethod " + strMethodName + (hParameters ? hParameters : '()') + " failed " + ex.description; throw ex; } if (outParam.ReturnValue != 0) throw new Error(outParam.ReturnValue, "Method " + strMethodName + " failed"); return outParam; } function EnumerateSetOfProperties(strSetName, SWBemSet, strIndent) { var fPrint = false; if (!strIndent) { strIndent = ''; fPrint = true; } var strMsg = strIndent + strSetName + "+\n"; strIndent += " "; try { var enumSet = new Enumerator(SWBemSet); for( ; !enumSet.atEnd(); enumSet.moveNext()) { var item = enumSet.item(); if (item.Properties_ == null) { if (item.Name != "Name") strMsg += strIndent + item.Name + " = " + item.Value + "\n"; } else { strMsg += EnumerateSetOfProperties(item.Name, item.Properties_, strIndent); } } if (fPrint) LogMsg(strMsg); } catch(ex) { if (strIndent == " " && SWBemSet.Properties_ != null) return EnumerateSetOfProperties(strSetName, SWBemSet.Properties_); LogMsg("ERROR: " + strSetName + " " + ex); } return strMsg; }