Creates an HTML file with the promote transactions that occurred in select streams during the past specified number of hours.
using System.Collections.Generic;
namespace LatestPromotions
{
class Program
{
#region class variables
private static DomainCollection _domains;
private static PropCollection _properties;
private static DepotsCollection _selDepots;
private static StreamsCollection _selStreams;
private static int _fromHoursAgo;
private static string _outputFile;
private static AcDepots _depots;
private static AcUsers _users;
private static List<XElement> _hist;
#endregion
static int Main()
{
if (!init()) return 1;
DateTime past = DateTime.Now.AddHours(_fromHoursAgo * -1);
if (!initListsAsync(past).Result) return 1;
if (_hist != null && _hist.Count > 0)
{
XmlWriter writer = null;
try
{
XmlWriterSettings settings = new XmlWriterSettings {
OmitXmlDeclaration = true, Indent = true, IndentChars = "\t",
Encoding = new UTF8Encoding(false)};
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;
}
private static async Task<bool> initListsAsync(DateTime past)
{
bool ret = false;
try
{
string timeHrsAgo = AcDateTime.DateTime2AcDate(past);
List<Task<AcResult>>[] tasks = new List<Task<AcResult>>[2];
tasks[0] = new List<Task<AcResult>>();
tasks[1] = new List<Task<AcResult>>();
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");
tasks[1].Add(sr);
}
_hist = new List<XElement>(tasks[0].Count);
while (tasks[0].Count > 0)
{
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)
{
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;
}
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;
}
private static XDocument buildReport(DateTime past)
{
XDocument doc = new XDocument(
new XDocumentType("HTML", null, null, null),
new XElement("html", new XAttribute("lang", "en"),
new XElement("head",
new XElement("meta", new XAttribute("charset", "utf-8")), new XElement("meta", new XAttribute("name", "description"),
new XAttribute("content", "Promotions to select streams during the past specified number of hours.")),
new XElement("title", "Promotions since " + past.ToString("f")),
new XElement("style",
$@"body {{
background-color: Gainsboro;
color: #0000ff;
font-family: Arial, sans-serif;
font-size: 13px;
margin: 10px; }}
table {{
background-color: #F1F1F1;
color: #000000;
font-size: 12px;
border: 2px solid black;
padding: 10px; }}"
)
),
new XElement("body",
new XElement("p", "Promotions since " + past.ToString("f") + " to streams:"),
new XElement("ul",
from s in _selStreams.OfType<StreamElement>()
orderby s.Stream
select new XElement("li", s.Stream)),
new XElement("table",
new XElement("thead",
new XElement("tr",
new XElement("td", "TransID"),
new XElement("td", "TransTime"),
new XElement("td", "Promoter"),
new XElement("td", "Elements")
)
),
new XElement("tbody",
from t in _hist.Elements(
"transaction")
orderby _users.getUser((string)t.Attribute("user")), t.acxTime("time") descending
select new XElement("tr",
new XElement("td", (int)t.Attribute("id")),
new XElement("td", ((DateTime)t.acxTime("time")).ToString("g")),
new XElement("td", _users.getUser((string)t.Attribute("user")) + " (" + (string)t.Attribute("user") + ")", new XElement("br"),
business((string)t.Attribute("user")), new XElement("br"), mobile((string)t.Attribute("user"))),
new XElement("td",
new XElement("table",
new XElement("caption", t.acxComment()),
new XElement("thead",
new XElement("tr",
new XElement("td", "EID"),
new XElement("td", "Element"),
new XElement("td", "Location"),
new XElement("td", "Real"),
new XElement("td", "Virtual"),
new XElement("td", "Status")
)
),
new XElement("tbody",
from v in t.Elements(
"version")
orderby Path.GetFileName((string)v.Attribute("path"))
select new XElement("tr",
new XElement("td", (int)v.Attribute("eid")),
new XElement("td", Path.GetFileName((string)v.Attribute("path"))),
new XElement("td", Path.GetDirectoryName((string)v.Attribute("path"))),
new XElement("td", $"{(string)v.Attribute("realNamedVersion")} ({(string)v.Attribute("real")})"),
new XElement("td", $"{(string)v.Attribute("virtualNamedVersion")} ({(string)v.Attribute("virtual")})"),
new XElement("td", (Stat.getElement(v) != null ? Stat.getElement(v).Status : "(earlier)"))
)
)
)
)
)
)
)
)
));
return doc;
}
private static string business(string prncpl)
{
string phone = null;
AcUser
user = _users.getUser(prncpl);
if (user != null)
phone = user.Business;
return (String.IsNullOrEmpty(phone)) ? String.Empty : phone + "(b)";
}
private static string mobile(string prncpl)
{
string phone = null;
AcUser
user = _users.getUser(prncpl);
if (user != null)
phone = user.Other.ContainsKey("Mobile") ? (string)user.Other["Mobile"] : null;
return (String.IsNullOrEmpty(phone)) ? String.Empty : phone + "(m)";
}
private static bool init()
{
if (!AcDebug.initAcLogging())
{
Console.WriteLine("Logging support initialization failed.");
return false;
}
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException);
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;
}
if (!initAppConfigData()) return false;
_depots = new AcDepots(dynamicOnly: true);
Task<bool> dini = _depots.initAsync(_selDepots);
_users = new AcUsers(_domains, _properties, includeGroupsList: false, includeDeactivated: true);
Task<bool> uini = _users.initAsync();
Task<bool[]>
all = Task.WhenAll(dini, uini);
if (all == null || all.Result.Any(n => n == false)) return false;
return true;
}
private static bool initAppConfigData()
{
bool ret = true;
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;
}
}
}