diff --git a/BinaryDetail.cs b/BinaryDetail.cs
index 66b3d0d..f8a0b0e 100644
--- a/BinaryDetail.cs
+++ b/BinaryDetail.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
@@ -9,12 +8,12 @@ namespace BinaryDetailer
[Serializable]
public class BinaryDetail
{
-
public BinaryDetail(FileInfo fileInfo)
{
FileInfo = fileInfo;
}
+ public string GroupId { get; internal set; }
public string Error { get; internal set; }
public FileInfo FileInfo { get; internal set; }
public ImageFileMachine ImageFileMachine { get; internal set; }
@@ -23,30 +22,26 @@ public BinaryDetail(FileInfo fileInfo)
public ProcessorArchitecture ProcessorArchitecture { get; internal set; }
public string TargetFrameworkAttribute { get; internal set; }
public string AssemblyVersion { get; internal set; }
-
public string FileVersion => FileVersionInfo.GetVersionInfo(FileInfo.FullName).FileVersion;
-
public string ProductVersion => FileVersionInfo.GetVersionInfo(FileInfo.FullName).ProductVersion;
-
public string AssemblyCompanyAttribute => FileVersionInfo.GetVersionInfo(FileInfo.FullName).CompanyName;
public string AssemblyCopyrightAttribute => FileVersionInfo.GetVersionInfo(FileInfo.FullName).LegalCopyright;
-
public static string[] CSVHeader
{
get
{
return new[]
{
- "Full Path,FileName,AssemblyCompanyAttribute,AssemblyCopyrightAttribute,AssemblyVersion,FileVersion,ProductVersion,ImageRuntimeVersion,TargetFrameworkAttribute,PortableExecutableKinds,ImageFileMachine,ProcessorArchitecture,Error"
+ "Group Id, Full Path,FileName,AssemblyCompanyAttribute,AssemblyCopyrightAttribute,AssemblyVersion,FileVersion,ProductVersion,ImageRuntimeVersion,TargetFrameworkAttribute,PortableExecutableKinds,ImageFileMachine,ProcessorArchitecture,Error"
};
}
}
-
public string ToCsv()
{
return
+ "\"" + GroupId + "\"," +
"\"" + FileInfo.FullName + "\"," +
"\"" + FileInfo.Name + "\"," +
"\"" + AssemblyCompanyAttribute + "\"," +
diff --git a/BinaryDetailFactory.cs b/BinaryDetailFactory.cs
index a47321a..58feb1a 100644
--- a/BinaryDetailFactory.cs
+++ b/BinaryDetailFactory.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
@@ -77,7 +76,6 @@ private AppDomain BuildChildDomain(AppDomain parentDomain)
evidence, setup);
}
-
private class BinaryDetailPopulator : MarshalByRefObject
{
[SuppressMessage("Microsoft.Performance",
diff --git a/BinaryDetailer.csproj b/BinaryDetailer.csproj
index dcb669e..62c3dc4 100644
--- a/BinaryDetailer.csproj
+++ b/BinaryDetailer.csproj
@@ -33,12 +33,16 @@
4
+
+
+
+
@@ -50,6 +54,12 @@
1.5.1
+
+ 15.0.4797.1004
+
+
+
+
diff --git a/Export.cs b/Export.cs
new file mode 100644
index 0000000..c9f40ed
--- /dev/null
+++ b/Export.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Linq;
+
+// Use of this library requires an install of Microsoft office
+using Microsoft.Office.Interop.Word;
+
+namespace BinaryDetailer
+{
+ public class Export
+ {
+ readonly List ExcludeNames = new List();
+
+ public Export(List excludeNames)
+ {
+ ExcludeNames = excludeNames;
+ }
+
+ public void GroupBinary(List binaryDetails, string xmlFilePath)
+ {
+ try
+ {
+ // Load xml config file
+ XDocument xmlDoc = XDocument.Load(xmlFilePath);
+
+ // Loop through the binaries
+ foreach (var binaryDetail in binaryDetails)
+ {
+ // Set an escape from the loop once match is found
+ bool groupIdSet = false;
+
+ // Loop through each "group" element. I.E Company name
+ foreach (XElement group in xmlDoc.Root.Elements("group"))
+ {
+ if (groupIdSet == true) break;
+
+ string groupName = group.Attribute("name").Value;
+
+ // Check if the binary has a match in the config xml
+ if (binaryDetail.AssemblyCompanyAttribute == groupName)
+ {
+ // Loop through each "dll" element in the matching group
+ // It is neccessarry to find the group first. It is possible a dll could be used in
+ // another library in which case a license check needs to be done.
+ foreach (XElement dll in group.Elements("dll"))
+ {
+ // Check if the "dllname" attribute matches a "FileInfo.Name"
+ string dllName = dll.Attribute("dllname")?.Value ?? dll.Value;
+
+ // If the dll in the config matches, set groupid
+ if (binaryDetail.FileInfo.Name == dllName)
+ {
+ binaryDetail.GroupId = groupName;
+ groupIdSet = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // If nothing matches
+ binaryDetail.GroupId = "Unknown";
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+
+ public void CreateReport(List binaryDetails)
+ {
+ string csvFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ Guid.NewGuid() + ".csv");
+
+ File.Create(csvFileName).Close();
+ File.AppendAllLines(csvFileName, BinaryDetail.CSVHeader);
+
+ foreach (var binaryDetail in binaryDetails)
+ {
+ bool include = true;
+ foreach (string excludeName in ExcludeNames)
+ {
+ if ((binaryDetail.AssemblyCompanyAttribute != null && binaryDetail.AssemblyCompanyAttribute.ToLower().Contains(excludeName)) ||
+ (binaryDetail.AssemblyCopyrightAttribute != null && binaryDetail.AssemblyCopyrightAttribute.ToLower().Contains(excludeName)))
+ {
+ include = false;
+ }
+ }
+
+ if (include == false) continue;
+
+ File.AppendAllLines(csvFileName, new[] { binaryDetail.ToCsv() });
+ }
+
+ Console.WriteLine("File created at " + csvFileName);
+ }
+
+ public void CreateWordDoc(List binaryDetails)
+ {
+ try
+ {
+ string wordFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ Guid.NewGuid() + ".docx");
+
+ // Create an instance for word app
+ Application winword = new Application
+ {
+ ShowAnimation = false,
+ Visible = false
+ };
+
+ // Create a missing variable for missing value
+ object missing = Missing.Value;
+
+ // Create a new document
+ Document document = winword.Documents.Add(ref missing, ref missing, ref missing, ref missing);
+ document.PageSetup.Orientation = WdOrientation.wdOrientLandscape;
+
+ // Add header into the document
+ foreach (Section section in document.Sections)
+ {
+ //Get the header range and add the header details.
+ Range headerRange = section.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
+ headerRange.Fields.Add(headerRange, WdFieldType.wdFieldPage);
+ headerRange.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
+ headerRange.Font.ColorIndex = WdColorIndex.wdBlue;
+ headerRange.Font.Size = 10;
+ headerRange.Text = "Binary Detailer";
+ }
+
+ // Add the footers into the document
+ foreach (Section wordSection in document.Sections)
+ {
+ //Get the footer range and add the footer details.
+ Range footerRange = wordSection.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
+ footerRange.Font.ColorIndex = WdColorIndex.wdDarkRed;
+ footerRange.Font.Size = 10;
+ footerRange.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
+ footerRange.Text = "Github repository: https://github.com/stuartjsmith/binarydetailer";
+ }
+
+ // Adding text to document
+ document.Content.SetRange(0, 0);
+ string firstLine = "Binary Detailer is a method of outputting binary details such as net framework, " +
+ "64-bit compatibility, version etc. Given a directory name, it will iterate dll and exe files " +
+ "and output the results to a csv file.";
+
+ document.Content.Text = firstLine + Environment.NewLine;
+
+ // Add paragraph with Heading 1 style
+ Paragraph para1 = document.Content.Paragraphs.Add(ref missing);
+ object styleHeading1 = "Heading 1";
+ para1.Range.set_Style(ref styleHeading1);
+ para1.Range.Text = "Binary Details";
+ para1.Range.InsertParagraphAfter();
+
+ // Create a table
+ Table table = document.Tables.Add(para1.Range, binaryDetails.Count + 1, 5, ref missing, ref missing);
+
+ // Define column headings
+ WordColumnHeadings(table);
+
+ // Add table borders
+ table.Borders.Enable = 1;
+
+ // Loop through each binary and add to the table.
+ foreach (var binaryDetail in binaryDetails.Select((value, i) => new { i, value }))
+ {
+ bool include = true;
+
+ foreach (string excludeName in ExcludeNames)
+ {
+ if ((binaryDetail.value.AssemblyCompanyAttribute != null && binaryDetail.value.AssemblyCompanyAttribute.ToLower().Contains(excludeName)) ||
+ (binaryDetail.value.AssemblyCopyrightAttribute != null && binaryDetail.value.AssemblyCopyrightAttribute.ToLower().Contains(excludeName)))
+ {
+ include = false;
+ }
+ }
+
+ if (include == false) continue;
+
+ // Passing the index + 2 as there is a heading column to overcome.
+ WordRowData(binaryDetail.i + 2, table, binaryDetail.value);
+ }
+
+ //Save the document
+ object filename = wordFileName;
+ document.SaveAs2(ref filename);
+ document.Close(ref missing, ref missing, ref missing);
+ document = null;
+ winword.Quit(ref missing, ref missing, ref missing);
+ winword = null;
+
+ Console.WriteLine("Word Document created at " + filename);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+
+ public void WordColumnHeadings(Table firstTable)
+ {
+ // Loop through each cell in the row
+ foreach (Cell cell in firstTable.Rows[1].Cells)
+ {
+ // Switch between the columns
+ switch (cell.ColumnIndex)
+ {
+ case 1:
+ cell.Range.Text = "Group ID";
+ break;
+ case 2:
+ cell.Range.Text = "Company Name";
+ break;
+ case 3:
+ cell.Range.Text = "File Name";
+ break;
+ case 4:
+ cell.Range.Text = "Assembly Version";
+ break;
+ case 5:
+ cell.Range.Text = "File Version";
+ break;
+ }
+
+ // Format properties goes here
+ cell.Range.Font.Bold = 1;
+ cell.Range.Font.Name = "verdana";
+ cell.Range.Font.Size = 10;
+
+ // Cell shading
+ cell.Shading.BackgroundPatternColor = WdColor.wdColorGray25;
+
+ // Center alignment for the Header cells
+ cell.VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
+ cell.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
+ }
+ }
+
+ public void WordRowData(int index, Table firstTable, BinaryDetail binaryDetail)
+ {
+ // Loop through each cell in the row
+ foreach (Cell cell in firstTable.Rows[index].Cells)
+ {
+ // Switch between the columns
+ switch (cell.ColumnIndex)
+ {
+ case 1:
+ cell.Range.Text = binaryDetail.GroupId;
+ break;
+ case 2:
+ cell.Range.Text = binaryDetail.AssemblyCompanyAttribute;
+ break;
+ case 3:
+ cell.Range.Text = binaryDetail.FileInfo.Name;
+ break;
+ case 4:
+ cell.Range.Text = binaryDetail.AssemblyVersion;
+ break;
+ case 5:
+ cell.Range.Text = binaryDetail.FileVersion;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/GroupingConfigExample.xml b/GroupingConfigExample.xml
new file mode 100644
index 0000000..0b7bb32
--- /dev/null
+++ b/GroupingConfigExample.xml
@@ -0,0 +1,17 @@
+
+
+
+ Infragistics.Documents.Core.dll
+
+
+ Microsoft.Build.Tasks.Core.resources.dll
+
+
+
+
+
+
+
+
+
+
diff --git a/Program.cs b/Program.cs
index cae61da..eac8dde 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,20 +1,18 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Text.RegularExpressions;
namespace BinaryDetailer
{
internal class Program
{
- private static string currentBinary = string.Empty;
private static List ExcludeNames = new List();
-
+
private static void Main(string[] args)
{
+ List groupedStrings = new List();
+
string path = args[0];
if (args.Length > 0)
{
@@ -24,6 +22,8 @@ private static void Main(string[] args)
}
}
+ Export ex = new Export(ExcludeNames);
+
List binaryDetails = new List();
IEnumerable allFiles = GetFiles(path, new[] { "*.dll", "*.exe" }, SearchOption.AllDirectories);
@@ -33,34 +33,36 @@ private static void Main(string[] args)
binaryDetails.Add(bd);
}
- CreateReport(binaryDetails);
- Console.In.ReadLine();
- }
-
- private static void CreateReport(List binaryDetails)
- {
- string fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
- Guid.NewGuid() + ".csv");
- File.Create(fileName).Close();
- File.AppendAllLines(fileName, BinaryDetail.CSVHeader);
- foreach (var binaryDetail in binaryDetails)
+ if (args.Length > 1)
{
- bool include = true;
- foreach (string excludeName in ExcludeNames)
+ foreach (var arg in args.Select((value, i) => new { i, value }))
{
- if ((binaryDetail.AssemblyCompanyAttribute != null && binaryDetail.AssemblyCompanyAttribute.ToLower().Contains(excludeName)) ||
- (binaryDetail.AssemblyCopyrightAttribute != null && binaryDetail.AssemblyCopyrightAttribute.ToLower().Contains(excludeName)))
+ var index = arg.i;
+
+ // Skip the first arg as this is the path to report on
+ if (index.Equals(0)) continue;
+
+ if (arg.value.ToLower().Equals("doc"))
+ {
+ // Create word document
+ ex.CreateWordDoc(binaryDetails);
+ }
+ else if (arg.value.ToLower().Equals("config"))
{
- include = false;
+ // Create a binary grouping based on a config.
+ ex.GroupBinary(binaryDetails, args[index+1]);
+ ex.CreateReport(binaryDetails);
}
}
-
- if (include == false) continue;
-
- File.AppendAllLines(fileName, new[] { binaryDetail.ToCsv() });
+ }
+ else
+ {
+ // Raw report
+ ex.CreateReport(binaryDetails);
}
- Console.WriteLine("File created at " + fileName);
+ Console.WriteLine("Export complete");
+ Console.In.ReadLine();
}
private static IEnumerable GetFiles(string path,
@@ -72,4 +74,4 @@ private static IEnumerable GetFiles(string path,
Directory.EnumerateFiles(path, searchPattern, searchOption));
}
}
-}
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index d7ca456..7b5ba2d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Binary Detailer
-Binary Detailer is a method of outputing binary details such as net framework, 64 bit compatibility, version etc. Given a directory name, it will iterate dll and exe files and output the results to a csv file.
+Binary Detailer is a method of outputting binary details such as net framework, 64-bit compatibility, version etc. Given a directory name, it will iterate dll and exe files and output the results to a csv file.
___
### Usage
@@ -18,6 +18,13 @@ ___

___
+### Arguments
+
+'config' - This requires an XML passed after the config argument. This will compare the binaries against the XML and group common binaries together. See "GroupingConfigExample.xml"
+'doc' - This will create a word document table of the data. This requires a Microsoft Office install on the machine executing.
+
+Example argument: BinaryDetailer.exe "C:\Program Files\dotnet\sdk\6.0.400" config "C:\BinaryDetailer\GroupingConfigExample.xml" doc
+
## Contribute
Congratulations! You’re up and running. Now you can begin using and contributing your fixes and new features to the project.