How to detect running ASP.NET version - c#

How can I see the version of .net framework which renders my aspx page on remote server?

This outputs your version:
System.Environment.Version.ToString()

<%# Page language="C#" %>
<% Response.Write(".NET Framework Version: " + Environment.Version.ToString()); %>

Environment.Version

Enable Trace
Enabling Trace is another option view every details of rendered page, including .NET Version
Add Trace="true" in page directive
<%# Page Trace="true" %>
Scroll down to bottom and you will see rendered .NET Version

Actually, you all got the CLR version (but not really either, you actually get a string that is hard-coded in mscorlib.dll).
For the actual ASP.NET version, as you see it on the YSOD error pages, see here (they are NOT the same):
using System;
namespace MyElmahReplacement
{
public class MyVersionInfo
{
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern IntPtr GetModuleHandle(string strModuleName);
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int GetModuleFileName(IntPtr ptrHmodule, System.Text.StringBuilder strFileName, int szeSize);
private static string GetFileNameFromLoadedModule(string strModuleName)
{
IntPtr hModule = GetModuleHandle(strModuleName);
if (hModule == IntPtr.Zero)
{
return null;
}
System.Text.StringBuilder sb = new System.Text.StringBuilder(256);
if (GetModuleFileName(hModule, sb, 256) == 0)
{
return null;
}
string strRetVal = sb.ToString();
if (strRetVal != null && strRetVal.StartsWith("\\\\?\\"))
strRetVal = strRetVal.Substring(4);
sb.Length = 0;
sb = null;
return strRetVal;
}
private static string GetVersionFromFile(string strFilename)
{
string strRetVal = null;
try
{
System.Diagnostics.FileVersionInfo fviVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(strFilename);
strRetVal = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.{1}.{2}.{3}", new object[] {
fviVersion.FileMajorPart,
fviVersion.FileMinorPart,
fviVersion.FileBuildPart,
fviVersion.FilePrivatePart
});
}
catch
{
strRetVal = "";
}
return strRetVal;
}
private static string GetVersionOfLoadedModule(string strModuleName)
{
string strFileNameOfLoadedModule = GetFileNameFromLoadedModule(strModuleName);
if (strFileNameOfLoadedModule == null)
return null;
return GetVersionFromFile(strFileNameOfLoadedModule);
}
public static string SystemWebVersion
{
get
{
return GetVersionFromFile(typeof(System.Web.HttpRuntime).Module.FullyQualifiedName);
}
}
public static bool IsMono
{
get
{
return Type.GetType("Mono.Runtime") != null;
}
}
public static string MonoVersion
{
get
{
string strMonoVersion = "";
Type tMonoRuntime = Type.GetType("Mono.Runtime");
if (tMonoRuntime != null)
{
System.Reflection.MethodInfo displayName = tMonoRuntime.GetMethod("GetDisplayName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (displayName != null)
strMonoVersion = (string)displayName.Invoke(null, null);
}
return strMonoVersion;
}
}
public static string DotNetFrameworkVersion
{
get
{
// values.Add(ExceptionPageTemplate.Template_RuntimeVersionInformationName, RuntimeHelpers.MonoVersion);
if (IsMono)
return MonoVersion;
// Return System.Environment.Version.ToString()
return GetVersionOfLoadedModule("mscorwks.dll");
}
}
public static string AspNetVersion
{
get
{
//values.Add(ExceptionPageTemplate.Template_AspNetVersionInformationName, Environment.Version.ToString());
if (IsMono)
return System.Environment.Version.ToString();
return GetVersionOfLoadedModule("webengine.dll");
}
}
public static bool IsVistaOrHigher
{
get
{
System.OperatingSystem osWindowsVersion = System.Environment.OSVersion;
return osWindowsVersion.Platform == System.PlatformID.Win32NT && osWindowsVersion.Version.Major >= 6;
}
}
public static void Test()
{
string ErrorPageInfo =
string.Format("Version Information: Microsoft .NET Framework Version: {0}; ASP.NET Version: {1}"
,DotNetFrameworkVersion
,AspNetVersion
);
Console.WriteLine(ErrorPageInfo);
}
} // End Class MyVersionInfo
} // End Namespace LegendenTest

Related

How do I dynamically add a body to a method marked `static extern` in C#?

