DeviceCapabilities generates error: data is invalid - c#

I want to get a printer's list of paper source, paper size, etc.
I slightly modified the codes from http://www.pinvoke.net/default.aspx/Enums/DeviceCapabilities.html?diff=y
The codes sometimes work, sometimes not.
The proplem is DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null) returns -1. the last error is "data is invalid"
Restart computer may not solve the problem. Once getting the problem, next time maybe OK maybe not.
So what is the problem here?
ArrayList arrBinName;
string sError = "";
GetBins("\\Lindy-PC.MyCpmpany.local\HP LaserJet 4000 Series PCL 5", "LPT1", out arrBinName, out sError);
public static bool GetBins(string DeviceName, string strPort, out ArrayList BinName, out string strError)
{
strError = "";
BinName = new ArrayList();
IntPtr pAddr = default(IntPtr);
int offset = 0;
int nRes = DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null); //Returns -1
if (nRes >= 0)
{
try
{
pAddr = Marshal.AllocHGlobal((int)nRes * 24);
nRes = DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, pAddr, (IntPtr)null);
if (nRes < 0)
{
strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "[" + DeviceName + ": " + strPort + ".DC_BINNAMES]";
return false;
}
offset = pAddr.ToInt32();
for (int i = 0; i < nRes; i++)
{
BinName.Add(Marshal.PtrToStringAnsi(new IntPtr(offset + i * 24)));
}
}
finally
{
Marshal.FreeHGlobal(pAddr);
}
}
else
strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "[" + DeviceName + ": " + strPort + ".DC_BINNAMES]";
return true;
}

As aggaton mentioned in his or her comment, DeviceCapabilities requires two calls in certain circumstances and retrieving bin names is one of them. You should first read the documentation for DeviceCapabilities.
Then go back and look at the sample code you used. You omitted a key step:
// BinNames
nRes = DeviceCapabilities(strDeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null);
pAddr = Marshal.AllocHGlobal((int)nRes * 24);
nRes = DeviceCapabilities(strDeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, pAddr, (IntPtr)null);
if(nRes < 0)
{
strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "["+ strDeviceName +": "+ strPort +"]";
return false;
}
Notice that there are three calls to DeviceCapabilities in that code. You need all three. (I think the code would be clearer by making each call a separate line of code but that's a style issue.) The doc for DeviceCapabilities plus the sample code above should get you back on track.

Related

System.IO.File.WriteAllText outputs gibberish C#

I have a simple program in C# that is supposed to output a text file containing a sequence of character separated by commas. I also output the resulting sequence on the console and it looks fine, however, the text file is full of weird character and no commas.
This is the output :
㔳㌬ⰵⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰳⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰴⰰⰰⰰⰳⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰲⰱⰱⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰲⰰⰳⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰱⰱⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰰⰰⰳⰰⰴⰴⰴⰰⰰⰰⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰰⰰⰰⰰⰴⰴⰴⰰⰰⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰱⰱⰱⰱⰱⰲⰰⰲⰱⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰰⰰⰰⰰⰰⰵⰰⰵⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰲⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰵⰰⰵⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰲⰰⰰⰵⰰⰰⰰⰰⰰⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰰⰱⰰⰰⰰⰰⰰⰰⰰⰰⰰⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰵⰰⰰⰰⰴⰴⰰⰰⰰⰰⰱⰱⰱⰱⰱⰱⰰⰰⰱⰱⰱⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰵⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰰⰰⰴⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰵⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰰⰰⰰⰰⰰⰵⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰰⰰⰵⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰳⰰⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰵⰰⰰⰰⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰰⰰⰰⰰⰰⰰⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴⰴ
This is what is supposed to be outputted
35,35,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,4,4,4,4,4,4,0,0,0,0,3,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,
4,0,0,0,0,4,0,0,0,3,0,4,4,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
4,4,0,0,0,0,4,4,4,0,0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,
0,4,4,4,0,0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,4,4,4,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,
0,0,0,0,0,2,1,1,1,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,2,0,3,1,0,
0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
0,0,0,0,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,
0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,3,0,4,4,4,0,
0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,4,4,4,0,0,4,4,4,0,
0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,0,2,1,1,4,4,0,0,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,4,4,0,0,4,4,4,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,5,0,5,0,1,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,
0,0,0,0,0,1,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,
1,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,2,0,0,5,0,0,0,0,0,0,1,4,4,0,0,
4,4,4,4,0,0,0,0,0,0,0,0,0,0,4,4,4,0,0,0,1,0,0,0,0,0,0,0,0,0,1,4,4,0,0,4,4,4,4,0,
0,0,0,0,0,5,0,0,0,4,4,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,4,4,0,0,4,4,4,4,0,0,0,5,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0,0,4,4,4,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,5,0,0,0,
0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,4,4,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,
4,4,4,0,0,3,0,4,4,4,4,4,4,4,0,0,0,0,0,5,0,0,0,4,4,4,4,0,0,4,4,4,4,4,4,4,4,0,0,0,
0,0,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,0,0,0,4,4,4,4,
4,4,4,4,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,
0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
As I said, what is supposed to be outputted is the string that is directly passed into File.WriteAllText.
Am I missing something ? I don't understand what i'm doing wrong. It seems to be working sometimes, but with other string it does not. I can find no relation between the sequences that works and those that do not.
Here is the whole code, it's a simple program that read a bitmap and output the sequence depending on the pixel. It's badly & quickly written but it's supposed to work, i see no reason it shouldn't.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(args[0]);
Bitmap Map = new Bitmap(args[0]);
var MapRGB = Map.Clone(new Rectangle(0, 0, Map.Width, Map.Height), PixelFormat.Format32bppRgb);
int height = Map.Height;
int widht = Map.Width;
string MapText = height.ToString() + "," + widht.ToString() + ",";
for (int h = 0; h < height; h++)
{
for (int w = 0; w < widht; w++)
{
Color currentPixel =
MapRGB.GetPixel(w ,h );
if (currentPixel.ToArgb() == Color.White.ToArgb())
{
MapText = MapText + "0,";
}
if (currentPixel.ToArgb() == Color.Black.ToArgb())
{
MapText = MapText + "1,";
}
if (currentPixel.ToArgb() == Color.Gray.ToArgb())
{
MapText = MapText + "2,";
}
if (currentPixel.ToArgb() == Color.Yellow.ToArgb())
{
MapText = MapText + "3,";
}
if (currentPixel.ToArgb() == Color.Green.ToArgb())
{
MapText = MapText + "4,";
}
if (currentPixel.ToArgb() == Color.Red.ToArgb())
{
MapText = MapText + "5,";
}
Console.Clear();
Console.WriteLine(args[0] + " WROKING " + w.ToString() + " OF " + widht.ToString() + " IN " + h.ToString() + " OF " + height.ToString());
}
}
Console.Clear();
Console.Write(MapText);
System.IO.File.WriteAllText(Environment.CurrentDirectory + "/Map.bwn", MapText);
Console.ReadKey();
}
}
Not absolutely sure but could be an encoding issue. Use the other overload File.WriteAllText(String, String, Encoding) which takes a encoding type as argument like
File.WriteAllText(filePath, stringMessage, Encoding.UTF8);

