How to find all the hardcoded values in a C# project(solution)? - c#

This question is not asking about hard coded strings only, but magic numbers etc. as well.
Is there a way to find all the hard coded values i.e. string , magic numbers and what not in C# project/solution in VS?
What prompted this question is a project that I am looking at, I just found 174 times a string value was hardcodely repeated!

What you could do is program Roslyn, the (not so) new cool kid in town. It allows you to parse C# (or VB.NET) projects quite easily. Then you can visit the detected nodes and check what you really want to check. Detecting magic literals for a machine is not always as easy as it seems for a human. For example, is 1 really a magic number? I personally consider it's not, but 2 is more suspect...
Anyway, here is a small sample that does a good part of the job I believe, but it could/should be improved, maybe to tailor your exact business needs or rules (which is very interesting).
Note Roslyn can also be used directly in the context of Visual Studio, so you could turn this sample into what's called a diagnostic (an extension to Visual Studio) that can help you directly live from within the IDE. There are samples for this: Samples and Walkthroughs
class Program
{
static void Main(string[] args)
{
var text = #"
public class MyClass
{
public void MyMethod()
{
const int i = 0; // this is ok
decimal d = 11; // this is not ok
string s = ""magic"";
if (i == 29) // another magic
{
}
else if (s != ""again another magic"")
{
}
}
}";
ScanHardcodedFromText("test.cs", text, (n, s) =>
{
Console.WriteLine(" " + n.SyntaxTree.GetLineSpan(n.FullSpan) + ": " + s);
}).Wait();
}
public static async Task ScanHardcodedFromText(string documentName, string text, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (text == null)
throw new ArgumentNullException("text");
AdhocWorkspace ws = new AdhocWorkspace();
var project = ws.AddProject(documentName + "Project", LanguageNames.CSharp);
ws.AddDocument(project.Id, documentName, SourceText.From(text));
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcodedFromSolution(string solutionFilePath, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (solutionFilePath == null)
throw new ArgumentNullException("solutionFilePath");
var ws = MSBuildWorkspace.Create();
await ws.OpenSolutionAsync(solutionFilePath);
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcodedFromProject(string solutionFilePath, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (solutionFilePath == null)
throw new ArgumentNullException("solutionFilePath");
var ws = MSBuildWorkspace.Create();
await ws.OpenProjectAsync(solutionFilePath);
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcoded(Workspace workspace, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (workspace == null)
throw new ArgumentNullException("workspace");
if (scannedFunction == null)
throw new ArgumentNullException("scannedFunction");
foreach (var project in workspace.CurrentSolution.Projects)
{
foreach (var document in project.Documents)
{
var tree = await document.GetSyntaxTreeAsync();
var root = await tree.GetRootAsync();
foreach (var n in root.DescendantNodesAndTokens())
{
if (!CanBeMagic(n.Kind()))
continue;
if (IsWellKnownConstant(n))
continue;
string suggestion;
if (IsMagic(n, out suggestion))
{
scannedFunction(n, suggestion);
}
}
}
}
}
public static bool IsMagic(SyntaxNodeOrToken kind, out string suggestion)
{
var vdec = kind.Parent.Ancestors().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (vdec != null)
{
var dec = vdec.Parent as MemberDeclarationSyntax;
if (dec != null)
{
if (!HasConstOrEquivalent(dec))
{
suggestion = "member declaration could be const: " + dec.ToFullString();
return true;
}
}
else
{
var ldec = vdec.Parent as LocalDeclarationStatementSyntax;
if (ldec != null)
{
if (!HasConstOrEquivalent(ldec))
{
suggestion = "local declaration contains at least one non const value: " + ldec.ToFullString();
return true;
}
}
}
}
else
{
var expr = kind.Parent.Ancestors().OfType<ExpressionSyntax>().FirstOrDefault();
if (expr != null)
{
suggestion = "expression uses a non const value: " + expr.ToFullString();
return true;
}
}
// TODO: add other cases?
suggestion = null;
return false;
}
private static bool IsWellKnownConstant(SyntaxNodeOrToken node)
{
if (!node.IsToken)
return false;
string text = node.AsToken().Text;
if (text == null)
return false;
// note: this is naïve. we also should add 0d, 0f, 0m, etc.
if (text == "1" || text == "-1" || text == "0")
return true;
// ok for '\0' or '\r', etc.
if (text.Length == 4 && text.StartsWith("'\\") && text.EndsWith("'"))
return true;
if (text == "' '")
return true;
// TODO add more of these? or make it configurable...
return false;
}
private static bool HasConstOrEquivalent(SyntaxNode node)
{
bool hasStatic = false;
bool hasReadOnly = false;
foreach (var tok in node.ChildTokens())
{
switch (tok.Kind())
{
case SyntaxKind.ReadOnlyKeyword:
hasReadOnly = true;
if (hasStatic)
return true;
break;
case SyntaxKind.StaticKeyword:
hasStatic = true;
if (hasReadOnly)
return true;
break;
case SyntaxKind.ConstKeyword:
return true;
}
}
return false;
}
private static bool CanBeMagic(SyntaxKind kind)
{
return kind == SyntaxKind.CharacterLiteralToken ||
kind == SyntaxKind.NumericLiteralToken ||
kind == SyntaxKind.StringLiteralToken;
}
}
If you run this little program (I've also provided helper methods to use it on solution or projects), it will output this:
test.cs: (6,20)-(6,22): local declaration contains at least one non const value: decimal d = 11; // this is not ok
test.cs: (7,19)-(7,26): local declaration contains at least one non const value: string s = "magic";
test.cs: (8,17)-(8,19): expression uses a non const value: i == 29
test.cs: (11,22)-(11,43): expression uses a non const value: s != "again another magic"

I have some code which can find magic numbers and hard coded non-constant strings. May be that can help someone -
/// <summary>
/// Scans all cs files in the solutions for magic strings and numbers using the Roslyn
/// compiler and analyzer tools.
/// Based upon a Roslyn code sample.
/// </summary>
class MagicStringAnalyzer
{
protected static Filter filter;
static void Main(string[] args)
{
string outputPath = #"E:\output.txt";
string solutionPath = #"E:\Solution.sln";
filter = new Filter(#"E:\IgnorePatterns.txt");
if (File.Exists(outputPath))
{
OverWriteFile(outputPath);
}
analyzeSolution(outputPath, solutionPath);
}
protected static void loadFilters()
{
}
private static void OverWriteFile(string path)
{
Console.WriteLine("Do you want to overwrite existing output file? (y/n)");
if (Console.ReadKey().Key == ConsoleKey.Y)
{
File.Delete(path);
Console.WriteLine("");
}
else
{
Environment.Exit(-1);
}
}
public static void analyzeSolution(string outputPath, string solutionPath)
{
Console.WriteLine("Analyzing file...");
System.IO.StreamWriter writer = new System.IO.StreamWriter(outputPath);
ScanHardcodedFromSolution(solutionPath, (n, s) =>
{
string syntaxLineSpan = n.SyntaxTree.GetLineSpan(n.FullSpan).ToString();
if (!filter.IsMatch(syntaxLineSpan))
{
writer.WriteLine(" " + syntaxLineSpan + ": \r\n" + s + "\r\n\r\n");
}
}).Wait();
writer.Close();
}
public static async Task ScanHardcodedFromText(string documentName, string text, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (text == null)
throw new ArgumentNullException("text");
AdhocWorkspace ws = new AdhocWorkspace();
var project = ws.AddProject(documentName + "Project", LanguageNames.CSharp);
ws.AddDocument(project.Id, documentName, SourceText.From(text));
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcodedFromSolution(string solutionFilePath, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (solutionFilePath == null)
throw new ArgumentNullException("solutionFilePath");
var ws = MSBuildWorkspace.Create();
await ws.OpenSolutionAsync(solutionFilePath);
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcodedFromProject(string solutionFilePath, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (solutionFilePath == null)
throw new ArgumentNullException("solutionFilePath");
var ws = MSBuildWorkspace.Create();
await ws.OpenProjectAsync(solutionFilePath);
await ScanHardcoded(ws, scannedFunction);
}
public static async Task ScanHardcoded(Workspace workspace, Action<SyntaxNodeOrToken, string> scannedFunction)
{
if (workspace == null)
throw new ArgumentNullException("workspace");
if (scannedFunction == null)
throw new ArgumentNullException("scannedFunction");
foreach (var project in workspace.CurrentSolution.Projects)
{
foreach (var document in project.Documents)
{
var tree = await document.GetSyntaxTreeAsync();
var root = await tree.GetRootAsync();
foreach (var n in root.DescendantNodesAndTokens())
{
if (!CanBeMagic(n.Kind()))
continue;
if (IsWellKnownConstant(n))
continue;
string suggestion;
if (IsMagic(n, out suggestion))
{
scannedFunction(n, suggestion);
}
}
}
}
}
public static bool IsMagic(SyntaxNodeOrToken kind, out string suggestion)
{
var vdec = kind.Parent.Ancestors().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (vdec != null)
{
var dec = vdec.Parent as MemberDeclarationSyntax;
if (dec != null)
{
if (!HasConstOrEquivalent(dec))
{
suggestion = "member declaration could be const: " + dec.ToFullString();
return true;
}
}
else
{
var ldec = vdec.Parent as LocalDeclarationStatementSyntax;
if (ldec != null)
{
if (!HasConstOrEquivalent(ldec))
{
suggestion = "local declaration contains at least one non const value: " + ldec.ToFullString();
return true;
}
}
}
}
else
{
var expr = kind.Parent.Ancestors().OfType<ExpressionSyntax>().FirstOrDefault();
if (expr != null)
{
suggestion = "expression uses a non const value: " + expr.ToFullString();
return true;
}
}
// TODO: add other cases?
suggestion = null;
return false;
}
private static bool IsWellKnownConstant(SyntaxNodeOrToken node)
{
if (!node.IsToken)
return false;
string text = node.AsToken().Text;
if (text == null)
return false;
// note: this is naïve. we also should add 0d, 0f, 0m, etc.
if (text == "1" || text == "-1" || text == "0")
return true;
// ok for '\0' or '\r', etc.
if (text.Length == 4 && text.StartsWith("'\\") && text.EndsWith("'"))
return true;
if (text == "' '")
return true;
if (text == "")
return true;
return false;
}
private static bool HasConstOrEquivalent(SyntaxNode node)
{
bool hasStatic = false;
bool hasReadOnly = false;
foreach (var tok in node.ChildTokens())
{
switch (tok.Kind())
{
case SyntaxKind.ReadOnlyKeyword:
hasReadOnly = true;
if (hasStatic)
return true;
break;
case SyntaxKind.StaticKeyword:
hasStatic = true;
if (hasReadOnly)
return true;
break;
case SyntaxKind.ConstKeyword:
return true;
}
}
return false;
}
private static bool CanBeMagic(SyntaxKind kind)
{
return kind == SyntaxKind.CharacterLiteralToken ||
kind == SyntaxKind.NumericLiteralToken ||
kind == SyntaxKind.StringLiteralToken;
}
}
public class Filter
{
protected string[] patterns;
public Filter(string path)
{
loadFilters(path);
}
protected void loadFilters(string path)
{
patterns = File.ReadAllLines(path);
}
public bool IsMatch(string input)
{
foreach (string pattern in patterns)
{
if(Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
{
return true;
}
}
return false;
}
}
Your txt file that contains file names to ignore would contain values like -
Constant.cs
Resoures.Designer.cs
Configuration.cs
Reference.cs
Test
Give name of your solution in solution path and run this. This will generate txt file for you with all hard coded strings and magic numbers.
Edit:
To compile the project, you'll need to install Microsoft.CodeAnalysis NuGet package into your console app project:
Install-Package Microsoft.CodeAnalysis -Pre
Here is a complete list of references you should have in your Program.cs:
using System;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Text;
namespace MagicStringAnalyzer
{
// the rest of the code goes here...
}

Related

Splitting ReadOnlySequence into lines then ReadOnlySequence by delimiters

I am trying to split the following chunked memory into ReadOnlySequence<char> by newline \n and then delimiters (in this example of ").
I have the partially working (by lines) code below which when I tweak I get exceptions, and currently have the incorrect output of: hello, fun, one.
I believe my issues are with my use of ReadOnlySequence.Slice() and SequencePosition, as this seems linked to the position of the starting sequence, and not the start of the sliced ReadOnlySequence (at least as I understand).
I am kindly seeking advice towards a corrected example of the below, so that we get the expected:
hello, much, fun, done.
using System;
using System.Buffers;
namespace NotMuchFunYet
{
class Program
{
static void Main(string[] args)
{
var buffer = GetExampleBuffer();
while (TryReadLine(ref buffer, out var line))
{
while (GetString(ref line, out var token))
{
Console.WriteLine(token.ToString());
}
}
}
private static ReadOnlySequence<char> GetExampleBuffer()
{
Chunk<char> startChnk;
var currentChnk = startChnk = new Chunk<char>(new ReadOnlyMemory<char>("\"hello\".\"mu".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("ch\".".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("\"fun\"".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("\n\"done\"\n".ToCharArray()));
return new ReadOnlySequence<char>(startChnk, 0, currentChnk, currentChnk.Memory.Length);
}
private static bool TryReadLine(ref ReadOnlySequence<char> buffer, out ReadOnlySequence<char> line)
{
var position = buffer.PositionOf('\n'); // Look for a EOL in the buffer.
if (position == null)
{
line = default;
return false;
}
line = buffer.Slice(0, position.Value); // Skip the line + the \n.
buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
return true;
}
public static bool GetString(ref ReadOnlySequence<char> line, out ReadOnlySequence<char> property)
{
var start = line.PositionOf('"');
if (start == null)
{
property = default;
return false;
}
property = line.Slice(start.Value.GetInteger() + 1);
var end = property.PositionOf('"');
if (end == null)
{
property = default;
return false;
}
property = property.Slice(0, end.Value);
line = line.Slice(line.GetPosition(1, end.Value));
return true;
}
}
class Chunk<T> : ReadOnlySequenceSegment<T>
{
public Chunk(ReadOnlyMemory<T> memory) => Memory = memory;
public Chunk<T> Add(ReadOnlyMemory<T> mem)
{
var segment = new Chunk<T>(mem) { RunningIndex = RunningIndex + Memory.Length };
Next = segment;
return segment;
}
}
}
Changing the first property fetch in GetString() method resolves this, from:
property = line.Slice(start.Value.GetInteger() + 1);
To:
property = line.Slice(line.GetPosition(1, start.Value));
Giving the code:
using System;
using System.Buffers;
namespace NowMuchFun
{
class Program
{
static void Main(string[] args)
{
var buffer = GetExampleBuffer();
while (TryReadLine(ref buffer, out var line))
{
while (GetString(ref line, out var token))
{
Console.WriteLine(token.ToString());
}
}
}
private static ReadOnlySequence<char> GetExampleBuffer()
{
Chunk<char> startChnk;
var currentChnk = startChnk = new Chunk<char>(new ReadOnlyMemory<char>("\"hello\".\"mu".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("ch\".".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("\"fun\"".ToCharArray()));
currentChnk = currentChnk.Add(new ReadOnlyMemory<char>("\n\"done\"\n".ToCharArray()));
return new ReadOnlySequence<char>(startChnk, 0, currentChnk, currentChnk.Memory.Length);
}
private static bool TryReadLine(ref ReadOnlySequence<char> buffer, out ReadOnlySequence<char> line)
{
var position = buffer.PositionOf('\n'); // Look for a EOL in the buffer.
if (position == null)
{
line = default;
return false;
}
line = buffer.Slice(0, position.Value); // Skip the line + the \n.
buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
return true;
}
public static bool GetString(ref ReadOnlySequence<char> line, out ReadOnlySequence<char> property)
{
var start = line.PositionOf('"');
if (start == null)
{
property = default;
return false;
}
// property = line.Slice(start.Value.GetInteger() + 1);
// REPLACE WITH BELOW:
property = line.Slice(line.GetPosition(1, start.Value));
var end = property.PositionOf('"');
if (end == null)
{
property = default;
return false;
}
property = property.Slice(0, end.Value);
line = line.Slice(line.GetPosition(1, end.Value));
return true;
}
}
class Chunk<T> : ReadOnlySequenceSegment<T>
{
public Chunk(ReadOnlyMemory<T> memory) => Memory = memory;
public Chunk<T> Add(ReadOnlyMemory<T> mem)
{
var segment = new Chunk<T>(mem) { RunningIndex = RunningIndex + Memory.Length };
Next = segment;
return segment;
}
}
}

How can make my URL checker program faster?

I made a URL checker program which is checked URLs from a list and return valid sub links recursively. It checks all sub links. I have more than 100 main page like this and I would check these sites with all subs. It takes 3 minutes averagely for one site. especially first Html Code (at the sample string "HtmlCode = client.DownloadString(Link);") takes times, the others faster than first. I would run my program repeatedly and it control links and sending me warning for broken links. How could I faster my program?
public Form1()
{
InitializeComponent();
List<KeyValuePair<string, bool>> UrlS = Link_Bul_v2("http://www.asdfhg.com", new List<string>(), new List<KeyValuePair<string, bool>>());
List<KeyValuePair<string, bool>> UrlS2 = Link_Bul_v2("http://www.huuene.com", new List<string>(), new List<KeyValuePair<string, bool>>());
}
string UrlSadelesti(string Link)
{
return Link.Replace("https://", "").Replace("http://", "").Replace("www.", "");
}
WebClient client = new WebClient();
private List<KeyValuePair<string, bool>> Link_Bul_v2(string Link, List<string> HList, List<KeyValuePair<string, bool>> CList)
{
try
{
string HtmlCode = client.DownloadString(Link);
//if(HtmlCode.
CList.Add(new KeyValuePair<string, bool>(Link, true));
var Link_Short = UrlSadelesti(Link).Split('/')[0];
//HList.Add(Link_Short);
string DLink;
int IndexH = 0;
while (true)
{
IndexH = HtmlCode.IndexOf("href", IndexH);
if (IndexH == -1) { break; }
if (HtmlCode[IndexH - 1] == '.')
{
IndexH = IndexH + 1;
}
else
{
var IndexD1 = HtmlCode.IndexOf('"', IndexH);
var IndexD2 = HtmlCode.IndexOf('"', IndexD1 + 1);
var length = IndexD2 - (IndexD1 + 1);
DLink = HtmlCode.Substring(IndexD1 + 1, length);
IndexH = IndexD2;
if ((DLink.Contains(".css") == false))
{
if (DLink.Contains("http://") || DLink.Contains("https://"))
{
if (DLink.Contains(Link_Short) == false)
continue;
}
if (DLink.Contains("#"))
{
continue;
}
DLink = UrlSadelesti(DLink).Replace(Link_Short, "");
if (DLink.Length == 1)
continue;
if (HList.Count(p => p.Contains(DLink)) == 0)
{
if (DLink.Contains("http://") || DLink.Contains("https://"))
{
HList.Add(Link_Short + "/" + DLink);
}
else
{
HList.Add("http://" + Link_Short + "/" + DLink);
}
}
}
}
}
}
catch
{
CList.Add(new KeyValuePair<string, bool>(Link, false));
if (!HList.Contains(Link))
HList.Add(Link);
if (UrlSadelesti(Link).Split('/').Count() > 1)
{
Link_Bul_v2("http://" + UrlSadelesti(Link).Split('/')[0], HList, CList);
}
}
foreach (string s in HList)
{
if (CList.Count(p => p.Key.Contains(s)) == 0)
{
Link_Bul_v2(s, HList, CList);
}
}
return CList;
}
One option would be to check each link in parallel:
How to: Write a Simple Parallel.ForEach Loop
using System.Threading;
using System.Threading.Tasks;
...
Parallel.ForEach(links, (currentLink) =>
{
// Check "currentLink"
});
// All links are checked at this point

Given the object identifier, how do we read the corresponding value from a ASN.1 DER encoded binary file?

I'm trying to read the value corresponding to a object identifier, from a Microsoft security catalog (*.cat) file, which is in fact a DER encoded ASN.1 object. I am using bouncy castle to create a Asn1Object. When I perform a .ToString() I can see my data in ASCII in the dumped text, against the object identifier "1.3.6.1.4.1.311.12.2.1" but is there a way to retrieve the data specifcally by passing this OID?
I see a class Org.BouncyCastle.Asn1.Microsoft, but I am not sure how to use this class. Any help appreciated! So far I have only this, where I call File.ReadAllBytes and pass to the function I've written below, on this I can call ToString() and see all data in the .cat
private Asn1Object asn1Object(byte[] data)
{
Asn1InputStream asn1InputStream = new Asn1InputStream(data);
if(asn1InputStream != null)
{
return asn1InputStream.ReadObject().;
}
else
{
return null;
}
}
The short answer: You would need to recursively walk the tree to find the DerSequence containing the DerObjectIdentifier and then returning the DerObjectIdentifiers next sibling.
The long answer: Looking at the ASN1/DER structure, there doesn't appear to be a single entry in the object graph that has the OID and a value. It appears that for a particular OID, it will be the first child object in a DerSequence and the value will be the second child object.
A recursive method that will find the DerSequence containing the DerObjectIdentifier matching your OID and return you the next sibling is:
public static Asn1Object FindAsn1Value(string oid, Asn1Object obj)
{
Asn1Object result = null;
if (obj is Asn1Sequence)
{
bool foundOID = false;
foreach (Asn1Object entry in (Asn1Sequence)obj)
{
var derOID = entry as DerObjectIdentifier;
if (derOID != null && derOID.Id == oid)
{
foundOID = true;
}
else if (foundOID)
{
return entry;
}
else
{
result = FindAsn1Value(oid, entry);
if (result != null)
{
return result;
}
}
}
}
else if (obj is DerTaggedObject)
{
result = FindAsn1Value(oid, ((DerTaggedObject)obj).GetObject());
if (result != null)
{
return result;
}
}
else
{
if (obj is DerSet)
{
foreach (Asn1Object entry in (DerSet)obj)
{
result = FindAsn1Value(oid, entry);
if (result != null)
{
return result;
}
}
}
}
return null;
}
To call this you would load the Asn1Object using the method you provided, and then call the FindAsn1Value shown above. This should return you the Asn1Object you are after (in the case of my test cat file, this value was a DerOctetString).
Asn1Object asn = asn1Object(File.ReadAllBytes(#"test_file.cat"));
Asn1Object value = FindAsn1Value("1.3.6.1.4.1.311.12.2.1", asn);
if (value is DerOctetString)
{
UnicodeEncoding unicode = new UnicodeEncoding(true, true);
Console.WriteLine("DerOctetString = {0}", unicode.GetString(((DerOctetString)value).GetOctets()));
}
I'm not sure if the value for that OID will always be a DerOctetString nor whether my decoding choice is necessarily correct, however it gave me the most readable version of the value that my test was working with.
Update
If the same OID appears multiple times in the hierarchy and you need to return all the possible values, an alternative method could be:
public static List<Asn1Object> FindAsn1Values(string oid, Asn1Object obj)
{
Asn1Object result = null;
List<Asn1Object> results = new List<Asn1Object>();
if (obj is Asn1Sequence)
{
bool foundOID = false;
foreach (Asn1Object entry in (Asn1Sequence)obj)
{
var derOID = entry as DerObjectIdentifier;
if (derOID != null && derOID.Id == oid)
{
foundOID = true;
}
else if (foundOID)
{
results.Add(entry);
}
else
{
result = FindAsn1Values(oid, entry);
if (result.Count > 0)
{
results.AddRange(result);
}
}
}
}
else if (obj is DerTaggedObject)
{
result = FindAsn1Values(oid, ((DerTaggedObject)obj).GetObject());
if (result.Count > 0)
{
results.AddRange(result);
}
}
else
{
if (obj is DerSet)
{
foreach (Asn1Object entry in (DerSet)obj)
{
result = FindAsn1Values(oid, entry);
if (result.Count > 0)
{
results.AddRange(result);
}
}
}
}
return results;
}

Find exception hiding/swallowing in C# code in VS2013

is there some way built in function/extension/tool to find all exception hidings/exception swallowing in C# solution(ASP.NET WebForms)n in VS2013.
Thanks
EDIT:
I have existing solution in which some programmers use hide/swallow exceptions(empty catch, catch only with some useless code). And I am looking for some way to find all these places in code, analyze them, and then fix them.
You can write some code using Roslyn to handle this pretty easily.
I actually wrote some code to do exactly that for a friend. It was my first attempt at using the Roslyn SDK, so my code is probably a terrible mess, but it was definitely functional.
static void Main(string[] args)
{
var result = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseFile(#"..\..\Test.cs");
var root = result.GetRoot();
var exceptionNodes = FindCatchNodes(root);
foreach (var node in exceptionNodes)
{
var line = node.GetLocation().GetLineSpan().StartLinePosition.Line + 1;
if (IsTotallyEmptyCatch(node))
{
Console.WriteLine("Totally empty catch: line {0}", line);
}
if (JustRethrows(node))
{
Console.WriteLine("Pointless rethrow: line {0}", line);
}
}
}
static List<SyntaxNodeOrToken> FindCatchNodes(SyntaxNodeOrToken node)
{
var exceptions = new List<SyntaxNodeOrToken>();
var isCatchBlock = node.IsKind(SyntaxKind.CatchClause);
if (isCatchBlock)
{
exceptions.Add(node);
}
foreach (var result in node.ChildNodesAndTokens().Select(FindCatchNodes).Where(result => result != null))
{
exceptions.AddRange(result);
}
return exceptions;
}
static bool IsTotallyEmptyCatch(SyntaxNodeOrToken catchBlock)
{
var block = catchBlock.ChildNodesAndTokens().First(t => t.CSharpKind() == SyntaxKind.Block);
var children = block.ChildNodesAndTokens();
return (children.Count == 2 && children.Any(c => c.CSharpKind() == SyntaxKind.OpenBraceToken) &&
children.Any(c => c.CSharpKind() == SyntaxKind.CloseBraceToken));
}
static bool JustRethrows(SyntaxNodeOrToken catchBlock)
{
var block = catchBlock.ChildNodesAndTokens().First(t => t.CSharpKind() == SyntaxKind.Block);
var children = block.ChildNodesAndTokens();
return (children.Count == 3 && children.Any(c => c.CSharpKind() == SyntaxKind.OpenBraceToken) &&
children.Any(c => c.CSharpKind() == SyntaxKind.CloseBraceToken) && children.Any(c=>c.CSharpKind() == SyntaxKind.ThrowStatement));
}
Given this test file:
using System;
namespace RoslynTest
{
public class Test
{
public void Foo()
{
try
{
var x = 0;
}
catch
{
}
}
public void Bar()
{
try
{
var x = 0;
}
catch (Exception ex)
{
throw;
}
}
public void Baz()
{
try
{
var x = 0;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
The output is:
Totally empty catch: ....\Test.cs: line 12
Pointless rethrow: ....\Test.cs: line 24
Pointless rethrow: ....\Test.cs: line 37
I don't know about the built-in methods. But you can write your own tool to find such places. Just regex all your files in solution and count catch and throw. There should be the same amount for each file :)

Scripting in Sound forge

I am completely new to scripting in sound forge. I have a requirement of mixing 2 .wav files.
For example, 1.wav file mix with INVERTED 2.wav file.
I need to get the statistics of the resultant mixed output file.
Statistics like minimum sample value, maximum sample value for all the channels.
Below i have the code to mix 2 .wav files. But the 2nd is not inverted.
Can anyone please help me on the scripting for the above in C#?
Or if anyone can share a document with the standard API's available for sound forge scripting also will be helpful.
using System;
using System.IO;
using System.Windows.Forms;
using System.Collections.Generic;
using SoundForge;
public class EntryPoint
{
public void Begin(IScriptableApp app)
{
//choose the first file.
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "Open the input file.";
String inputFilePath = String.Empty;
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFilePath = openFile.FileName.ToString();
}
OpenFileDialog openOutputFile = new OpenFileDialog();
openOutputFile.Title = "Open the output file.";
String outputFilePath = String.Empty;
if (openOutputFile.ShowDialog() == DialogResult.OK)
{
outputFilePath = openOutputFile.FileName.ToString();
}
ISfFileHost backFile = app.OpenFile(outputFilePath, true, false);
ISfFileHost file = app.OpenFile(inputFilePath, false, false);
long fileLen = file.Length;
SfAudioSelection asel = new SfAudioSelection(file);
file.DoMixReplace(SfAudioSelection.All, 1, 1, backFile, new SfAudioSelection(0, file.Length), null, null, EffectOptions.EffectOnly | EffectOptions.WaitForDoneOrCancel);
backFile.Close(CloseOptions.DiscardChanges);
}
public void FromSoundForge(IScriptableApp app)
{
ForgeApp = app; //execution begins here
app.SetStatusText(String.Format("Script '{0}' is running.", Script.Name));
Begin(app);
app.SetStatusText(String.Format("Script '{0}' is done.", Script.Name));
}
public static IScriptableApp ForgeApp = null;
public static void DPF(string sz) { ForgeApp.OutputText(sz); }
public static void DPF(string fmt, params object[] args) {
ForgeApp.OutputText(String.Format(fmt, args)); }
} //EntryPoint
Using the below code the requirement can be achieved.
Requirement was:
1.wav file mix with INVERTED 2.wav file. Get the statistics of the resultant mixed output file.
Statistics like minimum sample value, maximum sample value for all the channels.
using System;
using System.IO;
using System.Windows.Forms;
using System.Collections.Generic;
using SoundForge;
public class EntryPoint
{
public void Begin(IScriptableApp app)
{
string strOutFile = GETARG("outfile", "path to save file at");
if ("" == strOutFile)
{
MessageBox.Show("invald output path");
return;
}
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "Open the input file.";
////string to hold the path of input file.
String strFile1 = String.Empty;
if (openFile.ShowDialog() == DialogResult.OK)
{
strFile1 = openFile.FileName.ToString();
}
OpenFileDialog openOutputFile = new OpenFileDialog();
openOutputFile.Title = "Open the output file.";
////string to hold the path of output file.
String strFile2 = String.Empty;
if (openOutputFile.ShowDialog() == DialogResult.OK)
{
strFile2 = openOutputFile.FileName.ToString();
}
ISfFileHost fhOne = app.OpenFile(strFile1, true, true);
if (null == fhOne)
return;
ISfFileHost fhTwo = app.OpenFile(strFile2, true, true);
if (null == fhTwo)
{
fhOne.Close(CloseOptions.DiscardChanges);
return;
}
ISfFileHost fhOut = app.NewFile(fhOne.DataFormat, false);
fhOut.ReplaceAudio(new SfAudioSelection(0, 0), fhOne, new SfAudioSelection(fhOne));
fhOut.DoEffect("Invert/Flip", 0, new SfAudioSelection(fhOut), EffectOptions.EffectOnly);
fhOut.WaitForDoneOrCancel();
fhOut.MixAudio(new SfAudioSelection(fhOut), 1.0, 1.0, fhTwo, new SfAudioSelection(fhTwo));
fhOut.WaitForDoneOrCancel();
fhOut.SaveAs(strOutFile, fhOne.SaveFormat.Guid, "Default Template", RenderOptions.RenderOnly);
fhOut.WaitForDoneOrCancel();
fhOne.Close(CloseOptions.DiscardChanges);
fhTwo.Close(CloseOptions.DiscardChanges);
SfAudioStatistics[] stat = new SfAudioStatistics[fhOut.Channels];
fhOut.UpdateStatistics(SfAudioSelection.All);
stat[0] = fhOut.GetStatistics(0);
stat[1] = fhOut.GetStatistics(1);
stat[2] = fhOut.GetStatistics(2);
stat[3] = fhOut.GetStatistics(3);
stat[4] = fhOut.GetStatistics(4);
stat[5] = fhOut.GetStatistics(5);
stat[6] = fhOut.GetStatistics(6);
stat[7] = fhOut.GetStatistics(7);
MessageBox.Show(String.Format("Max Sample Value Channel 1 - {0},Channel 2 - {1},Channel 3 - {2},Channel 4 - {3},Channel 5 - {4},Channel 6 - {5},Channel 7 - {6},Channel 8 - {7}", stat[0].MaxValue, stat[1].MaxValue, stat[2].MaxValue, stat[3].MaxValue, stat[4].MaxValue, stat[5].MaxValue, stat[6].MaxValue, stat[7].MaxValue));
MessageBox.Show(String.Format("Min Sample Value Channel 1 - {0},Channel 2 - {1},Channel 3 - {2},Channel 4 - {3},Channel 5 - {4},Channel 6 - {5}, Channel 7 - {6}, Channel 8 - {7}", stat[0].MinValue, stat[1].MinValue, stat[2].MinValue, stat[3].MinValue, stat[4].MaxValue, stat[5].MinValue, stat[6].MinValue, stat[7].MinValue));
System.Diagnostics.Process curr = System.Diagnostics.Process.GetCurrentProcess();
}
public void FromSoundForge(IScriptableApp app)
{
ForgeApp = app; //execution begins here
app.SetStatusText(String.Format("Script '{0}' is running.", Script.Name));
Begin(app);
app.SetStatusText(String.Format("Script '{0}' is done.", Script.Name));
}
public static IScriptableApp ForgeApp = null;
public static void DPF(string sz) { ForgeApp.OutputText(sz); }
public static void DPF(string fmt, object o) { ForgeApp.OutputText(String.Format(fmt, o)); }
public static void DPF(string fmt, object o, object o2) { ForgeApp.OutputText(String.Format(fmt, o, o2)); }
public static void DPF(string fmt, object o, object o2, object o3) { ForgeApp.OutputText(String.Format(fmt, o, o2, o3)); }
public static string GETARG(string k, string d) { string val = Script.Args.ValueOf(k); if (val == null || val.Length == 0) val = d; return val; }
public static int GETARG(string k, int d) { string s = Script.Args.ValueOf(k); if (s == null || s.Length == 0) return d; else return Script.Args.AsInt(k); }
public static bool GETARG(string k, bool d) { string s = Script.Args.ValueOf(k); if (s == null || s.Length == 0) return d; else return Script.Args.AsBool(k); }
} //EntryPoint

Categories