// Run the hist command for depot and add the results to our transactions list. Returns // true if operation succeeds, otherwise false. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\LatestTransactions-YYYY-MM-DD.log on hist command failure. // Exception caught and logged in same for a range of exceptions. private async static Task <bool> initLastTransAsync(string depot) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"hist -p ""{depot}"" -t now -fx"); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); XElement trans = xml.Element("transaction"); trans.AddAnnotation(depot); // add depot since it's not in the XML lock (_locker) { _transactions.Add(trans); } ret = true; } } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initLastTransAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initLastTransAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Initialize our class variables with values from LatestPromotions.exe.config. Returns true if all values // successfully read and class variables initialized, false otherwise. ConfigurationErrorsException caught // and logged in %LOCALAPPDATA%\AcTools\Logs\LatestPromotions-YYYY-MM-DD.log on initialization failure. private static bool initAppConfigData() { bool ret = true; // assume success try { _fromHoursAgo = AcQuery.getAppConfigSetting <int>("FromHoursAgo"); _outputFile = AcQuery.getAppConfigSetting <string>("OutputFile").Trim(); ADSection adSection = ConfigurationManager.GetSection("activeDir") as ADSection; if (adSection == null) { AcDebug.Log("Error in Program.initAppConfigData creating ADSection"); ret = false; } else { _domains = adSection.Domains; _properties = adSection.Props; } DepotsSection depotsConfigSection = ConfigurationManager.GetSection("Depots") as DepotsSection; if (depotsConfigSection == null) { AcDebug.Log("Error in Program.initAppConfigData creating DepotsSection"); ret = false; } else { _selDepots = depotsConfigSection.Depots; } StreamsSection streamsConfigSection = ConfigurationManager.GetSection("Streams") as StreamsSection; if (streamsConfigSection == null) { AcDebug.Log("Error in Program.initAppConfigData creating StreamsSection"); ret = false; } else { _selStreams = streamsConfigSection.Streams; } } catch (ConfigurationErrorsException exc) { Process currentProcess = Process.GetCurrentProcess(); ProcessModule pm = currentProcess.MainModule; AcDebug.Log($"Invalid data in {pm.ModuleName}.config{Environment.NewLine}{exc.Message}"); ret = false; } return(ret); }
// Initialize our dictionary class variable with [element, EID] for all elements in all dynamic streams in depot. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on stat command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <bool> initMapAsync(AcDepot depot) { bool ret = false; // assume failure try { IEnumerable <AcStream> filter = from n in depot.Streams where n.IsDynamic && !n.Hidden select n; List <Task <AcResult> > tasks = new List <Task <AcResult> >(filter.Count()); foreach (AcStream stream in filter) { tasks.Add(AcCommand.runAsync($@"stat -a -s ""{stream}"" -fx")); // -a for all elements in stream } AcResult[] arr = await Task.WhenAll(tasks); // finish running stat commands in parallel if (arr != null && arr.All(n => n.RetVal == 0)) // true if all initialized successfully { HashSet <Tuple <string, int> > hset = new HashSet <Tuple <string, int> >(_tcompare); foreach (AcResult r in arr) { // if empty the stream has an ACL that is preventing us from reading it or some other error occurred if (r == null || String.IsNullOrEmpty(r.CmdResult)) { continue; } XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("element")) { string path = (string)e.Attribute("location"); int eid = (int)e.Attribute("id"); hset.Add(new Tuple <string, int>(path, eid)); } } lock (_locker) { _map.Add(depot, hset); } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.initMapAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initMapAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
private static readonly object _locker = new object(); // token for lock keyword scope #endregion // Returns zero (0) if program ran successfully, otherwise // one (1) in the event of an exception or program initialization failure. static int Main() { // general program startup initialization if (!init()) { return(1); } // if a TwinsExcludeFile was specified in EvilTwins.exe.config, // validate that it exists and retrieve its content if (!String.IsNullOrEmpty(_twinsExcludeFile)) { if (!File.Exists(_twinsExcludeFile)) { AcDebug.Log($"TwinsExcludeFile {_twinsExcludeFile} specified in EvilTwins.exe.config not found"); return(1); } else { _excludeList = getTwinsExcludeList(); } } // all stream types in order to include workspace streams, include hidden (removed) streams AcDepots depots = new AcDepots(dynamicOnly: false, includeHidden: true); Task <bool> dini = depots.initAsync(_selDepots); if (!dini.Result) { return(1); } _tcompare = new TwinEqualityComparer(); _map = new Dictionary <AcDepot, HashSet <Tuple <string, int> > >(); List <Task <bool> > tasks = new List <Task <bool> >(depots.Count); foreach (AcDepot depot in depots) { tasks.Add(initMapAsync(depot)); } Task <bool[]> arr = Task.WhenAll(tasks); // finish running stat commands and initialization in parallel if (arr == null || arr.Result.Any(n => n == false)) { return(1); // check log file } Task <bool> r = reportAsync(); return((r.Result) ? 0 : 1); }
// Run the stat command for all dynamic streams in depot and initialize our dictionary class variable // with the xlinked elements found that have a type listed in ElementTypes from XLinked.exe.config. // Returns true if the operation succeeded, false otherwise. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\XLinked-YYYY-MM-DD.log on stat command failure. Exception caught and // logged in same for a range of exceptions. private static async Task <bool> initAsync(AcDepot depot) { bool ret = false; // assume failure try { int num = depot.Streams.Count(); List <Task <AcResult> > tasks = new List <Task <AcResult> >(num); foreach (AcStream stream in depot.Streams) { // -k: Display the element type (that is, data type) of this version // -v: Display the target of an element link or symbolic link tasks.Add(AcCommand.runAsync($@"stat -s ""{stream}"" -a -fkvx")); } HashSet <XElement> hset = new HashSet <XElement>(_comparer); while (tasks.Count > 0) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); foreach (XElement e in xml.Elements("element") // attribute xlinked="true" exists only when status includes (xlinked), // otherwise it isn't there (i.e. there never is an xlinked="false" in the XML) .Where(n => (string)n.Attribute("xlinked") != null && _etypes.Any(t => t == n.acxType("elemType")))) { hset.Add(e); } } lock (_locker) { _map.Add(depot, hset); } ret = true; } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
static int Main() { // general program startup initialization if (!init()) { return(1); // initialization failure, check log file } DateTime past = DateTime.Now.AddHours(_fromHoursAgo * -1); // go back this many hours if (!initListsAsync(past).Result) { return(1); // operation failed, check log file } if (_hist != null && _hist.Count > 0) { XmlWriter writer = null; try { XmlWriterSettings settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, IndentChars = "\t", Encoding = new UTF8Encoding(false) }; // false to exclude Unicode byte order mark (BOM) using (writer = XmlWriter.Create(_outputFile, settings)) { XDocument report = buildReport(past); report.WriteTo(writer); } } catch (Exception exc) { AcDebug.Log($"Exception caught and logged in Program.Main{Environment.NewLine}" + $"Failed writing to {_outputFile}{Environment.NewLine}{exc.Message}"); return(1); } finally { if (writer != null) { writer.Close(); } } } return(0); }
// Run the stat command for streams in depots listed in LatestOverlaps.exe.config and add the // results to the Stat.Elements list. Returns true if initialization succeeded, false otherwise. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestOverlaps-YYYY-MM-DD.log // on stat command failure. Exception caught and logged in same for a range of exceptions. private static async Task <bool> initStatAsync() { bool ret = false; // assume failure try { IEnumerable <XElement> trans = from e in _hist.Elements("transaction") select e; ILookup <string, XElement> map = trans.ToLookup(n => (string)n.Attribute("streamName"), n => n); List <Task <AcResult> > tasks = new List <Task <AcResult> >(); foreach (var ii in map) // for each stream { AcStream stream = _depots.getStream(ii.Key); if (!stream.HasDefaultGroup) { continue; // run stat only if default group exists } tasks.Add(AcCommand.runAsync($@"stat -s ""{stream}"" -o -fx")); } bool op = true; while (tasks.Count > 0 && op) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); op = (r != null && r.Result.RetVal == 0 && Stat.init(r.Result.CmdResult)); } ret = op; // true if all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initStatAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initStatAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
private static async Task <bool> reportAsync() { DateTime past = DateTime.Now.AddHours(_fromHoursAgo * -1); // go back this many hours if (!(await initHistAsync(past))) { return(false); } if (_hist != null && _hist.Count > 0) { if (!(await initStatAsync())) { return(false); } XmlWriter writer = null; try { XmlWriterSettings settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, IndentChars = "\t", Encoding = new UTF8Encoding(false) // false to exclude Unicode byte order mark (BOM) }; using (writer = XmlWriter.Create(_outputFile, settings)) { XDocument report = buildReport(past); report.WriteTo(writer); } } catch (Exception exc) { AcDebug.Log($"Exception caught and logged in Program.reportAsync{Environment.NewLine}" + $"Failed writing to {_outputFile}{Environment.NewLine}{exc.Message}"); return(false); } finally { if (writer != null) { writer.Close(); } } } return(true); }
// General program startup initialization. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // save an unhandled exception in log file before program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our class variables from LatestPromotions.exe.config if (!initAppConfigData()) { return(false); } // dynamic streams only in select depots _depots = new AcDepots(dynamicOnly: true); Task <bool> dini = _depots.initAsync(_selDepots); // no group membership initialization, include deactivated users _users = new AcUsers(_domains, _properties, includeGroupsList: false, includeDeactivated: true); Task <bool> uini = _users.initAsync(); Task <bool[]> all = Task.WhenAll(dini, uini); // finish initializing both lists in parallel if (all == null || all.Result.Any(n => n == false)) { return(false); } return(true); }
// General program startup initialization. Returns true if initialization succeeded, false otherwise. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // in the event of an unhandled exception, save it to our log file before the program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our class variables from PromoCount.exe.config if (!initAppConfigData()) { return(false); } // initialize our logging support for program results if (!initPromoCountResultsLogging()) { return(false); } _users = new AcUsers(_domains, null, includeGroupsList: false, includeDeactivated: true); _depots = new AcDepots(dynamicOnly: true); Task <bool[]> lists = Task.WhenAll(_depots.initAsync(_selDepots), _users.initAsync()); if (lists == null || lists.Result.Any(n => n == false)) { return(false); } return(true); }
// Run the hist command for depots listed in LatestOverlaps.exe.config and add the results to // our history list class variable. Returns true if initialization succeeded, false otherwise. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestOverlaps-YYYY-MM-DD.log // on hist command failure. Exception caught and logged in same for a range of exceptions. private static async Task <bool> initHistAsync(DateTime past) { bool ret = false; // assume failure try { string timeHrsAgo = AcDateTime.DateTime2AcDate(past); // get date in string format suitable for AccuRev CLI List <Task <AcResult> > tasks = new List <Task <AcResult> >(_depots.Count); foreach (AcDepot depot in _depots) { tasks.Add(AcCommand.runAsync($@"hist -k promote -p ""{depot}"" -t now-""{timeHrsAgo}"" -fex")); } _hist = new List <XElement>(_depots.Count); while (tasks.Count > 0) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); _hist.Add(xml); } ret = true; // if we're here then all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initHistAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initHistAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Initialize our class variables from LatestTransactions.exe.config. Returns true if class variables // initialized successfully, false otherwise. ConfigurationErrorsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\LatestTransactions-YYYY-MM-DD.log on initialization failure. private static bool initAppConfigData() { bool ret = false; // assume failure try { _fileName = AcQuery.getAppConfigSetting <string>("FileName").Trim(); _fileLocation = AcQuery.getAppConfigSetting <string>("FileLocation").Trim(); ret = true; } catch (ConfigurationErrorsException exc) { Process currentProcess = Process.GetCurrentProcess(); ProcessModule pm = currentProcess.MainModule; AcDebug.Log($"Invalid data in {pm.ModuleName}.config{Environment.NewLine}{exc.Message}"); } return(ret); }
// General program startup initialization. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // in the event of an unhandled exception, save it to our log file before the program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our ElementType array class variable from XLinked.exe.config if (!initAppConfigData()) { return(false); } _depots = new AcDepots(dynamicOnly: true); // dynamic streams only Task <bool> dini = _depots.initAsync(); if (!dini.Result) { AcDebug.Log($"Depots list initialization failed. See log file:{Environment.NewLine}" + $"{AcDebug.getLogFile()}"); return(false); } return(true); }
// Returns the list of elements in TwinsExcludeFile from EvilTwins.exe.config with elements that can be ignored. // Assumes caller has determined that the TwinsExcludeFile specified in EvilTwins.exe.config exists. // Exception caught and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on operation failure. private static List <String> getTwinsExcludeList() { List <String> exclude = new List <String>(); FileStream fs = null; try { // constructor arguments that avoid an exception thrown when file is in use by another process fs = new FileStream(_twinsExcludeFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using (StreamReader sr = new StreamReader(fs)) { String line; while ((line = sr.ReadLine()) != null) { string temp = line.Trim(); if (temp.Length == 0 || temp.StartsWith("#")) { continue; // this is an empty line or a comment } exclude.Add(temp); } } } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.getTwinsExcludeList{Environment.NewLine}{ecx.Message}"); } finally // avoids CA2202: Do not dispose objects multiple times { if (fs != null) { fs.Dispose(); } } return(exclude); }
// Initialize our ElementType array class variable with values from XLinked.exe.config. // Returns true if successfully read and initialized, false otherwise. ConfigurationErrorsException // caught and logged in %LOCALAPPDATA%\AcTools\Logs\XLinked-YYYY-MM-DD.log on initialization failure. private static bool initAppConfigData() { bool ret = false; // assume failure try { string[] arr = AcQuery.getAppConfigSetting <string>("ElementTypes") .Split(',').Select(s => s.Trim()).ToArray(); _etypes = Array.ConvertAll(arr, new Converter <string, ElementType>(n => (ElementType)Enum.Parse(typeof(ElementType), n))); ret = true; } catch (ConfigurationErrorsException exc) { Process currentProcess = Process.GetCurrentProcess(); ProcessModule pm = currentProcess.MainModule; AcDebug.Log($"Invalid data in {pm.ModuleName}.config{Environment.NewLine}{exc.Message}"); } return(ret); }
// General program startup initialization. Returns true if initialization was successful, false otherwise. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // save an unhandled exception in log file before program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our depots list class variable with select depots from WSpaceTransLevel.exe.config if (!initAppConfigData()) { return(false); } // initialize our workspaces list class variable Task <bool> wslist = initWSListAsync(); if (!wslist.Result) { AcDebug.Log($"Workspaces list initialization failed. See log file:{Environment.NewLine}{AcDebug.getLogFile()}"); return(false); } return(true); }
// General program initialization routines. Returns true // if initialization succeeded, otherwise false. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // save an unhandled exception in log file before program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } return(true); }
// General program initialization routines. Returns true if initialization was successful, false otherwise. private static bool init() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // save an unhandled exception in log file before program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev Task <string> prncpl = AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl.Result)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our class variables from LatestTransactions.exe.config if (!initAppConfigData()) { return(false); } // list of all depot names in the repository _depots = AcQuery.getDepotNameListAsync().Result; if (_depots == null) { return(false); } return(true); }
// General program startup initialization. private static async Task <bool> initAsync() { // initialize our logging support so we can log errors if (!AcDebug.initAcLogging()) { Console.WriteLine("Logging support initialization failed."); return(false); } // in the event of an unhandled exception, save it to our log file before the program terminates AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException); // ensure we're logged into AccuRev string prncpl = await AcQuery.getPrincipalAsync(); if (String.IsNullOrEmpty(prncpl)) { AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again."); return(false); } // initialize our depots list class variable from PromoRights.exe.config if (!initAppConfigData()) { return(false); } _users = new AcUsers(null, null, includeGroupsList: true); _locks = new AcLocks(); bool[] arr = await Task.WhenAll( _users.initAsync(), // all users with their respective group membership list initialized _locks.initAsync(_depots) // locks on all streams in select depots from PromoRights.exe.config ); return(arr != null && arr.All(n => n == true)); }
// Generate an Excel worksheet with the results in reverse chronological order so the most // recent activity in the repository is shown on top. Returns true if the operation completed // successfully, false otherwise. COMException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\LatestTransactions-YYYY-MM-DD.log on worksheet creation failure. private static bool report() { Excel.Application excel = new Excel.Application(); if (excel == null) { MessageBox.Show("Excel installation not found.", "LatestTransactions", MessageBoxButtons.OK, MessageBoxIcon.Hand); return(false); } bool ret = true; // assume success excel.DisplayAlerts = false; // don't display the SaveAs dialog box Excel.Workbook wbook = excel.Workbooks.Add(); Excel.Worksheet wsheet = (Excel.Worksheet)wbook.Worksheets.get_Item(1); Excel.Range rheader = wsheet.get_Range("A1", "F1"); rheader.Font.Bold = true; rheader.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter; Excel.Range rdate = wsheet.get_Range("B:B"); rdate.NumberFormat = "mmm d, yyyy h:mm:ss am/pm"; Excel.Range rcomment = wsheet.get_Range("F:F"); rcomment.WrapText = true; wsheet.Cells[1, "A"] = "Depot"; wsheet.Columns["A"].ColumnWidth = 20; wsheet.Cells[1, "B"] = "Time"; wsheet.Columns["B"].ColumnWidth = 25; wsheet.Cells[1, "C"] = "Action"; wsheet.Columns["C"].ColumnWidth = 15; wsheet.Cells[1, "D"] = "User"; wsheet.Columns["D"].ColumnWidth = 15; wsheet.Cells[1, "E"] = "Trans_ID"; wsheet.Columns["E"].ColumnWidth = 10; wsheet.Cells[1, "F"] = "Comment"; wsheet.Columns["F"].ColumnWidth = 50; int row = 2; foreach (XElement trans in _transactions.OrderByDescending(n => n.acxTime("time"))) { string depot = trans.Annotation <string>(); int id = (int)trans.Attribute("id"); string action = (string)trans.Attribute("type"); DateTime?time = trans.acxTime("time"); string user = (string)trans.Attribute("user"); string comment = trans.acxComment(); wsheet.Cells[row, "A"] = depot; wsheet.Cells[row, "B"] = time; wsheet.Cells[row, "C"] = action; wsheet.Cells[row, "D"] = user; wsheet.Cells[row, "E"] = id; wsheet.Cells[row, "F"] = comment; row++; } string file = String.Empty; try { file = Path.Combine(_fileLocation, _fileName); wbook.SaveAs(Filename: file, ReadOnlyRecommended: true); wbook.Close(); } catch (COMException exc) { AcDebug.Log(exc.Message); MessageBox.Show(exc.Message); ret = false; } finally { excel.Quit(); } if (ret) { MessageBox.Show($"Latest transactions saved to {file}", "LatestTransactions", MessageBoxButtons.OK, MessageBoxIcon.Information); } return(ret); }
// Report evil twins if found. Assumes the initMapAsync method has been called. Exception caught // and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on operation failure. private static async Task <bool> reportAsync() { bool ret = false; // assume failure try { foreach (KeyValuePair <AcDepot, HashSet <Tuple <string, int> > > pair in _map.OrderBy(n => n.Key)) // order by AcDepot { AcDepot depot = pair.Key; // depot HashSet <Tuple <string, int> > hset = pair.Value; // [element, EID] from all dynamic streams in depot // from our hashset create a collection of elements mapped to their EID's Lookup <string, Tuple <string, int> > col = (Lookup <string, Tuple <string, int> >)hset.ToLookup(n => n.Item1); // where more than one EID exists for the element, order by element foreach (var ii in col.Where(n => n.Count() > 1).OrderBy(n => n.Key)) { string element = ii.Key; if (_excludeList != null && _excludeList.Contains(element)) { continue; // ignore if in TwinsExcludeFile } log(element); IEnumerable <AcStream> filter = from n in depot.Streams where n.IsDynamic && !n.Hidden select n; List <Task <XElement> > tasks = new List <Task <XElement> >(filter.Count()); foreach (AcStream stream in filter) { tasks.Add(getElementInfoAsync(stream, element)); } XElement[] arr = await Task.WhenAll(tasks); // finish running stat commands in parallel if (arr != null && arr.All(n => n != null)) // true if all ran successfully { foreach (Tuple <string, int> jj in ii.OrderBy(n => n.Item2)) // order twins by EID { int eid = jj.Item2; log($"\tEID: {eid} on {DateTime.Now.ToString("ddd MMM d h:mm tt")}"); // C# language short-circuit: the test for id equals eid isn't evaluated if status equals "(no such elem)", // otherwise an exception would be thrown since the id attribute doesn't exist in this case foreach (XElement e in arr.Where(n => (string)n.Attribute("status") != "(no such elem)" && (int)n.Attribute("id") == eid).OrderBy(n => n.Annotation <AcStream>())) { log($"\t\t{e.Annotation<AcStream>()} {(string)e.Attribute("status")}"); string namedVersion = (string)e.Attribute("namedVersion"); // virtual stream name and version number string temp = (string)e.Attribute("Real"); string[] real = temp.Split('\\'); // workspace stream and version numbers AcStream wkspace = depot.getStream(int.Parse(real[0])); // workspace stream ElementType elemType = e.acxType("elemType"); string twin; if ((long?)e.Attribute("size") != null) { twin = $"\t\t\tSize: {(long)e.Attribute("size")}, ModTime: {e.acxTime("modTime")} {{{elemType}}}" + $"{Environment.NewLine}\t\t\tReal: {wkspace}\\{real[1]}, Virtual: {namedVersion}"; } else // a folder or link { twin = $"\t\t\tReal: {wkspace}\\{real[1]}, Virtual: {namedVersion} {{{elemType}}}"; } log(twin); } log(""); } } } } ret = true; // operation succeeded } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.reportAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Initialize our history and stat lists for each stream listed in the LatestPromotions.exe.config Streams section. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestPromotions-YYYY-MM-DD.log on hist or stat // command failure. Exception caught and logged in same on failure to handle a range of exceptions. private static async Task <bool> initListsAsync(DateTime past) { bool ret = false; // assume failure try { string timeHrsAgo = AcDateTime.DateTime2AcDate(past); // get date in string format suitable for AccuRev CLI List <Task <AcResult> >[] tasks = new List <Task <AcResult> > [2]; tasks[0] = new List <Task <AcResult> >(); // for hist results tasks[1] = new List <Task <AcResult> >(); // for stat results // Alternatively change Equals() to Contains() and modify LatestPromotions.exe.config stream values // accordingly to filter on stream name subsets, e.g. <add stream="DEV"/> for all streams with DEV in their name. foreach (AcStream stream in _depots.SelectMany(d => d.Streams .Where(s => _selStreams.OfType <StreamElement>().Any(se => s.Name.Equals(se.Stream))))) { Task <AcResult> hr = AcCommand.runAsync($@"hist -k promote -s ""{stream}"" -t now-""{timeHrsAgo}"" -fx"); tasks[0].Add(hr); Task <AcResult> sr = AcCommand.runAsync($@"stat -s ""{stream}"" -d -fx"); // stream's default group tasks[1].Add(sr); } _hist = new List <XElement>(tasks[0].Count); while (tasks[0].Count > 0) // process hist results { Task <AcResult> r = await Task.WhenAny(tasks[0]); tasks[0].Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); _hist.Add(xml); } while (tasks[1].Count > 0) // process stat results { Task <AcResult> r = await Task.WhenAny(tasks[1]); tasks[1].Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } if (!Stat.init(r.Result.CmdResult)) { return(false); } } ret = true; // if we're here then all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initListsAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initListsAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Run the AccuRev hist command for all streams in PromoCount.exe.config, generate the results and send it // to the daily log file PromoCountResults-YYYY-MM-DD.log created (or updated) in the same folder where // PromoCount.exe resides. Returns true if the operation succeeded, false otherwise. AcUtilsException // caught and logged in %LOCALAPPDATA%\AcTools\Logs\PromoCount-YYYY-MM-DD.log on hist command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <bool> promoCountAsync() { bool ret = false; // assume failure try { Dictionary <AcStream, Task <AcResult> > map = new Dictionary <AcStream, Task <AcResult> >(_selStreams.Count); Func <AcStream, Task <AcResult> > run = (stream) => { // start-end times reversed as workaround for AccuRev issue 15780 Task <AcResult> result = AcCommand.runAsync( $@"hist -fx -k promote -s ""{stream}"" -t ""{_endTime} - {_startTime}"""); lock (_locker) { map.Add(stream, result); } return(result); }; var tasks = from s in _depots.SelectMany(d => d.Streams) where _selStreams.OfType <StreamElement>().Any(se => se.Stream == s.Name) select run(s); AcResult[] arr = await Task.WhenAll(tasks); // finish running hist commands in parallel if (arr == null || arr.Any(r => r.RetVal != 0)) { return(false); } log($"Promotions to select streams from {_startTime} to {_endTime}.{Environment.NewLine}"); int tgrandtot = 0; int vgrandtot = 0; foreach (var ii in map.OrderBy(n => n.Key)) { log($"{ii.Key} {{{$"promotions\\versions"}}}:"); // key is stream AcResult r = ii.Value.Result; XElement xml = XElement.Parse(r.CmdResult); ILookup <string, XElement> look = xml.Elements("transaction") .ToLookup(n => (string)n.Attribute("user"), n => n); int tsubtot = 0; int vsubtot = 0; foreach (var jj in look.OrderBy(n => _users.getUser(n.Key))) { AcUser user = _users.getUser(jj.Key); int tnum = jj.Count(); int vnum = jj.Elements("version").Count(); string val = $"{{{tnum}\\{vnum}}}"; log($"\t{user.ToString().PadRight(40, '.')}{val.PadLeft(13, '.')}"); tsubtot += tnum; tgrandtot += tnum; vsubtot += vnum; vgrandtot += vnum; } log($"\tTotal {tsubtot} promotions and {vsubtot} versions.{Environment.NewLine}"); } log($"Grand total of {tgrandtot} promotions and {vgrandtot} versions."); ret = true; } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }