Skip to content

Commit

Permalink
Merge pull request #2 from Xorcist77/Commandline
Browse files Browse the repository at this point in the history
Commandline Parameter Implementation
  • Loading branch information
Xorcist77 authored Jun 7, 2024
2 parents 2757ab0 + 3f8ea85 commit 437e3ed
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 31 deletions.
4 changes: 2 additions & 2 deletions App.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<appSettings>
<add key="PollingRate.ms" value="5" />
<add key="SystemInfo.show" value="true" />
<add key="Polling-Rate" value="5" />
<add key="Display-Info" value="True" />
</appSettings>
</configuration>
3 changes: 3 additions & 0 deletions FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
141 changes: 141 additions & 0 deletions FodyWeavers.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
127 changes: 102 additions & 25 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Binding;
using System.CommandLine.Builder;
using System.CommandLine.Help;
using System.CommandLine.Parsing;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Stateus {
Expand All @@ -26,15 +32,15 @@ static String HandleUnknown(Object val) {

static String MemTypeMap(Int32 memType) {
switch (memType) {
case 1: return "Other";
case 2: return "DRAM";
case 3: return "DRAM (Synchronous)";
case 4: return "DRAM (Cache)";
case 5: return "EDO";
case 6: return "EDRAM";
case 7: return "VRAM";
case 8: return "SRAM";
case 9: return "RAM";
case 1: return "Other";
case 2: return "DRAM";
case 3: return "DRAM (Synchronous)";
case 4: return "DRAM (Cache)";
case 5: return "EDO";
case 6: return "EDRAM";
case 7: return "VRAM";
case 8: return "SRAM";
case 9: return "RAM";
case 10: return "ROM";
case 11: return "FLASH";
case 12: return "EEPROM";
Expand Down Expand Up @@ -88,22 +94,93 @@ static String KeyCodeMap(Keys keyCode, Boolean showCode) {
return keyFace;
}

static void Main(String[] args) {
//Process Config Options
Int32 PollingRate;
if (Int32.TryParse(ConfigurationManager.AppSettings["PollingRate.ms"], out PollingRate)) {
if (PollingRate <= 0) {
PollingRate = 5;
}
} else {
PollingRate = 5;

public class AppOptions {
public Int32 PollingRate { get; set; }
public Boolean DisplayInfo { get; set; }
}

public class AppOptionsBinder : BinderBase<AppOptions> {
private readonly Option<Int32> _pollingRateOption;
private readonly Option<String> _displayInfoOption;

public AppOptionsBinder(Option<Int32> pollingRateOption, Option<String> displayInfoOption) {
_pollingRateOption = pollingRateOption;
_displayInfoOption = displayInfoOption;
}

Boolean SystemInfo;
if (!Boolean.TryParse(ConfigurationManager.AppSettings["SystemInfo.show"], out SystemInfo)) {
SystemInfo = false;
protected override AppOptions GetBoundValue(System.CommandLine.Binding.BindingContext bindingContext) {
return new AppOptions {
PollingRate = bindingContext.ParseResult.GetValueForOption(_pollingRateOption),
DisplayInfo = Boolean.Parse(bindingContext.ParseResult.GetValueForOption(_displayInfoOption))
};
}

}

static async Task<Int32> Main(String[] args) {
Option<Int32> pollingRateOption = new Option<Int32>(
aliases: new[] { "-r", "--Polling-Rate" },
description: "Millisecond interval at which devices are polled",
isDefault: true,
parseArgument: result => {
Int32 pr;
if (!result.Tokens.Any()) { //No value passed to option (or option not specified)
if (!Int32.TryParse(ConfigurationManager.AppSettings["Polling-Rate"], out pr)) {
pr = 5;
}
} else {
if (!Int32.TryParse(result.Tokens.Single().Value, out pr)) {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
}
}
if (pr < 1 || pr > 1000) {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
}
return pr;
}
);
pollingRateOption.ArgumentHelpName = "1-1000";
pollingRateOption.Arity = ArgumentArity.ExactlyOne;

Option<String> displayInfoOption = new Option<String>(
aliases: new[] { "-i", "--Display-Info" },
description: "Flag to show or hide hardware information header",
isDefault: true,
parseArgument: result => {
Boolean di;
if (!result.Tokens.Any()) {
if (!Boolean.TryParse(ConfigurationManager.AppSettings["Display-Info"], out di)) {
di = true;
}
} else {
if (!Boolean.TryParse(result.Tokens.Single().Value, out di)) {
result.ErrorMessage = "Display-Info must be True or False";
}
}
return di.ToString();
}
);
displayInfoOption.ArgumentHelpName = "True|False";
displayInfoOption.Arity = ArgumentArity.ExactlyOne;

RootCommand rootCommand = new RootCommand("Simple Windows Keyboard & Mouse \"State Monitor\" with Logging");
rootCommand.AddOption(pollingRateOption);
rootCommand.AddOption(displayInfoOption);
rootCommand.SetHandler((appOptions) => {
Run(appOptions);
}, new AppOptionsBinder(pollingRateOption, displayInfoOption));

Parser parser = new CommandLineBuilder(rootCommand)
.UseDefaults()
.UseHelp(ctx => {
ctx.HelpBuilder.CustomizeSymbol(pollingRateOption, secondColumnText: $"{pollingRateOption.Description} [default: 5]");
ctx.HelpBuilder.CustomizeSymbol(displayInfoOption, secondColumnText: $"{displayInfoOption.Description} [default: True]");
}).Build();

return await parser.InvokeAsync(args);
}

static void Run(AppOptions appOptions) {
//Read Assembly Info
String AppName = Assembly.GetEntryAssembly().GetName().Name;
String AppVers = Assembly.GetEntryAssembly().GetName().Version.ToString();
Expand All @@ -116,7 +193,7 @@ static void Main(String[] args) {
File.AppendAllText(FileName, initString + Environment.NewLine + Environment.NewLine);

//System Information
if (SystemInfo) {
if (appOptions.DisplayInfo) {
String info = String.Empty;
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_BaseBoard")) {
foreach (ManagementObject obj in searcher.Get()) {
Expand Down Expand Up @@ -185,12 +262,12 @@ static void Main(String[] args) {
IEnumerable<Keys> scanCodes = Enum.GetValues(typeof(Keys)).Cast<Keys>().Except(new Keys[] { Keys.Menu, Keys.ControlKey, Keys.ShiftKey });

//Start main polling loop
String pollString = $"Started! Monitoring {scanCodes.Count()} possible scan codes... (polling rate = {PollingRate}ms)";
String pollString = $"Started! Monitoring {scanCodes.Count()} possible scan codes... (polling rate = {appOptions.PollingRate}ms)";
Console.WriteLine(pollString + Environment.NewLine);
File.AppendAllText(FileName, pollString + Environment.NewLine + Environment.NewLine);
while (true) {
//Sleep based on polling rate
Thread.Sleep(PollingRate);
Thread.Sleep(appOptions.PollingRate);

//Read current input state
foreach (Keys k in scanCodes) {
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.1.0")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
12 changes: 12 additions & 0 deletions Stateus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
Expand All @@ -40,6 +41,7 @@
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
Expand All @@ -59,5 +61,15 @@
<ItemGroup>
<Content Include="Stateus.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Costura.Fody">
<Version>5.7.0</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.CommandLine">
<Version>2.0.0-beta4.22272.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
4 changes: 2 additions & 2 deletions Stateus.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31515.178
# Visual Studio Version 17
VisualStudioVersion = 17.10.34928.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stateus", "Stateus.csproj", "{EE427169-8088-472C-8821-508152B488DC}"
EndProject
Expand Down

0 comments on commit 437e3ed

Please sign in to comment.