mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Fixed LogReporter error introduced by my earlier modifications of HeliosPlus due to ProfileItem object changes. This messed up the LogReporter writing logic which in turn made log files balloon to multiple GB in size! Also added capture of the various JSON files that are used to store settings so that we can help fix JSON errors.
404 lines
15 KiB
C#
404 lines
15 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using WindowsDisplayAPI;
|
|
using WindowsDisplayAPI.DisplayConfig;
|
|
using HeliosPlus.Shared;
|
|
using NvAPIWrapper.GPU;
|
|
using NvAPIWrapper.Mosaic;
|
|
|
|
namespace HeliosPlus.LogReporter
|
|
{
|
|
internal class Program
|
|
{
|
|
private static StreamWriter _writer;
|
|
internal static string AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "HeliosPlus");
|
|
|
|
private static void DumpObject<T>(
|
|
IEnumerable<T> items,
|
|
string title,
|
|
Tuple<Func<T, object>, string>[] actions = null,
|
|
int deepIn = 0)
|
|
{
|
|
Console.Write($"- {title}...");
|
|
_writer.WriteLine(title + new string('=', Console.BufferWidth - title.Length));
|
|
var totalTime = TimeSpan.Zero;
|
|
var stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
foreach (var item in items)
|
|
{
|
|
var actionResults = actions?.Select(tuple =>
|
|
new Tuple<string, object>(tuple.Item2, tuple.Item1.Invoke(item))).ToArray();
|
|
stopWatch.Stop();
|
|
WriteObject(item, 0, stopWatch.Elapsed, actionResults, deepIn);
|
|
totalTime += stopWatch.Elapsed;
|
|
stopWatch.Reset();
|
|
stopWatch.Start();
|
|
}
|
|
|
|
stopWatch.Stop();
|
|
totalTime += stopWatch.Elapsed;
|
|
Console.WriteLine(@"(Took {0} to complete)", totalTime);
|
|
_writer.WriteLine(@"-- Total Elapsed: {0}", totalTime);
|
|
_writer.WriteLine();
|
|
_writer.WriteLine(new string('#', Console.BufferWidth));
|
|
_writer.WriteLine();
|
|
}
|
|
|
|
private static void IngestFile(string fileName, string title)
|
|
{
|
|
|
|
Console.Write($"- {title}...");
|
|
_writer.WriteLine(new string('=', Console.BufferWidth));
|
|
_writer.WriteLine(title + new string('=', Console.BufferWidth - title.Length));
|
|
_writer.WriteLine(new string('=', Console.BufferWidth));
|
|
var totalTime = TimeSpan.Zero;
|
|
var stopWatch = new Stopwatch();
|
|
|
|
if (File.Exists(fileName))
|
|
{
|
|
stopWatch.Start();
|
|
|
|
StreamReader reader = new StreamReader(fileName);
|
|
string fileContents = reader.ReadToEnd();
|
|
_writer.WriteLine(fileContents);
|
|
|
|
stopWatch.Stop();
|
|
totalTime += stopWatch.Elapsed;
|
|
Console.WriteLine(@"(Took {0} to complete)", totalTime);
|
|
_writer.WriteLine(@"-- Total Elapsed: {0}", totalTime);
|
|
_writer.WriteLine();
|
|
_writer.WriteLine(new string('#', Console.BufferWidth));
|
|
_writer.WriteLine();
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private static void Main(string[] args)
|
|
{
|
|
Console.WriteLine("HeliosPlus LogReporter");
|
|
Console.WriteLine("======================");
|
|
Console.WriteLine();
|
|
Console.WriteLine("This program will interrogate your HeliosPlus configuration settings, the Windows Display ");
|
|
Console.WriteLine("Subsystem and any NVIDIA Display Drivers to record what they can detect and report. This");
|
|
Console.WriteLine("recorded information is then stored in a log file. If you report a problem then you may be");
|
|
Console.WriteLine("asked to send us the log file generated by this program in order for us to help you.");
|
|
Console.WriteLine();
|
|
Console.WriteLine("Starting the interrogation...");
|
|
Console.WriteLine();
|
|
string date = DateTime.Now.ToString("yyyyMMdd.HHmmss");
|
|
_writer = new StreamWriter(new FileStream(
|
|
string.Format("HeliosPlus.Reporting.{0}.log", date),
|
|
FileMode.CreateNew));
|
|
|
|
try
|
|
{
|
|
IngestFile(Path.Combine(AppDataPath, "Settings_1.0.json"), "Storing HeliosPlus Settings JSON File");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
IngestFile(Path.Combine(AppDataPath, "Profiles", "DisplayProfiles_1.0.json"), "Storing HeliosPlus Display Profiles JSON File");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
IngestFile(Path.Combine(AppDataPath, "Shortcuts", "Shortcuts_1.0.json"), "Storing HeliosPlus Shortcuts JSON File");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
DumpObject(DisplayAdapter.GetDisplayAdapters(), "Storing a list of Display Adapters currently in this computer");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(Display.GetDisplays(), "Storing a list of possible settings for Displays currently connected to this computer", new[]
|
|
{
|
|
new Tuple<Func<Display, object>, string>(display => display.GetPossibleSettings(),
|
|
"GetPossibleSettings()")
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(UnAttachedDisplay.GetUnAttachedDisplays(),
|
|
"Storing a list of Displays not currently in use, but currently connected to this computer");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(PathDisplayAdapter.GetAdapters(),
|
|
"Storing a list of Displays Targets for all Display Adapters currently in this computer",
|
|
new[]
|
|
{
|
|
new Tuple<Func<PathDisplayAdapter, object>, string>(adapter => adapter.ToDisplayAdapter(),
|
|
"ToDisplayAdapter()")
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(PathDisplaySource.GetDisplaySources(),
|
|
"Storing a list of Display Sources for Displays currently connected to this computer", new[]
|
|
{
|
|
new Tuple<Func<PathDisplaySource, object>, string>(source => source.ToDisplayDevices(),
|
|
"ToDisplayDevices()")
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(PathDisplayTarget.GetDisplayTargets(),
|
|
"Storing a list of Displays Targets for Displays currently connected to this computer", new[]
|
|
{
|
|
new Tuple<Func<PathDisplayTarget, object>, string>(target => target.ToDisplayDevice(),
|
|
"ToDisplayDevice()")
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
if (PathInfo.IsSupported)
|
|
{
|
|
DumpObject(PathInfo.GetActivePaths(), "Storing a list of Active Displays currently connected to this computer", null,
|
|
2);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(LogicalGPU.GetLogicalGPUs(), "Storing a list of logical NVIDIA GPUs formed by NVIDIA GPUs currently in this computer (e.g. SLI)", null, 1);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(PhysicalGPU.GetPhysicalGPUs(), "Storing a list of physical NVIDIA GPUs currently in this computer");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(NvAPIWrapper.Display.Display.GetDisplays(), "Storing a list of Displays currently connected to this computer through a NVIDIA GPU", new[]
|
|
{
|
|
new Tuple<Func<NvAPIWrapper.Display.Display, object>, string>(
|
|
display => display.GetSupportedViews(),
|
|
"GetSupportedViews()")
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(NvAPIWrapper.Display.UnAttachedDisplay.GetUnAttachedDisplays(),
|
|
"Storing a list of Displays currently connected to this computer through a NVIDIA GPU but not active");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(NvAPIWrapper.Display.PathInfo.GetDisplaysConfig(),
|
|
"Storing a list of configuration of Displays currently connected to this computer through a NVIDIA GPU",
|
|
null, 3);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
DumpObject(GridTopology.GetGridTopologies(), "Storing a list of configured NZIVIDA Surround/Mosaic settings involving multiple Displays via a NVIDIA GPU", null, 3);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteException(e);
|
|
}
|
|
|
|
_writer.Flush();
|
|
_writer.Close();
|
|
_writer.Dispose();
|
|
|
|
Console.WriteLine(new string('=', Console.BufferWidth));
|
|
Console.WriteLine();
|
|
Console.WriteLine(@"Done, press enter to exit.");
|
|
Console.ReadLine();
|
|
}
|
|
|
|
private static void WriteException(Exception ex)
|
|
{
|
|
Console.WriteLine("{0} - Error: {1}", ex.GetType().Name, ex.Message);
|
|
_writer.WriteLine("{0} - Error: {1}", ex.GetType().Name, ex.Message);
|
|
}
|
|
|
|
private static void WriteObject(
|
|
object obj,
|
|
int padding = 0,
|
|
TimeSpan elapsed = default(TimeSpan),
|
|
Tuple<string, object>[] extraProperties = null,
|
|
int deepIn = 0)
|
|
{
|
|
try
|
|
{
|
|
if (padding == 0)
|
|
{
|
|
if (!elapsed.Equals(TimeSpan.Zero))
|
|
{
|
|
var elapsedFormated = string.Format("_{0}_", elapsed);
|
|
_writer.WriteLine(elapsedFormated +
|
|
new string('_', Console.BufferWidth - elapsedFormated.Length));
|
|
}
|
|
else
|
|
{
|
|
_writer.WriteLine(new string('_', Console.BufferWidth));
|
|
}
|
|
|
|
_writer.WriteLine("({0}) {{", obj.GetType().Name);
|
|
}
|
|
|
|
if (obj.GetType().IsValueType || obj is string)
|
|
{
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + obj);
|
|
}
|
|
else if (obj is IEnumerable)
|
|
{
|
|
var i = 0;
|
|
|
|
foreach (var arrayItem in (IEnumerable) obj)
|
|
{
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "[{0}]: ({1}) {{", i,
|
|
arrayItem?.GetType().Name);
|
|
WriteObject(arrayItem, padding + 1, default(TimeSpan), null, deepIn - 1);
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var propertyInfo in obj.GetType().GetProperties().OrderBy(info => info.Name))
|
|
{
|
|
if (propertyInfo.CanRead)
|
|
{
|
|
object value;
|
|
|
|
try
|
|
{
|
|
value = propertyInfo.GetValue(obj);
|
|
}
|
|
catch (TargetInvocationException ex)
|
|
{
|
|
value = ex.InnerException?.GetType().ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
value = ex.GetType().ToString();
|
|
}
|
|
|
|
if (deepIn > 0 &&
|
|
value != null &&
|
|
!value.GetType().IsValueType &&
|
|
value.GetType() != typeof(string))
|
|
{
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", propertyInfo.Name,
|
|
propertyInfo.PropertyType.Name);
|
|
WriteObject(value, padding + 1, default(TimeSpan), null, deepIn - 1);
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
|
|
}
|
|
else
|
|
{
|
|
_writer.WriteLine(
|
|
$"{new string(' ', padding * 3 + 2)}{propertyInfo.Name}: {value ?? "[NULL]"},");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (extraProperties != null)
|
|
{
|
|
foreach (var extraProperty in extraProperties)
|
|
{
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", extraProperty.Item1,
|
|
extraProperty.Item2?.GetType().Name);
|
|
WriteObject(extraProperty.Item2, padding + 1, default(TimeSpan), null, deepIn);
|
|
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
|
|
}
|
|
}
|
|
|
|
if (padding == 0)
|
|
{
|
|
_writer.WriteLine("};");
|
|
_writer.WriteLine(new string('_', Console.BufferWidth));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteException(ex);
|
|
}
|
|
}
|
|
}
|
|
} |