I write a simple utility that adds a route for specific interface. Code is very simple:
using System;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Text;
class Program
{
static void Main(string[] args)
{
const string firstConnection = "xxxx.yyyyy";
const string routeAddMask = "route add XX.XX.XX.XX mask 255.255.255.255 XXX.XXX.XXX.XXX METRIC 99 IF {0}";
StartProcess("rasdial", firstConnection);
var interfaceId = GetInterfaceId(firstConnection);
string routeAdd = string.Format(routeAddMask, interfaceId);
StartProcess("route", routeAdd);
}
private static int GetInterfaceId(string name)
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
var adapter = Array.Find(adapters, ni => ni.Name == name);
var props = adapter.GetIPProperties().GetIPv4Properties();
return props.Index;
}
private static void StartProcess(string name, string args)
{
var process = new Process
{
StartInfo = new ProcessStartInfo(name, args)
{
UseShellExecute = false,
RedirectStandardOutput = true,
StandardOutputEncoding = Encoding.ASCII
}
};
process.Start();
while (!process.HasExited)
{
Console.WriteLine(process.StandardOutput.ReadToEnd());
}
process.WaitForExit();
Console.WriteLine("Process {0} finished, exit code = {1}", name, process.ExitCode);
}
}
rasdial works fine and I get interface number, but when I'm running route I get an error:
Invalid MASK generates an error, that is when (DEST & MASK) != DEST.
I think problem is that process start args are not passed because I get the same error while sending null instead of routeAdd parameter meanwhile this command works fine when i'm prompting it in cmd.
Executable is running as Administrator.
I'm trying to create it with winapi, but it fails too
const string firstConnection = "someconnect";
StartProcess("rasdial", firstConnection);
var interfaceIndex = GetInterfaceIndex(firstConnection); //Everything is fine
var route = new MIB_IPFORWARDROW
{
dwForwardDest = BitConverter.ToUInt32(IPAddress.Parse("XX.XX.XX.XX").GetAddressBytes(), 0),
dwForwardMask = BitConverter.ToUInt32(IPAddress.Parse("255.255.255.255").GetAddressBytes(), 0),
dwForwardNextHop = BitConverter.ToUInt32(IPAddress.Parse("XXX.XXX.XXX.XXX").GetAddressBytes(), 0),
dwForwardMetric1 = 99,
dwForwardIfIndex = interfaceIndex
};
var ipForwardEntry = RouteInterop.CreateIpForwardEntry(ref route);
Console.WriteLine(ipForwardEntry);
returns ERROR_INVALID_PARAMETER
I know that question is not very complex, but I didn't encounter any explanation in the internet, this is why I think this answer would be helpful and this is why I'm writing it instead of deleting my initial question.
You just should specify more parameters to make it work
var route = new MIB_IPFORWARDROW
{
dwForwardDest = BitConverter.ToUInt32(IPAddress.Parse("XX.XX.XX.XX").GetAddressBytes(), 0),
dwForwardMask = BitConverter.ToUInt32(IPAddress.Parse("255.255.255.255").GetAddressBytes(), 0),
dwForwardNextHop = BitConverter.ToUInt32(IPAddress.Parse("XXX.XXX.XXX.XXX").GetAddressBytes(), 0),
dwForwardMetric1 = 99,
dwForwardType = ForwardType.Indirect,
dwForwardProto = ForwardProtocol.NetMGMT,
dwForwardAge = 0,
dwForwardIfIndex = interfaceIndex
};
var ipForwardEntry = RouteInterop.CreateIpForwardEntry(ref route);
Elaborating on Alex Zhukovskiy answer as I've combined his answer with a bunch of MSDN articles. The code below uses the Win32 API's, specifically the "iphlpapi.h" module, the comprehensive documentation can be found in this link on managing routing. The PMIB_IPFORWARDTABLE structure and enums are documented here.
The primary methods for mimicking the "route print", "route add", and "route delete" command are
GetIpForwardTable - Gets the network routing table, "route PRINT"
CreateIpForwardEntry - Add Route, like "route ADD"
DeleteIpFowardEntry - Delete Route, like "route DELETE"
SetIpForwardEntry - Modify existing route, like "route CHANGE"
The comprehensive code using C# can be found in this github repository (Ip4RouteTable) - https://github.com/CodeCowboyOrg/Ip4RouteTable
Setting up the Win32 API Calls in C#
internal static class NativeMethods
{
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
public extern static int GetIpForwardTable(IntPtr /*PMIB_IPFORWARDTABLE*/ pIpForwardTable, ref int /*PULONG*/ pdwSize, bool bOrder);
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
//public extern static int CreateIpForwardEntry(ref /*PMIB_IPFORWARDROW*/ Ip4RouteTable.PMIB_IPFORWARDROW pRoute); Can do by reference or by Pointer
public extern static int CreateIpForwardEntry(IntPtr /*PMIB_IPFORWARDROW*/ pRoute);
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
public extern static int DeleteIpForwardEntry(IntPtr /*PMIB_IPFORWARDROW*/ pRoute);
}
public class Ip4RouteTable
{
[ComVisible(false), StructLayout(LayoutKind.Sequential)]
internal struct IPForwardTable
{
public uint Size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public PMIB_IPFORWARDROW[] Table;
};
[ComVisible(false), StructLayout(LayoutKind.Sequential)]
internal struct PMIB_IPFORWARDROW
{
internal uint /*DWORD*/ dwForwardDest;
internal uint /*DWORD*/ dwForwardMask;
internal uint /*DWORD*/ dwForwardPolicy;
internal uint /*DWORD*/ dwForwardNextHop;
internal uint /*DWORD*/ dwForwardIfIndex;
internal uint /*DWORD*/ dwForwardType;
internal uint /*DWORD*/ dwForwardProto;
internal uint /*DWORD*/ dwForwardAge;
internal uint /*DWORD*/ dwForwardNextHopAS;
internal uint /*DWORD*/ dwForwardMetric1;
internal uint /*DWORD*/ dwForwardMetric2;
internal uint /*DWORD*/ dwForwardMetric3;
internal uint /*DWORD*/ dwForwardMetric4;
internal uint /*DWORD*/ dwForwardMetric5;
};
static IPForwardTable ReadIPForwardTable(IntPtr tablePtr)
{
var result = (IPForwardTable)Marshal.PtrToStructure(tablePtr, typeof(IPForwardTable));
PMIB_IPFORWARDROW[] table = new PMIB_IPFORWARDROW[result.Size];
IntPtr p = new IntPtr(tablePtr.ToInt64() + Marshal.SizeOf(result.Size));
for (int i = 0; i < result.Size; ++i)
{
table[i] = (PMIB_IPFORWARDROW)Marshal.PtrToStructure(p, typeof(PMIB_IPFORWARDROW));
p = new IntPtr(p.ToInt64() + Marshal.SizeOf(typeof(PMIB_IPFORWARDROW)));
}
result.Table = table;
return result;
}
public static void RoutePrint(bool testing)
{
var fwdTable = IntPtr.Zero;
int size = 0;
var result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal(size);
result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
var forwardTable = ReadIPForwardTable(fwdTable);
Marshal.FreeHGlobal(fwdTable);
Console.Write("\tNumber of entries: {0}\n", forwardTable.Size);
for (int i = 0; i < forwardTable.Table.Length; ++i)
{
Console.Write("\n\tRoute[{0}] Dest IP: {1}\n", i, new IPAddress((long)forwardTable.Table[i].dwForwardDest).ToString());
Console.Write("\tRoute[{0}] Subnet Mask: {1}\n", i, new IPAddress((long)forwardTable.Table[i].dwForwardMask).ToString());
Console.Write("\tRoute[{0}] Next Hop: {1}\n", i, new IPAddress((long)forwardTable.Table[i].dwForwardNextHop).ToString());
Console.Write("\tRoute[{0}] If Index: {1}\n", i, forwardTable.Table[i].dwForwardIfIndex);
Console.Write("\tRoute[{0}] Type: {1}\n", i, forwardTable.Table[i].dwForwardType);
Console.Write("\tRoute[{0}] Proto: {1}\n", i, forwardTable.Table[i].dwForwardProto);
Console.Write("\tRoute[{0}] Age: {1}\n", i, forwardTable.Table[i].dwForwardAge);
Console.Write("\tRoute[{0}] Metric1: {1}\n", i, forwardTable.Table[i].dwForwardMetric1);
}
}
public static void RoutePrint()
{
List<Ip4RouteEntry> routeTable = GetRouteTable();
RoutePrint(routeTable);
}
public static void RoutePrint(List<Ip4RouteEntry> routeTable)
{
Console.WriteLine("Route Count: {0}", routeTable.Count);
Console.WriteLine("{0,18} {1,18} {2,18} {3,5} {4,8} ", "DestinationIP", "NetMask", "Gateway", "IF", "Metric");
foreach (Ip4RouteEntry entry in routeTable)
{
Console.WriteLine("{0,18} {1,18} {2,18} {3,5} {4,8} ", entry.DestinationIP, entry.SubnetMask, entry.GatewayIP, entry.InterfaceIndex, entry.Metric);
}
}
public static List<Ip4RouteEntry> GetRouteTable()
{
var fwdTable = IntPtr.Zero;
int size = 0;
var result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal(size);
result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
var forwardTable = ReadIPForwardTable(fwdTable);
Marshal.FreeHGlobal(fwdTable);
List<Ip4RouteEntry> routeTable = new List<Ip4RouteEntry>();
for (int i = 0; i < forwardTable.Table.Length; ++i)
{
Ip4RouteEntry entry = new Ip4RouteEntry();
entry.DestinationIP = new IPAddress((long)forwardTable.Table[i].dwForwardDest);
entry.SubnetMask = new IPAddress((long)forwardTable.Table[i].dwForwardMask);
entry.GatewayIP = new IPAddress((long)forwardTable.Table[i].dwForwardNextHop);
entry.InterfaceIndex = Convert.ToInt32(forwardTable.Table[i].dwForwardIfIndex);
entry.ForwardType = Convert.ToInt32(forwardTable.Table[i].dwForwardType);
entry.ForwardProtocol = Convert.ToInt32(forwardTable.Table[i].dwForwardProto);
entry.ForwardAge = Convert.ToInt32(forwardTable.Table[i].dwForwardAge);
entry.Metric = Convert.ToInt32(forwardTable.Table[i].dwForwardMetric1);
routeTable.Add(entry);
}
return routeTable;
}
The C# wrapper functions
public class Ip4RouteEntry
{
public IPAddress DestinationIP { get; set; }
public IPAddress SubnetMask { get; set; }
public IPAddress GatewayIP { get; set; }
public int InterfaceIndex { get; set; }
public int ForwardType { get; set; }
public int ForwardProtocol { get; set; }
public int ForwardAge { get; set; }
public int Metric { get; set; }
}
public static void RoutePrint()
{
List<Ip4RouteEntry> routeTable = GetRouteTable();
RoutePrint(routeTable);
}
public static void RoutePrint(List<Ip4RouteEntry> routeTable)
{
Console.WriteLine("Route Count: {0}", routeTable.Count);
Console.WriteLine("{0,18} {1,18} {2,18} {3,5} {4,8} ", "DestinationIP", "NetMask", "Gateway", "IF", "Metric");
foreach (Ip4RouteEntry entry in routeTable)
{
Console.WriteLine("{0,18} {1,18} {2,18} {3,5} {4,8} ", entry.DestinationIP, entry.SubnetMask, entry.GatewayIP, entry.InterfaceIndex, entry.Metric);
}
}
public static List<Ip4RouteEntry> GetRouteTable()
{
var fwdTable = IntPtr.Zero;
int size = 0;
var result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal(size);
result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
var forwardTable = ReadIPForwardTable(fwdTable);
Marshal.FreeHGlobal(fwdTable);
List<Ip4RouteEntry> routeTable = new List<Ip4RouteEntry>();
for (int i = 0; i < forwardTable.Table.Length; ++i)
{
Ip4RouteEntry entry = new Ip4RouteEntry();
entry.DestinationIP = new IPAddress((long)forwardTable.Table[i].dwForwardDest);
entry.SubnetMask = new IPAddress((long)forwardTable.Table[i].dwForwardMask);
entry.GatewayIP = new IPAddress((long)forwardTable.Table[i].dwForwardNextHop);
entry.InterfaceIndex = Convert.ToInt32(forwardTable.Table[i].dwForwardIfIndex);
entry.ForwardType = Convert.ToInt32(forwardTable.Table[i].dwForwardType);
entry.ForwardProtocol = Convert.ToInt32(forwardTable.Table[i].dwForwardProto);
entry.ForwardAge = Convert.ToInt32(forwardTable.Table[i].dwForwardAge);
entry.Metric = Convert.ToInt32(forwardTable.Table[i].dwForwardMetric1);
routeTable.Add(entry);
}
return routeTable;
}
public static bool RouteExists(string destinationIP)
{
List<Ip4RouteEntry> routeTable = Ip4RouteTable.GetRouteTable();
Ip4RouteEntry routeEntry = routeTable.Find(i => i.DestinationIP.ToString().Equals(destinationIP));
return (routeEntry != null);
}
public static List<Ip4RouteEntry> GetRouteEntry(string destinationIP)
{
List<Ip4RouteEntry> routeTable = Ip4RouteTable.GetRouteTable();
List<Ip4RouteEntry> routeMatches = routeTable.FindAll(i => i.DestinationIP.ToString().Equals(destinationIP));
return routeMatches;
}
public static List<Ip4RouteEntry> GetRouteEntry(string destinationIP, string mask)
{
List<Ip4RouteEntry> routeTable = Ip4RouteTable.GetRouteTable();
List<Ip4RouteEntry> routeMatches = routeTable.FindAll(i => i.DestinationIP.ToString().Equals(destinationIP) && i.SubnetMask.ToString().Equals(mask));
return routeMatches;
}
public static void CreateRoute(Ip4RouteEntry routeEntry)
{
var route = new PMIB_IPFORWARDROW
{
dwForwardDest = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.DestinationIP.ToString()).GetAddressBytes(), 0),
dwForwardMask = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.SubnetMask.ToString()).GetAddressBytes(), 0),
dwForwardNextHop = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.GatewayIP.ToString()).GetAddressBytes(), 0),
dwForwardMetric1 = 99,
dwForwardType = Convert.ToUInt32(3), //Default to 3
dwForwardProto = Convert.ToUInt32(3), //Default to 3
dwForwardAge = 0,
dwForwardIfIndex = Convert.ToUInt32(routeEntry.InterfaceIndex)
};
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PMIB_IPFORWARDROW)));
try
{
Marshal.StructureToPtr(route, ptr, false);
var status = NativeMethods.CreateIpForwardEntry(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
public static void CreateRoute(string destination, string mask, int interfaceIndex, int metric)
{
NetworkAdaptor adaptor = NicInterface.GetNetworkAdaptor(interfaceIndex);
var route = new PMIB_IPFORWARDROW
{
dwForwardDest = BitConverter.ToUInt32(IPAddress.Parse(destination).GetAddressBytes(), 0),
dwForwardMask = BitConverter.ToUInt32(IPAddress.Parse(mask).GetAddressBytes(), 0),
dwForwardNextHop = BitConverter.ToUInt32(IPAddress.Parse(adaptor.PrimaryGateway.ToString()).GetAddressBytes(), 0),
dwForwardMetric1 = Convert.ToUInt32(metric),
dwForwardType = Convert.ToUInt32(3), //Default to 3
dwForwardProto = Convert.ToUInt32(3), //Default to 3
dwForwardAge = 0,
dwForwardIfIndex = Convert.ToUInt32(interfaceIndex)
};
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PMIB_IPFORWARDROW)));
try
{
Marshal.StructureToPtr(route, ptr, false);
var status = NativeMethods.CreateIpForwardEntry(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
public static void DeleteRoute(Ip4RouteEntry routeEntry)
{
var route = new PMIB_IPFORWARDROW
{
dwForwardDest = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.DestinationIP.ToString()).GetAddressBytes(), 0),
dwForwardMask = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.SubnetMask.ToString()).GetAddressBytes(), 0),
dwForwardNextHop = BitConverter.ToUInt32(IPAddress.Parse(routeEntry.GatewayIP.ToString()).GetAddressBytes(), 0),
dwForwardMetric1 = 99,
dwForwardType = Convert.ToUInt32(3), //Default to 3
dwForwardProto = Convert.ToUInt32(3), //Default to 3
dwForwardAge = 0,
dwForwardIfIndex = Convert.ToUInt32(routeEntry.InterfaceIndex)
};
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PMIB_IPFORWARDROW)));
try
{
Marshal.StructureToPtr(route, ptr, false);
var status = NativeMethods.DeleteIpForwardEntry(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
public static void DeleteRoute(string destinationIP)
{
List<Ip4RouteEntry> routeMatches = Ip4RouteTable.GetRouteEntry(destinationIP);
if (routeMatches == null) return;
foreach (Ip4RouteEntry routeEntry in routeMatches)
{
DeleteRoute(routeEntry);
}
}
public static void DeleteRoute(string destinationIP, string mask)
{
List<Ip4RouteEntry> routeMatches = Ip4RouteTable.GetRouteEntry(destinationIP, mask);
if (routeMatches == null) return;
foreach (Ip4RouteEntry routeEntry in routeMatches)
{
DeleteRoute(routeEntry);
}
}
public static void DeleteRoute(int interfaceIndex)
{
var fwdTable = IntPtr.Zero;
int size = 0;
var result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal(size);
result = NativeMethods.GetIpForwardTable(fwdTable, ref size, true);
var forwardTable = ReadIPForwardTable(fwdTable);
Marshal.FreeHGlobal(fwdTable);
List<PMIB_IPFORWARDROW> filtered = new List<PMIB_IPFORWARDROW>();
for (int i = 0; i < forwardTable.Table.Length; ++i)
{
if (Convert.ToInt32(forwardTable.Table[i].dwForwardIfIndex).Equals(interfaceIndex))
{
filtered.Add(forwardTable.Table[i]);
}
}
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PMIB_IPFORWARDROW)));
try
{
foreach (PMIB_IPFORWARDROW routeEntry in filtered)
{
Marshal.StructureToPtr(routeEntry, ptr, false);
var status = NativeMethods.DeleteIpForwardEntry(ptr);
}
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
Related
In my codebase I use TorchSharp to train a regression model. When using the CPU everything works fine, just when using the GPU i get a KeyNotFoundException at the optimizer.step() method call.
I have extracted the code into an example program that can be used to reproduce the problem.
It seems to have to do something with the custom CancelOut module and its weight parameters. If I remove it from the Sequential module the exception does not happen.
I am wondering if I am doing something wrong or if this is a TorchSharp bug that only occurs with GPU training, since CPU training works fine.
Here is the code:
using TorchSharp;
using TorchSharp.Modules;
using TorchSharp.Utils;
using static TorchSharp.torch.nn;
var module = Sequential(
new CancelOut(10),
Linear(10, 1)
);
var x = Enumerable.Range(0, 100).Select(x => new float[10]).ToArray();
var y = new float[100];
var trainer = new RegressionTorchTrainer(module, x, y, device: torch.CUDA);
trainer.Train();
public class CancelOut : Module
{
private readonly Parameter weights;
public CancelOut(int size) : base(nameof(CancelOut))
{
weights = Parameter(torch.zeros(size) + 4);
RegisterComponents();
}
public override torch.Tensor forward(torch.Tensor x)
{
return (x * torch.sigmoid(weights));
}
}
public class RegressionTorchTrainer : IDisposable
{
private readonly torch.Device? device;
private readonly torch.nn.Module module;
private readonly torch.Tensor xt;
private readonly torch.Tensor yt;
private readonly torch.Tensor wt;
public RegressionTorchTrainer(torch.nn.Module module, float[][] x, float[] y, float[]? weight = null, torch.Device? device = null)
{
this.device = device;
this.module = module;
xt = torch.tensor(x.SelectMany(x => x).ToArray(), x.Length, x[0].Length, device: this.device);
yt = torch.tensor(y, device: this.device);
wt = weight != null ? torch.tensor(weight, device: this.device) : torch.ones(y.Length, device: device);
}
public void Train(int iterations = 100, int batchSize = 128, double learningRate = 0.001, torch.optim.Optimizer? optimizer = null, long? seed = null)
{
if (seed != null)
torch.random.manual_seed(seed.Value);
var disposeOptimizer = optimizer == null;
optimizer ??= torch.optim.SGD(module.parameters(), learningRate);
var criterion = torch.nn.functional.mse_loss(torch.nn.Reduction.None);
if (device != null)
module.to(device);
module.train();
for (int iter = 0; iter < iterations; iter++)
{
using var permutation = torch.randperm(xt.size(0), device: device);
for (int i = 0; i < xt.size(0); i += batchSize)
{
using var indices1 = torch.arange(i, Math.Min(i + batchSize, xt.size(0)), device: device);
using var indices2 = permutation.index_select(0, indices1);
using var xb = xt.index_select(0, indices2);
using var yb = yt.index_select(0, indices2);
using var wb = wt.index_select(0, indices2);
using var prediction = module.forward(xb).view(-1);
using var loss = criterion(prediction, yb);
using var wloss = loss * wb;
using var mloss = wloss.mean();
optimizer.zero_grad();
mloss.backward();
optimizer.step();
GC.Collect(0);
}
}
if (disposeOptimizer)
optimizer.Dispose();
}
public void Dispose()
{
xt.Dispose();
yt.Dispose();
GC.SuppressFinalize(this);
}
}
public class RegressionTorchModel : IDisposable
{
private readonly torch.Device? device;
private readonly torch.nn.Module module;
private readonly bool ownsModule;
public RegressionTorchModel(torch.nn.Module module, bool ownsModule = true, torch.Device? device = null)
{
this.device = device;
this.module = module;
this.ownsModule = ownsModule;
}
public float Predict(float[] x)
{
module.to(device).eval();
using var xt = torch.tensor(x, device: device);
using var prediction = module.forward(xt);
using var predictionCpu = prediction.cpu();
return predictionCpu.item<float>();
}
public float[] Predict(float[][] x)
{
module.to(device).eval();
using var xt = torch.tensor(x.SelectMany(x => x).ToArray(), x.Length, x[0].Length, device: device);
using var prediction = module.forward(xt);
using var predictionCpu = prediction.cpu();
using var accessor = new TensorAccessor<float>(predictionCpu);
return accessor.ToArray();
}
public static RegressionTorchModel Load(string filename, torch.Device? device = null)
=> new(torch.nn.Module.Load(filename), true, device);
public void Save(string filename)
=> module.Save(filename);
public void Dispose()
{
if (ownsModule)
module.Dispose();
}
}
I've seen ways to list all variables in a certain class, but is there a way to set their values?
I want a method I can call, and it can reset all variables' values to false / 0 , I know I can manually set those to false / 0, but any change to their values would mess up everything, and I'm just seeing if there's anything more dynamic / easy way that this could be done ?
Currently I'm doing the following:
// These are just some of the vars that are here.
Error = false;
double GUM = 0, MUM = 0;
decimal Mass = 0, GAcc = 0, Fg = 0, FµsRes = 0, FµkRes = 0, Fµs = FµsNS.Value, Fµk = FµkNS.Value;
As others have mentioned, you could use Reflection to set all the class fields to their default values:
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var myClass = new MyClass();
myClass.Error = true;
myClass.GUM = 1;
myClass.MUM = 2;
myClass.Mass = 3.5m;
myClass.GAcc = 4.5m;
myClass.Fg = 5.5m;
ResetFields(myClass);
// All fields are reseted
}
public static void ResetFields(object source)
{
foreach (var fieldInfo in source.GetType().GetFields() )
{
fieldInfo.SetValue(source, GetDefault(fieldInfo.FieldType) );
}
}
public static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
}
public class MyClass
{
public bool Error = false;
public double GUM = 0, MUM = 0;
public decimal Mass = 0, GAcc = 0, Fg = 0;
//etc etc
}
}
A better approach however, is to create a class to only hold the values and re-create it when needed:
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var myClass = new MyClass();
myClass.Variables = new MyVariables();
myClass.Variables.Error = true;
myClass.Variables.GUM = 1;
myClass.Variables.MUM = 2;
myClass.Variables.Mass = 3.5m;
myClass.Variables.GAcc = 4.5m;
myClass.Variables.Fg = 5.5m;
myClass.Variables = new MyVariables();
// All fields are reseted
}
}
public class MyVariables
{
public bool Error = false;
public double GUM = 0, MUM = 0;
public decimal Mass = 0, GAcc = 0, Fg = 0;
}
public class MyClass
{
public MyVariables Variables;
// etc etc
public int Xyz
{
get { return Variables.GUM + Variables.MUM; } // Use calculated properties
}
}
}
The GetDefault method is shown in this answer.
I have been trying to replicate the following C++ function in my C# application but I am getting an AccessViolationException at the time the method "ObjSearchObject2" is invoked. Pretty sure I am doing a lot of things wrong. The C++ function and the corresponding headers looks like this,
bool DocumentSearch(char *pFileId)
{
const int NUM_CONDITIONS = 1;
const int NUM_TYPE_DEFNS = 1;
ObjSearchObjectParm rSearchObject;
ObjSearchCondition rSearchCondition;
ObjObjectResults rSearchResults;
char *pTypeDefnIdArray[NUM_TYPE_DEFNS];
bool bReturnValue = false;
memset(&rSearchObject, 0, sizeof(ObjSearchObjectParm));
memset(&rSearchCondition, 0, sizeof(ObjSearchCondition));
memset(&rSearchResults, 0, sizeof(ObjObjectResults));
pTypeDefnIdArray[0] = "dotdA9";//Documents
rSearchObject.obj_defn_ids = pTypeDefnIdArray;
rSearchObject.obj_defn_count = NUM_TYPE_DEFNS;
rSearchObject.num_conditions = NUM_CONDITIONS;
rSearchObject.max_results = 5000;
rSearchObject.search_cond = &rSearchCondition;
rSearchCondition.field = "ancestor";
rSearchCondition.op = "is";
rSearchCondition.value = pFileId;
if (ObjSearchObject2(&rSearchObject, &rSearchResults))
{
printf("ERROR: ObjSearchObject2 returned: %s \n", ObjGetErrorMsg());
}
else
{
printf("INFO : Number of returned results = %d \n", rSearchResults.num_results);
if (rSearchResults.num_results > 0)
{
for (int iIndex = 0; iIndex < rSearchResults.num_results; iIndex++)
{
if (rSearchResults.object_handle[iIndex])
{
printf("INFO : Object Id returned: %s (name=%s, updated=%s, type=%s, state=%s) \n",
ObjGetObjectAttr(rSearchResults.object_handle[iIndex], "id_object"),
ObjGetObjectAttr(rSearchResults.object_handle[iIndex], "name"),
ObjGetObjectAttr(rSearchResults.object_handle[iIndex], "date_update"),
ObjGetObjectAttr(rSearchResults.object_handle[iIndex], "id_type_definition"),
ObjGetObjectAttr(rSearchResults.object_handle[iIndex], "num_state")
);
ObjFreeObjectHdl(rSearchResults.object_handle[iIndex]);
}
}
bReturnValue = true;
}
}
return bReturnValue;
}
int ObjSearchObject2(ObjSearchObjectParm *, ObjObjectResults *);
char * ObjGetObjectAttr(ObjApiObjectHdl objectHdl, char *attr_name);
char * ObjGetErrorMsg();
void ObjFreeObjectHdl(ObjApiObjectHdl objectHdl);
typedef struct _ObjSearchObjectParm {
int obj_defn_count; // mandatory
char **obj_defn_ids; // mandatory
char *text_server_alias; // optional.
char *query_string; // optional text search string
ObjApiBoolean include_deleted; // defaults to OBJAPI_FALSE
int max_results; // default = 200
int num_conditions; // mandatory
ObjSearchCondition *search_cond; // mandatory
ObjApiBoolean include_content; // mandatory for COMPLEX searches, translated to Y/N in API
ObjApiBoolean include_metadata; // mandatory for COMPLEX searches, translated to Y/N in API
} ObjSearchObjectParm;
enum ObjApiSearchOp
{
OBJAPI_MATCH_ALL=1,
OBJAPI_MATCH_ANY=2
};
enum ObjApiBoolean
{
OBJAPI_FALSE,
OBJAPI_TRUE
};
typedef struct _ObjSearchCondition {
ObjApiSearchOp boolop; // only for complex searches
char *join_relation; // only for complex searches
int num_opening_brackets; // only for complex searches
int num_closing_brackets; // only for complex searches
char *field;
char *op;
char *value;
} ObjSearchCondition;
typedef void* ObjApiObjectHdl;
typedef struct _ObjObjectResults {
ObjApiObjectHdl *object_handle;
int num_results;
} ObjObjectResults;
My take on this is as follows, (UPDATE: Code updated)
public class ObjectiveNativeAPI
{
private const string dllPath = #"objapi.dll";
public enum ObjApiBoolean
{
OBJAPI_FALSE,
OBJAPI_TRUE
};
public enum ObjApiSearchOp
{
OBJAPI_MATCH_ALL = 1,
OBJAPI_MATCH_ANY = 2
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ObjSearchObjectParm
{
public int obj_defn_count;
public string[] obj_defn_ids;
public string text_server_alias;
public string query_string;
public ObjApiBoolean include_deleted;
public int max_results;
public int num_conditions;
public IntPtr search_cond;
public ObjApiBoolean include_content;
public ObjApiBoolean include_metadata;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ObjSearchCondition
{
public ObjApiSearchOp boolop;
public string join_relation;
public int num_opening_brackets;
public int num_closing_brackets;
public string field;
public string op;
public string value;
}
[StructLayout(LayoutKind.Sequential)]
public struct ObjObjectResults
{
public IntPtr object_handle;
public int num_results;
}
[DllImport(dllPath, EntryPoint = "ObjSearchObject2")]
public static extern int ObjSearchObject2(ref ObjSearchObjectParm objSearchObjectParm, ref ObjObjectResults objObjectResults);
[DllImport(dllPath, EntryPoint = "ObjGetObjectAttr")]
public static extern string ObjGetObjectAttr(IntPtr object_handle, string attr_name);
[DllImport(dllPath, EntryPoint = "ObjFreeObjectHdl")]
public static extern void ObjFreeObjectHdl(IntPtr object_handle);
}
public void Run()
{
ObjectiveNativeAPI.ObjSearchObjectParm rSearchObject = new ObjectiveNativeAPI.ObjSearchObjectParm();
ObjectiveNativeAPI.ObjSearchCondition rSearchCondition = new ObjectiveNativeAPI.ObjSearchCondition();
ObjectiveNativeAPI.ObjObjectResults rSearchResults = new ObjectiveNativeAPI.ObjObjectResults();
rSearchCondition.field = "ancestor";
rSearchCondition.op = "is";
rSearchCondition.value = txtCotainerId.Text;
rSearchObject.obj_defn_ids = new[] {"dotdA9"};
rSearchObject.obj_defn_count = 1;
rSearchObject.num_conditions = 1;
rSearchObject.max_results = 5000;
IntPtr search_cond = Marshal.AllocCoTaskMem(Marshal.SizeOf(rSearchCondition));
Marshal.StructureToPtr(rSearchCondition, search_cond, false);
rSearchObject.search_cond = search_cond;
int result = ObjectiveNativeAPI.ObjSearchObject2(ref rSearchObject, ref rSearchResults);
MessageBox.Show(string.Format("FunctionResult: {0}", result));
Marshal.FreeCoTaskMem(search_cond);
}
I am a bit lost on this. I have managed to translate some other segments of this project but this is causing me grief. Any help around this would be appreciated.
I am running a remote application on w2008r2 and would like to retrieve the virtual ip it is running from.
Already tried cassia, but it gives me the client ip, not the ip handed out by the dhcp server.
Looking up the address through dns lookup up doesn't work either; it returns the servers IP address instead of the virtual IP address
I have setup Remote Desktop IP Virtualization per program as described here
Seems I get results I needed with WTS_INFO_CLASS --> WTSSessionAddressV4
together with solution from C# Get RDC/RDP and “Console” Session information ( which lacked the full enumeration on WTS_INFO_CLASS)
using System;
using PreEmptive.SoSAttributes;
using Cassia;
using System.Runtime.InteropServices;
using System.Net;
Namespace SomeNameSpace
{
internal static class SomeProgram
{
//Check if we have a virtual IP address
TerminalSessionInfo SessionInfo = TermServicesManager.GetSessionInfo(Dns.GetHostName(), _manager.CurrentSession.SessionId);
string LocalIPAddress = "127.0.0.1";
if (SessionInfo.ClientAddress != null)
{
LocalIPAddress = SessionInfo.ClientAddress;
}
MessageBox.Show(LocalIPAddress);
}
#region Get TerminalServer info
public class TermServicesManager
{
[DllImport("wtsapi32.dll")]
static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName);
[DllImport("wtsapi32.dll")]
static extern void WTSCloseServer(IntPtr hServer);
[DllImport("Wtsapi32.dll")]
public static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass,out System.IntPtr ppBuffer, out uint pBytesReturned);
[DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory(IntPtr pMemory);
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_ADDRESS
{
public uint AddressFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] Address;
}
public enum WTS_INFO_CLASS
{
InitialProgram = 0,
ApplicationName = 1,
WorkingDirectory = 2,
OEMId = 3,
SessionId = 4,
UserName = 5,
WinStationName = 6,
DomainName = 7,
ConnectState = 8,
ClientBuildNumber = 9,
ClientName = 10,
ClientDirectory = 11,
ClientProductId = 12,
ClientHardwareId = 13,
ClientAddress = 14,
ClientDisplay = 15,
ClientProtocolType = 16,
WTSIdleTime = 17,
WTSLogonTime = 18,
WTSIncomingBytes = 19,
WTSOutgoingBytes = 20,
WTSIncomingFrames = 21,
WTSOutgoingFrames = 22,
WTSClientInfo = 23,
WTSSessionInfo = 24,
WTSSessionInfoEx = 25,
WTSConfigInfo = 26,
WTSValidationInfo = 27,
WTSSessionAddressV4 = 28,
WTSIsRemoteSession = 29
}
private static IntPtr OpenServer(string Name)
{
IntPtr server = WTSOpenServer(Name);
return server;
}
private static void CloseServer(IntPtr ServerHandle)
{
WTSCloseServer(ServerHandle);
}
public static TerminalSessionInfo GetSessionInfo(string ServerName, int SessionId)
{
IntPtr server = IntPtr.Zero;
server = OpenServer(ServerName);
System.IntPtr buffer = IntPtr.Zero;
uint bytesReturned;
TerminalSessionInfo data = new TerminalSessionInfo();
try
{
bool worked = WTSQuerySessionInformation(server, SessionId,
WTS_INFO_CLASS.WTSSessionAddressV4, out buffer, out bytesReturned);
if (!worked)
return data;
WTS_SESSION_ADDRESS si = (WTS_SESSION_ADDRESS)Marshal.PtrToStructure((System.IntPtr)buffer, typeof(WTS_SESSION_ADDRESS));
data.ClientAddress = si.Address[2] + "." +si.Address[3] + "." + si.Address[4] + "." + si.Address[5];
}
finally
{
WTSFreeMemory(buffer);
buffer = IntPtr.Zero;
CloseServer(server);
}
return data;
}
}
public class TerminalSessionInfo
{
public string ClientAddress;
}
}
#endregion
You mean you want to get the local IP, right?
If yes, here is how to do it:
public static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
I'm looking for a way to send Sms throught MbnApi using :
http://msdn.microsoft.com/en-us/library/windows/desktop/dd323167(v=vs.85).aspx
IMbnSms interface. But it's not working at all.
I could not have a sample project to see how to do it. I'm coding on C# .Net
Thx
public class NaErrorHandling
{
public Dictionary<UInt32, string> Hresults { get;private set; }
public NaErrorHandling()
{
Hresults = new Dictionary<UInt32, string>();
Init();
}
private void Init()
{
Hresults.Add(0, "S_OK");
Hresults.Add(0x8054820a, "E_MBN_SIM_NOT_INSERTED");
Hresults.Add(0x80070057, "E_INVALIDARG");
Hresults.Add(0x80548202, "E_MBN_BAD_SIM");
Hresults.Add(0x80548210, "E_MBN_PIN_REQUIRED");
Hresults.Add(0x80548224, "E_MBN_SMS_MEMORY_FAILURE");
Hresults.Add(0x80548226, "E_MBN_SMS_UNKNOWN_SMSC_ADDRESS");
Hresults.Add(0x80548209, "E_MBN_SERVICE_NOT_ACTIVATED");
Hresults.Add(0x80548225, "E_MBN_SMS_NETWORK_TIMEOUT");
Hresults.Add(0x8054820d, "E_MBN_NOT_REGISTERED");
Hresults.Add(0x80548223, "E_MBN_SMS_LANG_NOT_SUPPORTED");
Hresults.Add(0x80548220, "E_MBN_SMS_ENCODING_NOT_SUPPORTED");
Hresults.Add(0x80548228, "E_MBN_SMS_OPERATION_NOT_ALLOWED");
Hresults.Add(0x80548229, "E_MBN_SMS_MEMORY_FULL");
Hresults.Add(0X80070015, "ERROR_NOT_READY");
Hresults.Add(1062, "ERROR_SERVICE_NOT_ACTIVE");
}
public string GetError(int error)
{
UInt32 uerror = (UInt32)error;
if (Hresults.ContainsKey(uerror))
return Hresults[uerror];
return "Error Not Know";
}
}
public class SmsResult : MbnApi.IMbnSmsEvents
{
public void OnSetSmsConfigurationComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
}
public void OnSmsConfigurationChange(MbnApi.IMbnSms sms)
{
}
public void OnSmsDeleteComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
}
public void OnSmsNewClass0Message(MbnApi.IMbnSms sms, MbnApi.MBN_SMS_FORMAT SmsFormat, object[] readMsgs)
{
}
public void OnSmsReadComplete(MbnApi.IMbnSms sms, MbnApi.MBN_SMS_FORMAT SmsFormat, object[] readMsgs, bool moreMsgs, uint requestID, int status)
{
string messageShow = String.Empty;
SMSPDULib.SMS rms= new SMSPDULib.SMS();
foreach (var msgReceived in readMsgs)
{
var msg = msgReceived as IMbnSmsReadMsgPdu;
messageShow += GetSms(msg.PduData) + "\n";
}
System.Windows.MessageBox.Show( messageShow);
}
private string GetSms(string pduSource)
{
SMSType smsType = SMSBase.GetSMSType(pduSource);
string message = string.Empty;
switch (smsType)
{
case SMSType.SMS:
SMS sms = new SMS();
SMS.Fetch(sms, ref pduSource);
message = sms.Message;
//Use instance of SMS class here
break;
case SMSType.StatusReport:
SMSStatusReport statusReport = new SMSStatusReport();
SMSStatusReport.Fetch(statusReport, ref pduSource);
//Use instance of SMSStatusReport class here
break;
}
return message;
}
public void OnSmsSendComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
NaErrorHandling handling = new NaErrorHandling();
var res = handling.GetError(status);
UInt32 uStatus = (UInt32)status;
}
public void OnSmsStatusChange(MbnApi.IMbnSms sms)
{
throw new NotImplementedException();
}
}
public void SendSms()
{
MbnConnectionManager mbnConnectionMgr = new MbnConnectionManager();
IMbnConnectionManager connMgr = (IMbnConnectionManager)mbnConnectionMgr;
try
{
IMbnConnection[] arrConn = connMgr.GetConnections();
if (arrConn != null)
{
String res = String.Empty;
foreach (var connection in arrConn)
{
res += String.Format("Connection ID : {0} | Interface Id : {1}\n", connection.ConnectionID, connection.InterfaceID);
}
//MessageBox.Show(res);
var conn = arrConn[0];
uint prId = 0;
//conn.Connect(MBN_CONNECTION_MODE.MBN_CONNECTION_MODE_PROFILE, "Bouygues Telecom", out prId);
MbnInterfaceManager mbnInterfaceMgr = new MbnInterfaceManager();
var mbnInterface = mbnInterfaceMgr as IMbnInterfaceManager;
var selectInterface = mbnInterface.GetInterface(conn.InterfaceID);
MBN_INTERFACE_CAPS caps = selectInterface.GetInterfaceCapability();
var theCap =caps.smsCaps;// (uint)MBN_SMS_CAPS.MBN_SMS_CAPS_PDU_SEND;
IConnectionPointContainer icpc;
icpc = (IConnectionPointContainer)mbnInterfaceMgr;
Guid IID_IMbnConnectionEvents = typeof(IMbnSmsEvents).GUID;
IConnectionPoint icp;
icpc.FindConnectionPoint(ref IID_IMbnConnectionEvents, out icp);
SmsResult connEvtsSink = new SmsResult();
uint cookie;
icp.Advise(connEvtsSink, out cookie);
var sms = selectInterface as IMbnSms;
string phoneDest = "";
string pdu = String.Empty;
byte[] size = new byte[5];
uint requestId = 456;
MBN_SMS_STATUS_INFO smsStatusInfo = new MBN_SMS_STATUS_INFO();
smsStatusInfo.flag = 10;
try
{
IMbnSmsConfiguration smsConfig = sms.GetSmsConfiguration();
sms.GetSmsStatus(out smsStatusInfo);
var wtf = smsStatusInfo;
string serviceDatacenter = smsConfig.ServiceCenterAddress;
CreatePduSms(null, phoneDest, "Hello", out pdu, out size);
//var res1 = SMSPDULib.SMS.GetBytes(pdu, 16);
var total = SMSPDULib.SMS.GetBytes(pdu);
byte wantedSize =(byte) total.Length;
CreatePduSms(serviceDatacenter, phoneDest, "Hello", out pdu, out size);
//var byteArray = StringToByteArray(pdu);
//var str = System.Text.Encoding.UTF7.GetString(byteArray);
sms.SmsSendPdu(pdu, wantedSize, out requestId);
//sms.SmsSendCdma(phoneDest, MBN_SMS_CDMA_ENCODING.MBN_SMS_CDMA_ENCODING_7BIT_ASCII, MBN_SMS_CDMA_LANG.MBN_SMS_CDMA_LANG_FRENCH, 2, GetBytes("Hi"), out requestId);
}
catch (Exception exp)
{
//MessageBox.Show("Cannot send Message : " + exp.Message);
}
}
}
catch (Exception e)
{
//MessageBox.Show(e.Message + e.StackTrace);
}
}
private void CreatePduSms(string servAddress, string phoneDest, string msg, out string pdu, out byte[] size)
{
SMSPDULib.SMS sms = new SMSPDULib.SMS();
sms.Direction = SMSPDULib.SMSDirection.Submited;
sms.PhoneNumber = "";
if (servAddress != null)
sms.ServiceCenterNumber = servAddress;
sms.ValidityPeriod = new TimeSpan(4, 0, 0, 0);
sms.Message = msg + DateTime.Now.ToString();
pdu = sms.Compose(SMSPDULib.SMS.SMSEncoding._7bit);
size = 0;
}