How to allocate more memory for a variable

I have created a c# program that takes a scan input, and then takes the information from the input. What I have been noticing is that for larger strings, my program for some reason splits the string into two parts (not in half), which screws up the way I get my information. My string has hexadecimal values in it as well.
For example, when I scan a code into my console, it reads the string
[)>065JUN1234567892300167Q205GT21L123 ABC06P123456787Q100PL7Q10PKQ1006P98356877Q100PL7Q5PKQ2006P235265437Q200PL7Q40PKQ5
but it splits that string into:
[)>065JUN1234567892300167Q205GT21L123 ABC06P123456787Q100PL7Q10PKQ1006P98356877Q100"
and
PL7Q5PKQ2006P235265437Q200PL7Q40PKQ5
Any idea how to fix this, or allocate more memory to my variable which reads the console for the input scan?
Here is my code, its kind of long.
static void Main(string[] args)
{
Console.WriteLine("Please enter the date and lane number");
Console.WriteLine("like so: ddmmyylanenumber.");
string lanenum = Console.ReadLine();
Console.WriteLine("When done scanning, please type");
Console.WriteLine("\"finish\" into the console.");
string scanInput;
do
{
Console.Write("Scan now:");
scanInput = Console.ReadLine();
//The number before "JUN" identifies the type of label it is.
int posOfJUN = scanInput.IndexOf("JUN");
//Finding the type of label
string typeOfLabel = scanInput.Substring(posOfJUN - 1, 1);
string label;
if (typeOfLabel == "5")
{
label = "mixed";
}
else if (typeOfLabel == "1")
{
label = "individual";
}
else
{
label = null;
}
switch (label)
{
case "individual":
partNumber = scanInput.Substring(8, 8);
int posOfQ1 = scanInput.IndexOf("Q");
int posOf1JUN = scanInput.IndexOf("1JUN");
//Quantity of the pack
total = scanInput.Substring(posOfQ1 + 1, posOf1JUN - posOfQ1 - 1 - 1);
//number of packs is 1 because individual
numOfPacks = "1";
dunsNumber = scanInput.Substring(posOf1JUN + 4, 9);
//used to find the duns and serial number
posOf20L = scanInput.IndexOf("20L");
posOf21L = scanInput.IndexOf("21L");
//Setting the serial number
if (posOf21L == -1 || posOf20L < posOf21L)
{
serialNumber = scanInput.Substring(posOf1JUN + 4, posOf20L - posOf1JUN - 4 - 1);
}
else if (posOf20L == -1 || posOf21L < posOf20L)
{
serialNumber = scanInput.Substring(posOf1JUN + 4, posOf21L - posOf1JUN - 4 - 2);
}
else
{
serialNumber = null; //else clause if serial number can't be created
Console.WriteLine(new ArgumentException("Error obtaining Serial Number"));
}
partObject part2 = new partObject(partNumber, total, numOfPacks);
newPacks = int.Parse(numOfPacks);
total = total.ToString();
newtotal = int.Parse(total);
part2.callSQL(partNumber, newtotal, newPacks, dunsNumber, serialNumber, lanenum);
break;
case "mixed":
posOfJUN = scanInput.IndexOf("JUN");
dunsNumber = scanInput.Substring(posOfJUN + 3, 9);
int posOf7Q = scanInput.IndexOf("7Q");
posOf20L = scanInput.IndexOf("20L");
posOf21L = scanInput.IndexOf("21L");
//Finding serial number
serialNumber = scanInput.Substring(posOfJUN + 3, posOf7Q - posOfJUN - 3);
//The following lines are to find how many different parts are in the mixed load.
posOfPK = scanInput.IndexOf("PK");
int PKTemp;
int parts = 1;
//Each time a "PK" is seen, it means there is another part so the count increments.
while (scanInput.IndexOf("PK", posOfPK + 1) != -1)
{
PKTemp = scanInput.IndexOf("PK", posOfPK + 1);
posOfPK = PKTemp;
parts++;
}
//Creating an array of size "parts"
int posOf06 = scanInput.IndexOf("06");
int temp06 = scanInput.IndexOf("06", posOf06 + 2);
posOf06 = temp06;
int indexOfP = scanInput.IndexOf("P", posOf06 + 1);
partNumber = scanInput.Substring(indexOfP + 1, 8);
posOfPK = scanInput.IndexOf("PK", indexOfP);
posOfPL = scanInput.IndexOf("PL", indexOfP);
posOf7Q1 = scanInput.IndexOf("7Q", indexOfP);
partObject[] arrayOfParts = new partObject[parts];
for (int i = 0; i < parts; i++)
{
//Finds the different values, creates an object and puts it into the array of parts
partNumber = scanInput.Substring(indexOfP + 1, 8);
total = scanInput.Substring(posOf7Q1 + 2, posOfPL - posOf7Q1 - 2);
numOfPacks = scanInput.Substring(posOfPL + 5, posOfPK - posOfPL - 5);
arrayOfParts[i] = new partObject(partNumber, total, numOfPacks);
//resetting the variables for the next iteration, so a new object can be created with the next part
posOf06 = scanInput.IndexOf("06", temp06 + 1);
indexOfP = scanInput.IndexOf("P", posOf06 + 1);
temp06 = posOf06;
posOfPK = scanInput.IndexOf("PK", indexOfP);
posOfPL = scanInput.IndexOf("PL", indexOfP);
posOf7Q1 = scanInput.IndexOf("7Q", indexOfP);
//putting each object into SQL
newtotal = int.Parse(total);
newPacks = int.Parse(numOfPacks);
serialNumber = serialNumber + "P" + (i + 1);
arrayOfParts[i].callSQL(partNumber, newtotal, newPacks, dunsNumber, serialNumber, lanenum);
}
break;
default:
break;
}
}
} while (scanInput != "finish");
}
The full string is never there right from the start of the code.
If you debug your program I think you will find that the string is all there.
I'm not sure why you think the string is split... a System.String can only hold one string. At some point are you getting a string[] ?
Place a breakpoint after this line scanInput = Console.ReadLine(); and in Visual Studio hover over scanInput, and it will show you the whole string.... or try just printing out the string to show that it is all there.
EDIT: If you're using hexadecimal, try looking up the hex values which cause the anomaly on the ascii table. Perhaps the hex value is resulting in a carriage return or newline.