Summary
I'm trying to write a small API for my project that would provide a near drop-in replacement for the System.DllImportAttribute. How would I dynamically either replace or add a body to a method marked static extern?
Background
I've seen a few answers on here (here and here) that show how to intercept and dynamically replace methods, but they are not extern, and I can't get any of them to work with methods that aren't.
My current API does the following:
Finds all methods marked with a NativeCallAttribute and returns a MethodInfo[].
For each MethodInfo in the returned MethodInfo[]:
Loads the specified library (if not already loaded) using either LoadLibrary or dlopen.
Get an IntPtr representing the function pointer for a specified method from the loaded library using either GetProcAddress or dlsym.
Generates a delegate for the native function pointer based on the current MethodInfo.
Gets a MethodInfo from the generated delegate to replace the existing one.
Replaces the old method with the new one.
Code
My current implementation takes a similar approach to this project in terms of getting an attribute set up and gathering information about the attached method, and this stackoverflow answer in terms of replacing the function body with a native delegate.
The current API that I have to load the library and get the function pointer work as they should (as they work in other situations than this), and they have been excluded from the code below.
Current API
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using TCDFx.ComponentModel;
namespace TCDFx.InteropServices
{
// Indicates that the attributed method is exposed by an native assembly as a static entry point.
[CLSCompliant(false)]
[SuppressUnmanagedCodeSecurity]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class NativeCallAttribute : Attribute
{
// The name of the native method.
public string EntryPoint;
// Initializes a new instance of the NativeCallAttribute.
public NativeCallAttribute(params string[] assemblyNames)
{
if (assemblyNames == null || assemblyNames.Length == 0)
throw new NativeCallException("No assembly specified.");
string[] names = new string[] { };
int i = 0;
foreach (string name in assemblyNames)
{
if (!string.IsNullOrWhiteSpace(name))
{
names[i] = name;
i++;
}
}
AssemblyNames = names;
}
// An ordered list of assembly names.
public string[] AssemblyNames { get; }
}
[SuppressUnmanagedCodeSecurity]
public static class NativeCalls
{
private static readonly object sync = new object();
// Replaces all defined functions with the 'NativeCallAttribute' that are 'static' and 'extern' with their native call.
public static void Load()
{
lock (sync)
{
MethodInfo[] funcInfo = GetNativeCalls();
for (int i = 0; i < funcInfo.Length; i++)
{
NativeCallAttribute attribute = funcInfo[i].GetCustomAttribute<NativeCallAttribute>(false);
NativeAssemblyBase nativeAssembly;
if (IsAssemblyCached(attribute.AssemblyNames, out NativeAssemblyBase cachedAssembly))
nativeAssembly = cachedAssembly;
else
{
if (TryLoadAssembly(attribute.AssemblyNames, out NativeAssemblyBase loadedAssembly, out Exception loadingEx))
nativeAssembly = loadedAssembly;
else
throw loadingEx;
}
string funcName = attribute.EntryPoint ?? funcInfo[i].Name;
IntPtr funcPtr = nativeAssembly.LoadFunctionPointer(funcName);
Delegate funcDelegate = GenerateNativeDelegate(funcName, nativeAssembly.Name, funcInfo[i], funcPtr);
MethodInfo funcInfoNew = funcDelegate.GetMethodInfo();
MethodReplacementState state = ReplaceMethod(funcInfo[i], funcInfoNew);
replacements.Add(state);
}
}
}
// Gets all methods marked with a 'NativeCallAttribute'.
private static MethodInfo[] GetNativeCalls()
{
List<MethodInfo> result = new List<MethodInfo>();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
Type[] types = assemblies[i].GetTypes();
for (int ii = 0; ii < types.Length; ii++)
{
MethodInfo[] methods = types[ii].GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
for (int iii = 0; iii < methods.Length; iii++)
{
Attribute attr = methods[iii].GetCustomAttribute<NativeCallAttribute>(false);
if (attr != null)
result.Add(methods[iii]);
}
}
}
return result.ToArray();
}
// Gets a 'Delegate' for a native function pointer with information provided from the method to replace.
private static Delegate GenerateNativeDelegate(string funcName, string assemblyName, MethodInfo funcInfo, IntPtr funcPtr)
{
Type returnType = funcInfo.ReturnType;
ParameterInfo[] #params = funcInfo.GetParameters();
Type[] paramTypes = new Type[] { };
for (int i = 0; i < #params.Length; i++)
paramTypes[i] = #params[i].ParameterType;
DynamicMethod nativeMethod = new DynamicMethod($"{assemblyName}_{funcName}", returnType, paramTypes, funcInfo.Module);
ILGenerator ilGenerator = nativeMethod.GetILGenerator();
// Generate the arguments
for (int i = 0; i < #params.Length; i++)
{
//TODO: See if I need separate out code for this...
if (#params[i].ParameterType.IsByRef || #params[i].IsOut)
{
ilGenerator.Emit(OpCodes.Ldarg, i);
ilGenerator.Emit(OpCodes.Ldnull);
ilGenerator.Emit(OpCodes.Stind_Ref);
}
else
{
ilGenerator.Emit(OpCodes.Ldarg, i);
}
}
// Push the funcPtr to the stack
if (IntPtr.Size == 4)
ilGenerator.Emit(OpCodes.Ldc_I4, funcPtr.ToInt32());
else if (IntPtr.Size == 8)
ilGenerator.Emit(OpCodes.Ldc_I8, funcPtr.ToInt64());
else throw new PlatformNotSupportedException();
// Call it and return;
ilGenerator.EmitCall(OpCodes.Call, funcInfo, null);
ilGenerator.Emit(OpCodes.Ret);
Type delegateType = Expression.GetDelegateType((from param in #params select param.ParameterType).Concat(new[] { returnType }).ToArray());
return nativeMethod.CreateDelegate(delegateType);
}
private static bool IsAssemblyCached(string[] assemblyNames, out NativeAssemblyBase cachedAssembly)
{
bool result = false;
cachedAssembly = null;
foreach (string name in assemblyNames)
{
if (!Component.Cache.ContainsKey(Path.GetFileNameWithoutExtension(name)))
{
Type asmType = Component.Cache[Path.GetFileNameWithoutExtension(name)].Value1;
if (asmType == typeof(NativeAssembly))
cachedAssembly = (NativeAssembly)Component.Cache[Path.GetFileNameWithoutExtension(name)].Value2;
else if (asmType == typeof(NativeAssembly))
cachedAssembly = (DependencyNativeAssembly)Component.Cache[Path.GetFileNameWithoutExtension(name)].Value2;
else if (asmType == typeof(NativeAssembly))
cachedAssembly = (EmbeddedNativeAssembly)Component.Cache[Path.GetFileNameWithoutExtension(name)].Value2;
result = true;
break;
}
}
return result;
}
private static bool TryLoadAssembly(string[] assemblyNames, out NativeAssemblyBase loadedAssembly, out Exception exception)
{
bool result = false;
exception = null;
try
{
loadedAssembly = new NativeAssembly(assemblyNames);
}
catch (Exception ex)
{
exception = ex;
loadedAssembly = null;
}
try
{
if (exception != null)
loadedAssembly = new DependencyNativeAssembly(assemblyNames);
}
catch (Exception ex)
{
exception = ex;
loadedAssembly = null;
}
try
{
if (exception == null)
loadedAssembly = new EmbeddedNativeAssembly(assemblyNames);
}
catch (Exception ex)
{
exception = ex;
loadedAssembly = null;
}
return result;
}
private static unsafe MethodReplacementState ReplaceMethod(MethodInfo targetMethod, MethodInfo replacementMethod)
{
if (!(targetMethod.GetMethodBody() == null && targetMethod.IsStatic))
throw new NativeCallException($"Only the replacement of methods marked 'static extern' is supported.");
#if DEBUG
RuntimeHelpers.PrepareMethod(targetMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(replacementMethod.MethodHandle);
#endif
IntPtr target = targetMethod.MethodHandle.Value;
IntPtr replacement = replacementMethod.MethodHandle.Value + 8;
if (!targetMethod.IsVirtual)
target += 8;
else
{
int i = (int)(((*(long*)target) >> 32) & 0xFF);
IntPtr classStart = *(IntPtr*)(targetMethod.DeclaringType.TypeHandle.Value + (IntPtr.Size == 4 ? 40 : 64));
target = classStart + (IntPtr.Size * i);
}
#if DEBUG
target = *(IntPtr*)target + 1;
replacement = *(IntPtr*)replacement + 1;
MethodReplacementState state = new MethodReplacementState(target, new IntPtr(*(int*)target));
*(int*)target = *(int*)replacement + (int)(long)replacement - (int)(long)target;
return state;
#else
MethodReplacementState state = new MethodReplacementState(target, *(IntPtr*)target);
* (IntPtr*)target = *(IntPtr*)replacement;
return state;
#endif
}
private readonly struct MethodReplacementState : IDisposable
{
private readonly IntPtr Location;
private readonly IntPtr OriginalValue;
public MethodReplacementState(IntPtr location, IntPtr origValue)
{
Location = location;
OriginalValue = origValue;
}
public void Dispose() => Restore();
private unsafe void Restore() =>
#if DEBUG
*(int*)Location = (int)OriginalValue;
#else
*(IntPtr*)Location = OriginalValue;
#endif
}
}
}
Test Code
using TCDFx.InteropServices;
namespace NativeCallExample
{
internal class Program
{
internal static void Main()
{
NativeCalls.Load();
Beep(2000, 400);
}
[NativeCall("kernel32.dll")]
private static extern bool Beep(uint frequency, uint duration);
}
}
Expected/Actual Results
I expected it to run as it should (as listed above in the description), but it is crashing dotnet.exe with error code -532462766. No breakpoints are hit anywhere in the code (in the test app or API library), and no exception is thrown. I believe the problem to be happening between steps 2.3 and 2.5 above, but I'm pretty stuck at the moment. Any help would be appreciated!
More Information
If you want to see the referenced code that isn't included and a full copy of what I have for this, you can find it in this branch of my project.

NancyFx: how to pass an error message to a custom error page?

We've implemented static custom error pages for 404/500 HTTP status codes using Razor and the IStatusCodeHandler implementation documented here:
https://blog.tommyparnell.com/custom-error-pages-in-nancy/
That works, and now we've been trying to pass an error message to the Razor template. The RenderView method runs without exception, however the output is totally blank.
In the Handle method, we construct an ErrorModel object and set its ErrorMessage property, then pass the object to RenderView:
var response = viewRenderer.RenderView(context, "views/Errors/" + (int)statusCode + ".cshtml", errorModel);
The CustomStatusCode.cs code is:
public class CustomStatusCode : IStatusCodeHandler
{
private readonly ILog _log = LogManager.GetLogger<CustomStatusCode>();
private static IEnumerable<int> _checks = new List<int>();
public static IEnumerable<int> Checks { get { return _checks; } }
private IViewRenderer viewRenderer;
public CustomStatusCode(IViewRenderer viewRenderer)
{
this.viewRenderer = viewRenderer;
}
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return (_checks.Any(x => x == (int)statusCode));
}
public static void AddCode(int code)
{
AddCode(new List<int>() { code });
}
public static void AddCode(IEnumerable<int> code)
{
_checks = _checks.Union(code);
}
public static void RemoveCode(int code)
{
RemoveCode(new List<int>() { code });
}
public static void RemoveCode(IEnumerable<int> code)
{
_checks = _checks.Except(code);
}
public static void Disable()
{
_checks = new List<int>();
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
var errorMessage = string.Empty;
var exception = context.GetException();
if (exception != null)
{
errorMessage = exception.Message;
}
var errorModel = new ErrorModel(errorMessage);
try
{
var response = viewRenderer.RenderView(context, "views/Errors/" + (int)statusCode + ".cshtml", errorModel);
response.StatusCode = HttpStatusCode.OK;
context.Response = response;
}
catch (Exception ex)
{
_log.Debug($"CustomStatusCodes caught exception: {ex.Message}");
RemoveCode((int)statusCode);
context.Response.StatusCode = statusCode;
}
}
}
The ErrorModel.cs class is:
public class ErrorModel
{
public ErrorModel(string message)
{
ErrorMessage = message;
}
string ErrorMessage { get; set; }
}
One of the Razor templates:
#using WebService.Models
#Model ErrorModel
<html>
<body>
<b>500 Internal server error.</b>
<p>Error message was: #Model.ErrorMessage</p>
</body>
</html>
We've tried setting response.StatusCode to the original statusCode parameter value, as well as HttpStatusCode.OK, both result in a blank page.
Any suggestions as to what we're missing?

Dynamically loading assemblies and instantiating types using reflection

I have a requirement to dynamically load and cast an instance of a class to it's various base types using requirement. Now on reading and trying my hand on some examples, I find that either I probably don't understand all that I need to when it comes to working with classes at runtime.
I have a situation where Abstract class B implements interface A. Now Class B is a base class for class C. When I dynamically load, at runtime, the assembly that contains all 3 types, I expect that I should be able to, using Load From context, load the assembly, create an instance of class C, and cast it to type of interface A. But that does not seem to be happening at all and I would appreciate an explanation as to why. Thanks in Advance.
http://msdn.microsoft.com/en-us/library/2xkww633.aspx
http://msdn.microsoft.com/en-us/library/1009fa28.aspx
public interface ICaseOutputGenerator
{
String SampleProperty { get; set; }
void Process();
}
public abstract class CaseOutputGeneratorBase : ICaseOutputGenerator
{
public String SecondSampleProperty { get; set; }
public virtual void SecondProcessMethod()
{
}
public abstract void ThirdSampleProcessMethod();
public string SampleProperty
{
get;
set;
}
public void Process()
{
Console.WriteLine("Process in CaseOutputGeneratorBase Called");
}
}
public class TestCaseOutputGenerator : CaseOutputGeneratorBase
{
public override void ThirdSampleProcessMethod()
{
throw new NotImplementedException();
}
}
//////////////////////////////////////////////////////////////////////////////
public class TestSandBoxManager
{
public TestSandBoxManager()
{
}
public String ProcessAssemblyByFullDisplayName(String assemblyFullDisplayName)
{
String temp = String.Empty;
var casecust = GetAssemblyByFullDisplayName(assemblyFullDisplayName);
if (casecust != null)
temp = ("Cast Passed");
else
temp = ("Cast Failed");
return temp;
}
public String ProcessFile(String assemblyName, String className)
{
String temp = String.Empty;
var casecust = GetCaseOutputGeneratorObject(assemblyName, className);
if (casecust != null)
temp=("Cast Passed");
else
temp=("Cast Failed");
return temp;
}
private static object GetAssemblyByFullDisplayName(string fullName)
{
try
{
Type caseOutputGen = null;
String fullQualifiedName = String.Empty;
var localAssembly = Assembly.LoadFrom(fullName);
foreach (var testType in localAssembly.GetTypes())
{
if ( testType.FullName != fullName)
continue;
fullQualifiedName = testType.FullName;
break;
}
if (fullQualifiedName == null)
return null;
var obj = Activator.CreateInstance(Type.GetType(fullQualifiedName));
return obj;
}
catch (Exception ex)
{
throw ex;
}
}
public String ProcessFile2(String assemblyName, String className)
{
String temp = String.Empty;
var casecust = GetCaseOutputGeneratorObjectLoadFrom(assemblyName, className);
if (casecust != null)
temp = ("Cast Passed");
else
temp = ("Cast Failed");
return temp;
}
public static ICaseOutputGenerator GetCaseOutputGeneratorObject(string assemblyName, string className)
{
ICaseOutputGenerator caseOutputGen = null;
var obj = GetObject(assemblyName, className);
if (obj != null)
caseOutputGen = (ICaseOutputGenerator)obj; // FAILS HERE
return caseOutputGen;
}
public static ICaseOutputGenerator GetCaseOutputGeneratorObjectLoadFrom(string assemblyName, string className)
{
ICaseOutputGenerator caseOutputGen = null;
try
{
var obj = GetObject2(assemblyName, className);
if (obj != null)
caseOutputGen = (ICaseOutputGenerator)obj; // FAILS HERE
}
catch (Exception ex)
{
throw ex;
}
return caseOutputGen;
}
private static object GetObject2(string fullName, string className)
{
try
{
Type caseOutputGen = null;
String fullQualifiedName = String.Empty;
var localAssembly = Assembly.LoadFrom(fullName);
foreach (var testType in localAssembly.GetTypes())
{
if (!testType.FullName.EndsWith(className, StringComparison.InvariantCultureIgnoreCase))
continue;
caseOutputGen = testType;
fullQualifiedName = testType.FullName;
break;
}
if (caseOutputGen == null)
return null;
var obj = Activator.CreateInstanceFrom(fullName, fullQualifiedName);
return obj.Unwrap();
}
catch (Exception ex)
{
throw ex;
}
}
private static object GetObject(string fullName, string className)
{
try
{
Type caseOutputGen = null;
var localAssembly = Assembly.LoadFrom(fullName);
foreach (var testType in localAssembly.GetTypes())
{
if (!testType.FullName.EndsWith(className, StringComparison.InvariantCultureIgnoreCase)) continue;
caseOutputGen = testType;
break;
}
if (caseOutputGen == null) return null;
var obj = Activator.CreateInstance(caseOutputGen);
return obj;
}
catch (FileNotFoundException ex)
{
throw new Exception("Failed to load assembly: " + Environment.NewLine + fullName, ex);
}
catch (Exception ex)
{
throw new Exception("Failed to load assembly: " + Environment.NewLine + fullName, ex);
}
}
}
//////////////////////////////////////////////////////////////////////////////
public Boolean testReflection2()
{
try
{
//create an instance of the testsandboxmanager
TestSandBoxManager t = new TestSandBoxManager();
String ret = t.ProcessFile2(#"...\Documents\visual studio 2012\Projects\TestSandBox\TestSandBox\bin\Debug\TestSandBox.dll", "TestCaseOutputGenerator");
Console.WriteLine(ret);
Console.ReadLine();
return true;
}
catch (Exception)
{
return false;
}
}
Most likely you have 2 ICaseOutputGenerator - one in each assembly. You can't cast object/interface to similarly named interface in another assembly even if code is identical. You can check the fact that create object implements ICaseOutputGenerator from its own assembly by looking at created object in the debugger.
If it is the case you need to figure out where you want to put ICaseOutputGenerator interface so it is coming from the same assembly for both "custom loaded assembly" and you main application. Often shared interfaces are implemented in separate assembly and linked to all "plug-in" assemblies as well as application assembly.
I think that Alexei Levenkov is spot on. You load your TestSandBox.dll twice. Once as a reference to your project and second time via Assembly.LoadFrom. As per documentation that you yourself linking this can result in unexpected behaviour. Here is a quote for you reference:
If an assembly is loaded with LoadFrom, and the probing path includes
an assembly with the same identity but a different location, an
InvalidCastException, MissingMethodException, or other unexpected
behavior can occur.
This is exactly what's happening in your case. If you change the path you are loading your assembly from to point to the same folder as your main executable, it will work fine.

Using C# to reference a port number to service name

On Linux using MONO.
How do I use C# to pair a port number to a service ?
example:
port 80 = http
port 443 = https
and output it to the console, I need this for a simple port scanner I built.
I know this function exists in ruby:
Socket.getservbyport(80, "tcp")
Mono Linux version
I had a bit of time on my hands so set up Mono on my Ubuntu Linux box to test with. The Mono PInvoke implementation of getservbyport() and getservbyname() is simpler than on Windows (just load libc which has the networking stuff built in). Here's the example code for reference in case anyone ever wants it ;)
namespace SocketUtil
{
using System;
using System.Net;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
[Serializable]
public class SocketUtilException : Exception
{
public SocketUtilException()
{
}
public SocketUtilException(string message)
: base(message)
{
}
public SocketUtilException(string message, Exception inner)
: base(message, inner)
{
}
protected SocketUtilException(
SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
public static class SocketUtil
{
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct servent
{
public string s_name;
public IntPtr s_aliases;
public ushort s_port;
public string s_proto;
}
[DllImport("libc", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr getservbyname(string name, string proto);
[DllImport("libc", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr getservbyport(ushort port, string proto);
public static string GetServiceByPort(ushort port, string protocol, out List<string> aliases)
{
var netport = unchecked((ushort)IPAddress.HostToNetworkOrder(unchecked((short)port)));
var result = getservbyport(netport, protocol);
if (IntPtr.Zero == result)
{
throw new SocketUtilException(
string.Format("Could not resolve service for port {0}", port));
}
var srvent = (servent)Marshal.PtrToStructure(result, typeof(servent));
aliases = GetAliases(srvent);
return srvent.s_name;
}
private static List<string> GetAliases(servent srvent)
{
var aliases = new List<string>();
if (srvent.s_aliases != IntPtr.Zero)
{
IntPtr cb;
for (var i = 0;
(cb = Marshal.ReadIntPtr(srvent.s_aliases, i)) != IntPtr.Zero;
i += Marshal.SizeOf(cb))
{
aliases.Add(Marshal.PtrToStringAnsi(cb));
}
}
return aliases;
}
public static ushort GetServiceByName(string service, string protocol, out List<string> aliases)
{
var result = getservbyname(service, protocol);
if (IntPtr.Zero == result)
{
throw new SocketUtilException(
string.Format("Could not resolve port for service {0}", service));
}
var srvent = (servent)Marshal.PtrToStructure(result, typeof(servent));
aliases = GetAliases(srvent);
var hostport = IPAddress.NetworkToHostOrder(unchecked((short)srvent.s_port));
return unchecked((ushort)hostport);
}
}
class Program
{
static void Main(string[] args)
{
try
{
List<string> aliases;
var port = SocketUtil.GetServiceByName("https", "tcp", out aliases);
Console.WriteLine("https runs on port {0}", port);
foreach (var alias in aliases)
{
Console.WriteLine(alias);
}
Console.WriteLine("Reverse call:{0}", SocketUtil.GetServiceByPort(port, "tcp", out aliases));
}
catch (SocketUtilException exception)
{
Console.WriteLine(exception.Message);
if (exception.InnerException != null)
{
Console.WriteLine(exception.InnerException.Message);
}
}
}
}
}
Windows Version
Update: Saw too late that poster had added a Linux and Mono tag after asking the question so wrote a Windows implementation. On Linux use the Mono version in the second post.
Mohammad's solution is more portable than the alternative in many ways. getservbyname() and getservbyport() are platform-dependent and require using P/Invoke to use with c# on Windows and most likely on Mono as well.
To implement the code below in Mono you'll need to PInvoke using the platform specific APIs (the header would be netdb.h) - note that WSAStartUp() and WSACleanUp() are windows-specific socket initialization functions which are irrelevant on a Linux system. Don't have mono setup at the moment so can't provide a linux-specific solution but if you're willing to jump through the hoops here's a windows (32-bit) example to base your code on:
namespace SocketTest
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
[Serializable]
public class SocketUtilException : Exception
{
public SocketUtilException()
{
}
public SocketUtilException(string message)
: base(message)
{
}
public SocketUtilException(string message, Exception inner)
: base(message, inner)
{
}
protected SocketUtilException(
SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
public static class SocketUtil
{
private const int WSADESCRIPTION_LEN = 256;
private const int WSASYSSTATUS_LEN = 128;
[StructLayout(LayoutKind.Sequential)]
public struct WSAData
{
public short wVersion;
public short wHighVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = WSADESCRIPTION_LEN+1)]
public string szDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = WSASYSSTATUS_LEN+1)]
public string wSystemStatus;
[Obsolete("Ignored when wVersionRequested >= 2.0")]
public ushort wMaxSockets;
[Obsolete("Ignored when wVersionRequested >= 2.0")]
public ushort wMaxUdpDg;
public IntPtr dwVendorInfo;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct servent
{
public string s_name;
public IntPtr s_aliases;
public short s_port;
public string s_proto;
}
private static ushort MakeWord ( byte low, byte high)
{
return (ushort)((ushort)(high << 8) | low);
}
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)]
private static extern int WSAStartup(ushort wVersionRequested, ref WSAData wsaData);
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)]
private static extern int WSACleanup();
[DllImport("ws2_32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr getservbyname(string name, string proto);
[DllImport("ws2_32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr getservbyport(short port, string proto);
public static string GetServiceByPort(short port, string protocol)
{
var wsaData = new WSAData();
if (WSAStartup(MakeWord(2, 2), ref wsaData) != 0)
{
throw new SocketUtilException("WSAStartup",
new SocketException(Marshal.GetLastWin32Error()));
}
try
{
var netport = Convert.ToInt16(IPAddress.HostToNetworkOrder(port));
var result = getservbyport(netport, protocol);
if (IntPtr.Zero == result)
{
throw new SocketUtilException(
string.Format("Could not resolve service for port {0}", port),
new SocketException(Marshal.GetLastWin32Error()));
}
var srvent = (servent)Marshal.PtrToStructure(result, typeof(servent));
return srvent.s_name;;
}
finally
{
WSACleanup();
}
}
public static short GetServiceByName(string service, string protocol)
{
var wsaData = new WSAData();
if(WSAStartup(MakeWord(2,2), ref wsaData) != 0)
{
throw new SocketUtilException("WSAStartup",
new SocketException(Marshal.GetLastWin32Error()));
}
try
{
var result = getservbyname(service, protocol);
if (IntPtr.Zero == result)
{
throw new SocketUtilException(
string.Format("Could not resolve port for service {0}", service),
new SocketException(Marshal.GetLastWin32Error()));
}
var srvent = (servent)Marshal.PtrToStructure(result, typeof(servent));
return Convert.ToInt16(IPAddress.NetworkToHostOrder(srvent.s_port));
}
finally
{
WSACleanup();
}
}
}
class Program
{
static void Main(string[] args)
{
try
{
var port = SocketUtil.GetServiceByName("http", "tcp");
Console.WriteLine("http runs on port {0}", port);
Console.WriteLine("Reverse call:{0}", SocketUtil.GetServiceByPort(port, "tcp"));
}
catch(SocketUtilException exception)
{
Console.WriteLine(exception.Message);
if(exception.InnerException != null)
{
Console.WriteLine(exception.InnerException.Message);
}
}
}
}
On Windows there is a "services" file which is located at System32\Drivers\Etc\ folder. I have written the following code to parse it. You can use it to find information on any port you want:
class Program
{
static void Main(string[] args)
{
var services = ReadServicesFile();
// For example, I want to find information about port 443 of TCP service
var port443Info = services.FirstOrDefault(s => s.Port == 443 && s.Type.Equals("tcp"));
if (port443Info != null)
{
Console.WriteLine("TCP Port = {0}, Service name = {1}", port443Info.Port, port443Info.Name);
}
}
static List<ServiceInfo> ReadServicesFile()
{
var sysFolder = Environment.GetFolderPath(Environment.SpecialFolder.System);
if (!sysFolder.EndsWith("\\"))
sysFolder += "\\";
var svcFileName = sysFolder + "drivers\\etc\\services";
var lines = File.ReadAllLines(svcFileName);
var result = new List<ServiceInfo>();
foreach (var line in lines)
{
if (string.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
var info = new ServiceInfo();
var index = 0;
// Name
info.Name = line.Substring(index, 16).Trim();
index += 16;
// Port number and type
var temp = line.Substring(index, 9).Trim();
var tempSplitted = temp.Split('/');
info.Port = ushort.Parse(tempSplitted[0]);
info.Type = tempSplitted[1].ToLower();
result.Add(info);
}
return result;
}
}
You will also need the following class declaration:
class ServiceInfo
{
public ushort Port { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}

Enumerating Files Throwing Exception

I am trying to enumerate through files on my computer using the below code but everytime it hits a file or dir that I don't have permission to read it throws an exception. Is there any way I can continue searching after the exception has been thrown? I know some people have had similar issues but is there any other way of doing this other than checking every file/folder individually?
try
{
string[] files = Directory.GetFiles(#"C:\", "*.*",SearchOption.AllDirectories);
foreach (string file in files)
{
Console.WriteLine(file);
}
}
catch
{
}
Thanks for any help as this is driving me mad!
I came across the same problem just today. I hacked together the following code. If you want to use it in a real product you might need to improve the error handling. Since this was for a one-shot script I didn't care much.
static IEnumerable<string> EnumerateFilesRecursive(string root,string pattern="*")
{
var todo = new Queue<string>();
todo.Enqueue(root);
while (todo.Count > 0)
{
string dir = todo.Dequeue();
string[] subdirs = new string[0];
string[] files = new string[0];
try
{
subdirs = Directory.GetDirectories(dir);
files = Directory.GetFiles(dir, pattern);
}
catch (IOException)
{
}
catch (System.UnauthorizedAccessException)
{
}
foreach (string subdir in subdirs)
{
todo.Enqueue(subdir);
}
foreach (string filename in files)
{
yield return filename;
}
}
}
To use it you can either:
string[] files = EnumerateFilesRecursive(#"C:\").ToArray();//Note the ToArray()
foreach (string file in files)
{
Console.WriteLine(file);
}
which first enumerates all files, stores all file names in memory and only then displays them. Alternatively you can:
IEnumerable<string> files = EnumerateFilesRecursive(#"C:\");//Note that there is NO ToArray()
foreach (string file in files)
{
Console.WriteLine(file);
}
Which writes while enumerating and thus doesn't need to keep all filenames in memory at the same time.
Here is some utility code based on Windows API that enumerates file system entries without throwing/catching exceptions.
Sample usage:
...
foreach (var fi in Utilities.EnumerateFileSystemEntries(#"c:\windows\system32", DirectoryEnumerateOptions.Recursive))
{
Console.WriteLine(fi.FullName);
}
...
Utility classes:
[Flags]
public enum DirectoryEnumerateOptions
{
None = 0x0,
Recursive = 0x1,
ThrowErrors = 0x2, // if you really want it
ExpandEnvironmentVariables = 0x4,
}
public static class Utilities
{
public static IEnumerable<FileSystemInfo> EnumerateFileSystemEntries(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (directoryPath == null)
throw new ArgumentNullException(nameof(directoryPath));
if (!Path.IsPathRooted(directoryPath))
{
directoryPath = Path.GetFullPath(directoryPath);
}
return EnumerateFileSystemEntriesPrivate(directoryPath, options);
}
private static IEnumerable<FileSystemInfo> EnumerateFileSystemEntriesPrivate(string directoryPath, DirectoryEnumerateOptions options = DirectoryEnumerateOptions.None)
{
if (!Directory.Exists(directoryPath))
yield break;
var findPath = Normalize(directoryPath, options.HasFlag(DirectoryEnumerateOptions.ExpandEnvironmentVariables));
if (!findPath.EndsWith("*"))
{
findPath = Path.Combine(findPath, "*");
}
var h = FindFirstFile(findPath, out var data);
if (h == INVALID_HANDLE_VALUE)
{
if (options.HasFlag(DirectoryEnumerateOptions.ThrowErrors))
throw new Win32Exception(Marshal.GetLastWin32Error());
yield break;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
do
{
if (!FindNextFile(h, out data))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_FILES)
{
FindClose(h);
break;
}
continue;
}
if (Include(ref data))
{
yield return ToInfo(ref data, directoryPath);
if (options.HasFlag(DirectoryEnumerateOptions.Recursive) && data.fileAttributes.HasFlag(FileAttributes.Directory))
{
foreach (var wfd in EnumerateFileSystemEntriesPrivate(Path.Combine(directoryPath, data.cFileName), options))
{
yield return wfd;
}
}
}
}
while (true);
}
private static bool Include(ref WIN32_FIND_DATA data) => data.cFileName != "." && data.cFileName != "..";
private static FileSystemInfo ToInfo(ref WIN32_FIND_DATA data, string directoryPath)
{
if (data.fileAttributes.HasFlag(FileAttributes.Directory))
return new FileInfo(Path.Combine(directoryPath, data.cFileName));
return new DirectoryInfo(Path.Combine(directoryPath, data.cFileName));
}
private static string Normalize(string path, bool expandEnvironmentVariables)
{
if (path == null)
return null;
string expanded;
if (expandEnvironmentVariables)
{
expanded = Environment.ExpandEnvironmentVariables(path);
}
else
{
expanded = path;
}
if (expanded.StartsWith(_prefix))
return expanded;
if (expanded.StartsWith(#"\\"))
return _uncPrefix + expanded.Substring(2);
return _prefix + expanded;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", SetLastError = true)]
private static extern bool FindClose(IntPtr hFindFile);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
#pragma warning disable IDE1006 // Naming Styles
private const int ERROR_NO_MORE_FILES = 18;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
#pragma warning restore IDE1006 // Naming Styles
private const string _prefix = #"\\?\";
private const string _uncPrefix = _prefix + #"UNC\";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WIN32_FIND_DATA
{
public FileAttributes fileAttributes;
public uint ftCreationTimeLow;
public uint ftCreationTimeHigh;
public uint ftLastAccessTimeLow;
public uint ftLastAccessTimeHigh;
public uint ftLastWriteTimeLow;
public uint ftLastWriteTimeHigh;
public uint fileSizeHigh;
public uint fileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
}

Categories

Resources