Trying to delete a single value from array

I am trying to delete a value from a passed array at the selected index. Basically taking the selected index of a list box that displays the arrays and using it to delete an entry. For some reason nothing is deleted and stays the same when I run the program. I am programing in Visual Studio 2010 in C#
public double [] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
for (int i = selectedIndex; i < ary.GetUpperBound(0); i++)
{
redoneArray[i] = ary[i + 1];
}
//redoneArray[ary.GetUpperBound(0)] = 0;
return redoneArray;
}
Here is the delete button portion of code
private void btnDelete_Click(object sender, EventArgs e)
{
int selectedIndex;
if (this.lstClients.SelectedIndex <= 1)
{
return;
}
//else if ((this.lstClients.SelectedIndex - 2) < arrayIndex)
else
{
selectedIndex = this.lstClients.SelectedIndex - 2;
this.lstClients.Items.RemoveAt(this.lstClients.SelectedIndex);
lbSI.Text = (this.lstClients.SelectedIndex - 2).ToString();
redrawArray(mFirstNameArray, selectedIndex);
redrawArray(mLastNameArray, selectedIndex);
redrawArray(mAgeArray, selectedIndex);
redrawArray(mHeightArray, selectedIndex);
redrawArray(mStartWeightArray, selectedIndex);
redrawArray(mGoalWeightArray , selectedIndex);
redrawArray(mTotalWeeksArray, selectedIndex);
//arrayIndex += -1;
lstClients.Items.Clear();
loadListBox();
}
}
And here is my main code that loads it into the list
private void loadListBox()
{
string currentClient;
int lineNumber = 0;
string formattedName;
string strAvgBMI;
string strLowBMI;
string strHghBMI;
double dStartAvgBMI;
double dStartLowBMI;
double dStartHghBMI;
double dEndAvgBMI;
double dEndLowBMI;
double dEndHghBMI;
lstClients.Items.Add(" CLIENT NAME AGE HEIGHT(in) START WEIGHT START BMI GOAL WEIGHT GOAL BMI WEEKS");
lstClients.Items.Add("================= ===== =========== ============== =========== ============= ========== =========");
for (int index = 0; index < arrayIndex; index++)
{
if (mFirstNameArray[index] == null)
{
continue;
}
lineNumber++;
formattedName = mFirstNameArray[index];
formattedName += " ";
formattedName += mLastNameArray[index];
mStartBMI[index] = calcBMI(mHeightArray[index], mStartWeightArray[index]);
mEndBMI[index] = calcBMI(mHeightArray[index], mGoalWeightArray[index]);
currentClient = index.ToString() + " ";
currentClient += formattedName.PadRight(18) + " ";
currentClient += mAgeArray[index].ToString("##").PadLeft(4) + " ";
currentClient += mHeightArray[index].ToString("##.#0").PadRight(4) + " ";
currentClient += mStartWeightArray[index].ToString("###.0").PadRight(4) + " ";
currentClient += mStartBMI[index].ToString("##.#0").PadRight(4) + " ";
currentClient += mGoalWeightArray[index].ToString("###.0").PadRight(4) + " ";
currentClient += mEndBMI[index].ToString("###.#0").PadRight(4) + " ";
currentClient += mTotalWeeksArray[index].ToString("##").PadRight(4);
lstClients.Items.Add(currentClient);
}
dStartAvgBMI = sumAvg(mStartBMI, arrayIndex);
dStartHghBMI = maxArray(mStartBMI, arrayIndex);
dStartLowBMI = minArray(mStartBMI, arrayIndex);
dEndAvgBMI = sumAvg(mEndBMI, arrayIndex);
dEndHghBMI = maxArray(mEndBMI, arrayIndex);
dEndLowBMI = minArray(mEndBMI, arrayIndex);
strAvgBMI = "";
strHghBMI = "";
strLowBMI = "";
strAvgBMI = " Average: " + dStartAvgBMI.ToString("0#.#0") + " " + dEndAvgBMI.ToString("0#.#0");
strHghBMI = " High: " + dStartHghBMI.ToString("0#.#0") + " " + dEndHghBMI.ToString("0#.#0");
strLowBMI = " Low: " + dStartLowBMI.ToString("0#.#0") + " " + dEndLowBMI.ToString("0#.#0");
lstClients.Items.Add(strAvgBMI);
lstClients.Items.Add(strHghBMI);
lstClients.Items.Add(strLowBMI);
}
I'd strongly recommend using a List<double> instead, since it has a more graceful and efficient strategy for adding and removing items.
There is a significant problem with your algorithm, because you haven't actually used selectedIndex to filter out the 'deleted' item. I think it should look like this
public double[] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
int i = 0;
for (; i < selectedIndex; i++)
{
redoneArray[i] = ary[i];
}
for (; i < redoneArray.Length; i++)
{
redoneArray[i] = ary[i + 1];
}
return redoneArray;
}
Or even better:
public double[] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
Array.Copy(ary, redoneArray, selectedIndex);
Array.Copy(ary, selectedIndex + 1,
redoneArray, selectedIndex, redoneArray.Length - selectedIndex);
return redoneArray;
}
Update
The real problem, however, is that you're redrawArray method returns a new array rather than modifying the existing array. You'd have to use assign the result array back to your variables, like this:
mFirstNameArray = redrawArray(mFirstNameArray, selectedIndex);
mLastNameArray = redrawArray(mLastNameArray, selectedIndex);
mAgeArray = redrawArray(mAgeArray, selectedIndex);
mHeightArray = redrawArray(mHeightArray, selectedIndex);
mStartWeightArray = redrawArray(mStartWeightArray, selectedIndex);
mGoalWeightArray = redrawArray(mGoalWeightArray , selectedIndex);
mTotalWeeksArray = redrawArray(mTotalWeeksArray, selectedIndex);
You're starting from the selectedIndex.. but the new array doesn't contain any of the source array. This makes everything before the index 0. This can be solved with Array.Copy.
public static double[] redrawArray(double[] ary, int selectedIndex) {
double[] redoneArray = new double[ary.GetUpperBound(0)];
Array.Copy(ary, redoneArray, ary.GetUpperBound(0)); // copy the source into the destination minus one..
for (int i = selectedIndex; i < ary.GetUpperBound(0); i++) {
redoneArray[i] = ary[i + 1];
}
return redoneArray;
}
Example usage:
double[] arr = new double[] {2, 4, 6};
// remove first
arr = redrawArray(arr, 0); // {4, 6}
// remove second
arr = redrawArray(arr, 1); // {2, 6}
// etc..
If you want an array which you can delete things from, then its best to use something like List<double>, which will save you a lot of trouble.
Then to delete at a particular index, just call .RemoveAt(index)
If you still want to use Arrays externally, you can 'cheat' by using the array.ToList() function to get yourself a list, delete whatever it is you want, and then .toArray() it back. Yeah its quite inefficient, but I don't think what you're currently doing is that fast as it is.
public double[] RedrawArray(double[] ary, int selectedIndex)
{
var lst = new List<double>(ary);
lst.RemoveAt(selectedIndex);
return lst.ToArray();
}
With Linq I guess you can:
public double[] RedrawArray(double[] ary, int selectedIndex)
{
return ary.Where((d, i) => i!=selectedIndex).ToArray();
}
or:
public void RedrawArray(ref double[] ary, int selectedIndex)
{
ary = ary.Where((d, i) => i!=selectedIndex).ToArray();
}
depending on which syntax is most convenient when calling the method.
Note that in either case the array passed to this method should not be modified by other threads while the method is running. In the ref case, if a field or captured variable was passed, that variable must not be re-assigned by other threads.

How to get mx records for a dns name with System.Net.DNS? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Improve this question
Is there any built in method in the .NET library that will return all of the MX records for a given domain? I see how you get CNAMES, but not MX records.
Update 2018/5/23:
Check out MichaC's answer for a newer library that has .NET standard support.
Original Answer:
The ARSoft.Tools.Net library by Alexander Reinert seems to do the job pretty well.
It's available from NuGet:
PM> Install-Package ARSoft.Tools.Net
Import the namespace:
using ARSoft.Tools.Net.Dns;
Then making a synchronous lookup is as simple as:
var resolver = new DnsStubResolver();
var records = resolver.Resolve<MxRecord>("gmail.com", RecordType.Mx);
foreach (var record in records) {
Console.WriteLine(record.ExchangeDomainName?.ToString());
}
Which gives us the output:
gmail-smtp-in.l.google.com.
alt1.gmail-smtp-in.l.google.com.
alt2.gmail-smtp-in.l.google.com.
alt3.gmail-smtp-in.l.google.com.
alt4.gmail-smtp-in.l.google.com.
Underneath the hood, it looks like the library constructs the UDP (or TCP) packets necessary to send to the resolver, like you might expect. The library even has logic (invoked with DnsClient.Default) to discover which DNS server to query.
Full documentation can be found here.
Just roled my own library because there was nothing for .net core / xplat support... https://github.com/MichaCo/DnsClient.NET
It works pretty great and gives you dig like log messages if you want.
Simple to use
var lookup = new LookupClient();
var result = await lookup.QueryAsync("google.com", QueryType.ANY);
and works with custom servers running on any ports, multiple servers, etc...
see also DnsClient Website for more details
I spent all day figuring out how to send/receive dns requests and came up with this. Its a complete generic handler. You just have to set the dns server and pass in 'd' eg. my.website.com?d=itmanx.com
<%# WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
public class Handler : IHttpHandler
{
string dns = "dc1"; //change to your dns
string qtype = "15"; //A=1 MX=15
string domain = "";
int[] resp;
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
if (context.Request["t"] != null) qtype = context.Request["t"];
if (context.Request["d"] != null) domain = context.Request["d"];
if (string.IsNullOrEmpty(domain)) throw new Exception("Add ?d=<domain name> to url or post data");
Do(context);
}
catch (Exception ex)
{
string msg = ex.Message;
if (msg == "1") msg = "Malformed packet";
else if (msg == "5") msg = "Refused";
else if (msg == "131") msg = "No such name";
context.Response.Write("Error: " + msg);
}
}
public void Do(HttpContext context)
{
UdpClient udpc = new UdpClient(dns, 53);
// SEND REQUEST--------------------
List<byte> list = new List<byte>();
list.AddRange(new byte[] { 88, 89, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 });
string[] tmp = domain.Split('.');
foreach (string s in tmp)
{
list.Add(Convert.ToByte(s.Length));
char[] chars = s.ToCharArray();
foreach (char c in chars)
list.Add(Convert.ToByte(Convert.ToInt32(c)));
}
list.AddRange(new byte[] { 0, 0, Convert.ToByte(qtype), 0, 1 });
byte[] req = new byte[list.Count];
for (int i = 0; i < list.Count; i++) { req[i] = list[i]; }
udpc.Send(req, req.Length);
// RECEIVE RESPONSE--------------
IPEndPoint ep = null;
byte[] recv = udpc.Receive(ref ep);
udpc.Close();
resp = new int[recv.Length];
for (int i = 0; i < resp.Length; i++)
resp[i] = Convert.ToInt32(recv[i]);
int status = resp[3];
if (status != 128) throw new Exception(string.Format("{0}", status));
int answers = resp[7];
if (answers == 0) throw new Exception("No results");
int pos = domain.Length + 18;
if (qtype == "15") // MX record
{
while (answers > 0)
{
int preference = resp[pos + 13];
pos += 14; //offset
string str = GetMXRecord(pos, out pos);
context.Response.Write(string.Format("{0}: {1}\n", preference, str));
answers--;
}
}
else if (qtype == "1") // A record
{
while (answers > 0)
{
pos += 11; //offset
string str = GetARecord(ref pos);
context.Response.Write(string.Format("{0}\n", str));
answers--;
}
}
}
//------------------------------------------------------
private string GetARecord(ref int start)
{
StringBuilder sb = new StringBuilder();
int len = resp[start];
for (int i = start; i < start + len; i++)
{
if (sb.Length > 0) sb.Append(".");
sb.Append(resp[i + 1]);
}
start += len + 1;
return sb.ToString();
}
private string GetMXRecord(int start, out int pos)
{
StringBuilder sb = new StringBuilder();
int len = resp[start];
while (len > 0)
{
if (len != 192)
{
if (sb.Length > 0) sb.Append(".");
for (int i = start; i < start + len; i++)
sb.Append(Convert.ToChar(resp[i + 1]));
start += len + 1;
len = resp[start];
}
if (len == 192)
{
int newpos = resp[start + 1];
if (sb.Length > 0) sb.Append(".");
sb.Append(GetMXRecord(newpos, out newpos));
start++;
break;
}
}
pos = start + 1;
return sb.ToString();
}
//------------------------------------------------------
public bool IsReusable { get { return false; } }
}
My approach was to use nslookup.exe to retreive the MX record.
The solution is not as fancy as rewriting whole DNS or using a System DLL -> but it works, with a little amount of lines.
To get things right, this code >just works< it's not ressource efficient nor fast and has a lots of room for improvment (multiple hostnames, async, more usefull return value,adding the priority):
static List<string> GetMxRecords(string host){
ProcessStartInfo nslookup_config = new ProcessStartInfo("nslookup.exe");
nslookup_config.RedirectStandardInput = true;
nslookup_config.RedirectStandardOutput = true;
nslookup_config.RedirectStandardError = true;
nslookup_config.UseShellExecute = false;
var nslookup = Process.Start(nslookup_config);
nslookup.StandardInput.WriteLine("set q=mx");
nslookup.StandardInput.WriteLine(host);
nslookup.StandardInput.WriteLine("exit");
List<string> lines = new List<string>();
while (!nslookup.StandardOutput.EndOfStream)
{
string l = nslookup.StandardOutput.ReadLine();
if (l.Contains("internet address ="))
{
while (l.Contains("\t\t"))
{
l = l.Replace("\t\t", "\t");
}
lines.Add(l.Replace("\tinternet address = ","="));
}
}
nslookup.Close();
return lines;
}
Should be working international, since nslookup does not support any translation (I'm working on a German machine and I'm getting english output).
The result are strings like this:
alt4.gmail-smtp-in.l.google.com=74.125.28.27
alt2.gmail-smtp-in.l.google.com=74.125.200.27
alt1.gmail-smtp-in.l.google.com=209.85.233.26
gmail-smtp-in.l.google.com=66.102.1.27
alt3.gmail-smtp-in.l.google.com=108.177.97.27
The accepted answer doesn't work for .NET framework < 4.5, so would suggest that those of you who can't use ARSOFT.Tools can use DNDNs from https://dndns.codeplex.com
Given below is a console application that returns the MX record for a given domain modifying their examples.
using System;
using System.Net.Sockets;
using DnDns.Enums;
using DnDns.Query;
using DnDns.Records;
namespace DnDnsExamples
{
class Program
{
static void Main(string[] args)
{
DnsQueryRequest request3 = new DnsQueryRequest();
DnsQueryResponse response3 = request3.Resolve("gmail.com", NsType.MX, NsClass.INET, ProtocolType.Tcp);
OutputResults(response3);
Console.ReadLine();
}
private static void OutputResults(DnsQueryResponse response)
{
foreach (IDnsRecord record in response.Answers)
{
Console.WriteLine(record.Answer);
Console.WriteLine(" |--- RDATA Field Length: " + record.DnsHeader.DataLength);
Console.WriteLine(" |--- Name: " + record.DnsHeader.Name);
Console.WriteLine(" |--- NS Class: " + record.DnsHeader.NsClass);
Console.WriteLine(" |--- NS Type: " + record.DnsHeader.NsType);
Console.WriteLine(" |--- TTL: " + record.DnsHeader.TimeToLive);
Console.WriteLine();
}
}
}
}
Here is a Class I use to look up MX records only.
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections.Specialized;
namespace Mx.Dns
{
public class Query
{
//Build a DNS query buffer according to RFC 1035 4.1.1 e 4.1.2
private readonly int id;
private readonly int flags;
private readonly int QDcount;
private readonly int ANcount;
private readonly int NScount;
private readonly int ARcount;
private readonly string Qname;
private readonly int Qtype;
private readonly int Qclass;
public byte[] buf;
public Query(int ID, string query, int qtype)
{
//init vectors with given + default values
id = ID;
flags = 256;
QDcount = 1;
ANcount = 0;
NScount = 0;
ARcount = 0;
Qname = query;
Qtype = qtype;
Qclass = 1; //Internet = IN = 1
//build a buffer with formatted query data
//header information (16 bit padding
buf = new byte[12 + Qname.Length + 2 + 4];
buf[0] = (byte)(id / 256);
buf[1] = (byte)(id - (buf[0] * 256));
buf[2] = (byte)(flags / 256);
buf[3] = (byte)(flags - (buf[2] * 256));
buf[4] = (byte)(QDcount / 256);
buf[5] = (byte)(QDcount - (buf[4] * 256));
buf[6] = (byte)(ANcount / 256);
buf[7] = (byte)(ANcount - (buf[6] * 256));
buf[8] = (byte)(NScount / 256);
buf[9] = (byte)(NScount - (buf[8] * 256));
buf[10] = (byte)(ARcount / 256);
buf[11] = (byte)(ARcount - (buf[10] * 256));
//QNAME (RFC 1035 4.1.2)
//no padding
string[] s = Qname.Split('.');
int index = 12;
foreach (string str in s) {
buf[index] = (byte)str.Length;
index++;
byte[] buf1 = Encoding.ASCII.GetBytes(str);
buf1.CopyTo(buf, index);
index += buf1.Length;
}
//add root domain label (chr(0))
buf[index] = 0;
//add Qtype and Qclass (16 bit values)
index = buf.Length - 4;
buf[index] = (byte)(Qtype / 256);
buf[index + 1] = (byte)(Qtype - (buf[index] * 256));
buf[index + 2] = (byte)(Qclass / 256);
buf[index + 3] = (byte)(Qclass - (buf[index + 2] * 256));
}
}
public class C_DNSquery
{
public StringCollection result = new StringCollection();
public int Error = 0;
public string ErrorTxt = "undefined text";
public bool Done = false;
public UdpClient udpClient;
private string DNS;
private string Query;
private int Qtype;
public bool IS_BLACKLIST_QUERY = false;
public C_DNSquery(string IPorDNSname, string query, int type)
{
DNS = IPorDNSname;
Query = query;
Qtype = type;
}
public void doTheJob()
{
//check if provided DNS contains an IP address or a name
IPAddress ipDNS;
IPHostEntry he;
try {
//try to parse an IPaddress
ipDNS = IPAddress.Parse(DNS);
} catch (FormatException ) {
// Console.WriteLine(e);
//format error, probably is a FQname, try to resolve it
try {
//try to resolve the hostname
he = Dns.GetHostEntry(DNS);
} catch {
//Error, invalid server name or address
Error = 98;
ErrorTxt = "Invalid server name:" + DNS;
Done = true;
return;
}
//OK, get the first server address
ipDNS = he.AddressList[0];
}
//Query the DNS server
//our current thread ID is used to match the reply with this process
Query myQuery = new Query(System.Threading.Thread.CurrentThread.ManagedThreadId, Query, Qtype);
//data buffer for query return value
Byte[] recBuf;
//use UDP protocol to connect
udpClient = new UdpClient();
do {
try {
//connect to given nameserver, port 53 (DNS)
udpClient.Connect(DNS, 53);
//send query
udpClient.Send(myQuery.buf, myQuery.buf.Length);
//IPEndPoint object allow us to read datagrams..
//..selecting only packet coming from our nameserver and port
IPEndPoint RemoteIpEndPoint = new IPEndPoint(ipDNS, 53);
//Blocks until a message returns on this socket from a remote host.
recBuf = udpClient.Receive(ref RemoteIpEndPoint);
udpClient.Close();
} catch (Exception e) {
//connection error, probably a wrong server address
udpClient.Close();
Error = 99;
ErrorTxt = e.Message + "(server:" + DNS + ")";
Done = true;
return;
}
//repeat until we get the reply with our threadID
} while (System.Threading.Thread.CurrentThread.ManagedThreadId != ((recBuf[0] * 256) + recBuf[1]));
//Check the DNS reply
//check if bit QR (Query response) is set
if (recBuf[2] < 128) {
//response byte not set (probably a malformed packet)
Error = 2;
ErrorTxt = "Query response bit not set";
Done = true;
return;
}
//check if RCODE field is 0
if ((recBuf[3] & 15) > 0) {
//DNS server error, invalid reply
switch (recBuf[3] & 15) {
case 1:
Error = 31;
ErrorTxt = "Format error. The nameserver was unable to interpret the query";
break;
case 2:
Error = 32;
ErrorTxt = "Server failure. The nameserver was unable to process the query.";
break;
case 3:
Error = 33;
ErrorTxt = "Name error. Check provided domain name!!";
break;
case 4:
Error = 34;
ErrorTxt = "Not implemented. The name server does not support the requested query";
break;
case 5:
Error = 35;
ErrorTxt = "Refused. The name server refuses to reply for policy reasons";
break;
default:
Error = 36;
ErrorTxt = "Unknown. The name server error code was: " + Convert.ToString((recBuf[3] & 15));
break;
}
Done = true;
return;
}
//OK, now we should have valid header fields
int QDcnt, ANcnt, NScnt, ARcnt;
int index;
QDcnt = (recBuf[4] * 256) + recBuf[5];
ANcnt = (recBuf[6] * 256) + recBuf[7];
NScnt = (recBuf[8] * 256) + recBuf[9];
ARcnt = (recBuf[10] * 256) + recBuf[11];
index = 12;
//sometimes there are no erros but blank reply... ANcnt == 0...
if (ANcnt == 0) { // if blackhole list query, means no spammer !!//if ((ANcnt == 0) & (IS_BLACKLIST_QUERY == false))
//error blank reply, return an empty array
Error = 4;
ErrorTxt = "Empty string array";
Done = true;
return;
}
//Decode received information
string s1;
// START TEST
s1 = Encoding.ASCII.GetString(recBuf, 0, recBuf.Length);
// END TEST
if (QDcnt > 0) {
//we are not really interested to this string, just parse and skip
s1 = "";
index = parseString(recBuf, index, out s1);
index += 4; //skip root domain, Qtype and QClass values... unuseful in this contest
}
if (IS_BLACKLIST_QUERY) {
// get the answers, normally one !
// int the four last bytes there is the ip address
Error = 0;
int Last_Position = recBuf.Length - 1;
result.Add(recBuf[Last_Position - 3].ToString() + "." + recBuf[Last_Position - 2].ToString() + "." + recBuf[Last_Position - 1].ToString() + "." + recBuf[Last_Position].ToString());
Done = true;
return;
}
int count = 0;
//get all answers
while (count < ANcnt) {
s1 = "";
index = parseString(recBuf, index, out s1);
//Qtype
int QType = (recBuf[index] * 256) + recBuf[index + 1];
index += 2;
s1 += "," + QType.ToString();
//QClass
int QClass = (recBuf[index] * 256) + recBuf[index + 1];
index += 2;
s1 += "," + QClass.ToString();
//TTL (Time to live)
uint TTL = (recBuf[index] * 16777216u) + (recBuf[index + 1] * 65536u) + (recBuf[index + 2] * 256u) + recBuf[index + 3];
index += 4;
s1 += "," + TTL.ToString();
int blocklen = (recBuf[index] * 256) + recBuf[index + 1];
index += 2;
if (QType == 15) {
int MXprio = (recBuf[index] * 256) + recBuf[index + 1];
index += 2;
s1 += "," + MXprio.ToString();
}
string s2;
index = parseString(recBuf, index, out s2);
s1 += "," + s2;
result.Add(s1);
count++;
}
Error = 0;
Done = true;
}
private int parseString(byte[] buf, int i, out string s)
{
int len;
s = "";
bool end = false;
while (!end) {
if (buf[i] == 192) {
//next byte is a pointer to the string, get it..
i++;
s += getString(buf, buf[i]);
i++;
end = true;
} else {
//next byte is the string length
len = buf[i];
i++;
//get the string
s += Encoding.ASCII.GetString(buf, i, len);
i += len;
//check for the null terminator
if (buf[i] != 0) {
//not null, add a point to the name
s += ".";
} else {
//null char..the string is complete, exit
end = true;
i++;
}
}
}
return i;
}
private string getString(byte[] buf, int i)
{
string s = "";
int len;
bool end = false;
while (!end) {
len = buf[i];
i++;
s += Encoding.ASCII.GetString(buf, i, len);
i += len;
if (buf[i] == 192) {
i++;
s += "." + getString(buf, buf[i]);
return s;
}
if (buf[i] != 0) {
s += ".";
} else {
end = true;
}
}
return s;
}
}
}
Here is how you use it.
/// <summary>
/// Get the MX from the domain address.
/// </summary>
public static string getMXrecord(string domain)
{
domain = domain.Substring(domain.IndexOf('#') + 1);
string LocalDNS = GetDnsAdress().ToString();
Console.WriteLine("domain: " + domain);
// resolv the authoritative domain (type=2)
C_DNSquery DnsQry = new C_DNSquery(LocalDNS, domain, 2);
Thread t1 = new Thread(new ThreadStart(DnsQry.doTheJob));
t1.Start();
int timeout = 20;
while ((timeout > 0) & (!DnsQry.Done)) {
Thread.Sleep(100);
timeout--;
}
if (timeout == 0) {
if (DnsQry.udpClient != null) {
DnsQry.udpClient.Close();
}
t1.Abort();
DnsQry.Error = 100;
}
string[] ns1;
string MyNs = "";
if (DnsQry.Error == 0) {
ns1 = DnsQry.result[0].Split(',');
MyNs = ns1[4];
t1.Abort();
} else {
t1.Abort();
MyNs = LocalDNS;
}
// Resolve MX (type = 15)
DnsQry = new C_DNSquery(MyNs, domain, 15);
Thread t2 = new Thread(new ThreadStart(DnsQry.doTheJob));
t2.Start();
timeout = 20;
string TTL = "";
string MXName = "";
Int32 preference = 9910000;
while ((timeout > 0) & (!DnsQry.Done)) {
Thread.Sleep(100);
timeout--;
}
if (timeout == 0) {
if (DnsQry.udpClient != null) {
DnsQry.udpClient.Close();
}
t2.Abort();
DnsQry.Error = 100;
}
if (DnsQry.Error == 0) {
if (DnsQry.result.Count == 1) {
string[] ns2 = DnsQry.result[0].Split(',');
MXName = ns2[5];
TTL = ns2[3];
preference = Int32.Parse(ns2[4]);
Console.WriteLine("domaine: {0} MX: {1} time: {2} pref: {3} ttl: {4}", domain.Substring(domain.IndexOf('#') + 1), MXName,
DateTime.Now, preference, TTL);
} else {
for (int indns = 0; indns <= DnsQry.result.Count - 1; indns++) {
string[] ns2 = DnsQry.result[indns].Split(',');
if (Int32.Parse(ns2[4]) < preference) {
MXName = ns2[5];
TTL = ns2[3];
preference = Int32.Parse(ns2[4]);
Console.WriteLine("domain: {0} MX: {1} time: {2} pref: {3} ttl: {4}", domain.Substring(domain.IndexOf('#') + 1), MXName,
DateTime.Now, preference, TTL);
}
}
}
}
return MXName;
}
I wrote a simply URL for that means
https://devselz.com/social/sign/buttons/dashboard/default.aspx?a=ciee&email=emailaddresstocheckifexistsornot#anydomain.com
Do not abuse
Return 1 if email exists or may exist, 0 if not
Works great in order to check:
gmail and gmail pro (domains not #gmail) accounts.
hotmail
For others like yahoo always returns 1
You can use this open source library to do almost any kind of query you would usually need.
Usage:
DnsClient dnsClient = new DnsClient();
string mxDomain = dnsClient.ResolveMX("example.com");
string mxDomainIP = dnsClient.ResolveMX("example.com", true);
string mxDomainIPv6 = dnsClient.ResolveMX("example.com", true, true);

HttpParsing for hypertext

I am in process of getting all hierarchical links from a given link and validating them;
This is the code I wrote. But I am not feeling it as efficient.
Reasons are:
1.For the non unique links which open same page, code is getting sub-links again and again
2.Is the code getting all links?
3.Is it making valid URLs from the sub-links it derived?
4.May be some other reasons about which I have no idea.
Please suggest me how to make this piece of code efficient .
Thank you.
class Program
{
public static ArrayList sublink = new ArrayList();
public static ArrayList subtitle = new ArrayList();
public static int ini = 0, len_o, len_n, counter = 0;
static void Main(string[] args)
{
// Address of URL
string URL = "http://www.techonthenet.com/";
sublink.Add(URL);
l:
len_o = sublink.Count; len_o);
Console.WriteLine("-------------Level:" + counter++);
for (int i = ini; i < len_o; i++) test(sublink[i].ToString());
len_n = sublink.Count;
if (len_o < len_n) { ini = len_o; goto l; }
Console.ReadKey();
}
//method to get the sub-links
public static void test(string URL)
{
try
{
// Get HTML data
WebClient client = new WebClient();
Stream data = client.OpenRead(URL);
StreamReader reader = new StreamReader(data);
string str = "", htmldata = "", temp;
int n1, n2;
str = reader.ReadLine();
while (str != null)
{
htmldata += str;
str = reader.ReadLine();
}
data.Close();
for (int i = 0; i < htmldata.Length - 5; i++)
{
if (htmldata.Substring(i, 5) == "href=")
{
n1 = htmldata.Substring(i + 6, htmldata.Length - (i + 6)).IndexOf("\"");
temp = htmldata.Substring(i + 6, n1);
if (temp.Length > 4 && temp.Substring(0, 4) != "http")
{
if(temp.Substring(0,1)!="/")
temp=URL.Substring(0,URL.IndexOf(".com/")+5)+temp;
else temp = URL.Substring(0, URL.IndexOf(".com/") + 5) + temp.Remove(0,1);
}
if (temp.Length < 4) temp = URL.Substring(0, URL.IndexOf(".com/") + 5) + temp;
sublink.Add(temp);
n2 = htmldata.Substring(i + n1 + 1, htmldata.Length - (i + n1 + 1)).IndexOf("<");
subtitle.Add(htmldata.Substring(i + 6 + n1 + 2, n2 - 7));
i += temp.Length + htmldata.Substring(i + 6 + n1 + 2, n2 - 7).Length;
}
}
for (int i = len_n; i < sublink.Count; i++) Console.WriteLine(i + "--> " + sublink[i]);
}
catch (WebException exp)
{
Console.WriteLine("URL Could not be Resolved" + URL);
Console.WriteLine(exp.Message, "Exception");
}
}
}
Why not using regular expressions? They are easier to read, debug and mantain.
Also check out the Uri class. It has a couple of useful helpers (e.g. for base-relative url manipulation).
Also consider using an html/xml parser. There already was a discussion here.
Parsing html as plain text (i.e. with regular expressions) seems to be easy at first, but it may soon become painful to add new features to your parser.

Categories